/* * This is the source code of Telegram for Android v. 5.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * * Copyright Nikolai Kudashov, 2013-2018. */ package org.telegram.ui; import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.DatePickerDialog; import android.app.Dialog; import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Matrix; import android.graphics.Outline; 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.RectF; import android.graphics.Shader; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.os.Vibrator; import android.provider.MediaStore; import android.text.Layout; import android.text.Spannable; 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.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.URLSpan; import android.util.Property; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.Menu; import android.view.MotionEvent; import android.view.TextureView; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Space; import android.widget.TextView; import android.widget.Toast; import androidx.collection.LongSparseArray; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.core.graphics.ColorUtils; import androidx.exifinterface.media.ExifInterface; import androidx.recyclerview.widget.ChatListItemAnimator; import androidx.recyclerview.widget.GridLayoutManagerFixed; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScrollerCustom; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.zxing.common.detector.MathUtils; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.EmojiData; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ForwardingMessagesParams; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LanguageDetector; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; 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.NotificationsController; import org.telegram.messenger.R; import org.telegram.messenger.SecretChatHelper; 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.VideoEditedInfo; import org.telegram.messenger.browser.Browser; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.messenger.voip.VoIPService; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Adapters.MessagesSearchAdapter; import org.telegram.ui.Cells.BotHelpCell; import org.telegram.ui.Cells.BotSwitchCell; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatLoadingCell; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.ChatUnreadCell; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.MentionCell; import org.telegram.ui.Cells.StickerCell; import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AttachBotIntroTopView; import org.telegram.ui.Components.AutoDeletePopupWrapper; import org.telegram.ui.Components.BackButtonMenu; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BlurBehindDrawable; import org.telegram.ui.Components.BluredView; import org.telegram.ui.Components.BlurredFrameLayout; import org.telegram.ui.Components.BotCommandsMenuView; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ChatActivityEnterTopView; import org.telegram.ui.Components.ChatActivityEnterView; import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.ChatAttachAlertDocumentLayout; import org.telegram.ui.Components.ChatAvatarContainer; import org.telegram.ui.Components.ChatBigEmptyView; import org.telegram.ui.Components.ChatGreetingsView; import org.telegram.ui.Components.ChatNotificationsPopupWrapper; import org.telegram.ui.Components.ChatScrimPopupContainerLayout; import org.telegram.ui.Components.ChatThemeBottomSheet; import org.telegram.ui.Components.ChecksHintView; import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.ClippingImageView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CounterView; import org.telegram.ui.Components.CrossfadeDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EditTextCaption; import org.telegram.ui.Components.EmbedBottomSheet; import org.telegram.ui.Components.EmojiPacksAlert; import org.telegram.ui.Components.EmojiView; import org.telegram.ui.Components.ExtendedGridLayoutManager; import org.telegram.ui.Components.FireworksOverlay; import org.telegram.ui.Components.ForwardingPreviewView; import org.telegram.ui.Components.FragmentContextView; import org.telegram.ui.Components.GigagroupConvertAlert; import org.telegram.ui.Components.HideViewAfterAnimation; import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.ImportingAlert; import org.telegram.ui.Components.InstantCameraView; import org.telegram.ui.Components.InviteMembersBottomSheet; import org.telegram.ui.Components.JoinGroupAlert; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MentionsContainerView; import org.telegram.ui.Components.MessageBackgroundDrawable; import org.telegram.ui.Components.MessageContainsEmojiButton; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.PhonebookShareAlert; import org.telegram.ui.Components.PinnedLineView; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.PollVotesAlert; import org.telegram.ui.Components.PopupSwipeBackLayout; import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.ReactedHeaderView; import org.telegram.ui.Components.ReactedUsersListView; import org.telegram.ui.Components.ReactionTabHolderView; import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.ReactionsContainerLayout; import org.telegram.ui.Components.RecyclerAnimationScrollHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ReportAlert; import org.telegram.ui.Components.SearchCounterView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SharedMediaLayout; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.StickersAlert; import org.telegram.ui.Components.SuggestEmojiView; import org.telegram.ui.Components.TextSelectionHint; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.ThemeEditorView; import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.Components.TranslateAlert; import org.telegram.ui.Components.TrendingStickersAlert; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.Components.URLSpanMono; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.URLSpanReplacement; import org.telegram.ui.Components.URLSpanUserMention; import org.telegram.ui.Components.UndoView; import org.telegram.ui.Components.ViewHelper; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.InputStream; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @SuppressWarnings("unchecked") public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, LocationActivity.LocationActivityDelegate, ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate { protected TLRPC.Chat currentChat; protected TLRPC.User currentUser; protected TLRPC.EncryptedChat currentEncryptedChat; private boolean userBlocked; private long chatInviterId; private ArrayList chatMessageCellsCache = new ArrayList<>(); private HashMap alreadyPlayedStickers = new HashMap<>(); private Dialog closeChatDialog; private boolean showCloseChatDialogLater; private FrameLayout progressView; private View progressView2; private FrameLayout bottomOverlay; protected ChatActivityEnterView chatActivityEnterView; private ChatActivityEnterTopView chatActivityEnterTopView; private int chatActivityEnterViewAnimateFromTop; private boolean chatActivityEnterViewAnimateBeforeSending; private View timeItem2; private ActionBarMenuItem attachItem; private ActionBarMenuItem headerItem; private ActionBarMenuItem editTextItem; private ActionBarMenuItem searchItem; private ActionBarMenuItem searchIconItem; private ActionBarMenuItem audioCallIconItem; private boolean searchItemVisible; private RadialProgressView progressBar; private ActionBarMenuSubItem addContactItem; private ActionBarMenuSubItem clearHistoryItem; private ClippingImageView animatingImageView; private RecyclerListView chatListView; private ChatListItemAnimator chatListItemAnimator; private GridLayoutManagerFixed chatLayoutManager; private ChatActivityAdapter chatAdapter; private UnreadCounterTextView bottomOverlayChatText; private ImageView bottomOverlayImage; private RadialProgressView bottomOverlayProgress; private AnimatorSet bottomOverlayAnimation; private BlurredFrameLayout bottomOverlayChat; private BlurredFrameLayout bottomMessagesActionContainer; private TextView forwardButton; private TextView replyButton; private FrameLayout emptyViewContainer; private ChatGreetingsView greetingsViewContainer; public SizeNotifierFrameLayout contentView; private ChatBigEmptyView bigEmptyView; private ArrayList actionModeViews = new ArrayList<>(); private ChatAvatarContainer avatarContainer; private TextView bottomOverlayText; private NumberTextView selectedMessagesCountTextView; private RecyclerListView.OnItemClickListener mentionsOnItemClickListener; private SuggestEmojiView suggestEmojiPanel; private ActionBarMenuSubItem muteItem; private View muteItemGap; private ChatNotificationsPopupWrapper chatNotificationsPopupWrapper; private float pagedownButtonEnterProgress; private float mentionsButtonEnterProgress; private float reactionsMentionButtonEnterProgress; private FrameLayout pagedownButton; private ImageView pagedownButtonImage; private boolean pagedownButtonShowedByScroll; private CounterView pagedownButtonCounter; private FrameLayout mentiondownButton; private SimpleTextView mentiondownButtonCounter; private ImageView mentiondownButtonImage; private int reactionsMentionCount; private FrameLayout reactionsMentiondownButton; private CounterView reactionsMentiondownButtonCounter; private ImageView reactionsMentiondownButtonImage; private BackupImageView replyImageView; private SimpleTextView replyNameTextView; private SimpleTextView replyObjectTextView; private SimpleTextView replyObjectHintTextView; private boolean showTapForForwardingOptionsHit; private Runnable tapForForwardingOptionsHitRunnable; private ImageView replyIconImageView; private ImageView replyCloseImageView; public MentionsContainerView mentionContainer; private AnimatorSet mentionListAnimation; public ChatAttachAlert chatAttachAlert; private BlurredFrameLayout topChatPanelView; private AnimatorSet reportSpamViewAnimator; private TextView addToContactsButton; private boolean addToContactsButtonArchive; private TextView reportSpamButton; private ImageView closeReportSpam; private TextView chatWithAdminTextView; private FragmentContextView fragmentContextView; private FragmentContextView fragmentLocationContextView; private View replyLineView; private TextView emptyView; private HintView gifHintTextView; private HintView mediaBanTooltip; private HintView searchAsListHint; private HintView scheduledOrNoSoundHint; private boolean searchAsListHintShown; private HintView fwdRestrictedTopHint; private HintView fwdRestrictedBottomHint; private HintView slowModeHint; private HintView pollHintView; private HintView timerHintView; private ChatMessageCell pollHintCell; private int pollHintX; private int pollHintY; private HintView voiceHintTextView; private HintView noSoundHintView; private HintView forwardHintView; private ChecksHintView checksHintView; private View emojiButtonRed; private BlurredFrameLayout pinnedMessageView; private BluredView blurredView; private PinnedLineView pinnedLineView; private boolean setPinnedTextTranslationX; private AnimatorSet pinnedMessageViewAnimator; private BackupImageView[] pinnedMessageImageView = new BackupImageView[2]; private TrackingWidthSimpleTextView[] pinnedNameTextView = new TrackingWidthSimpleTextView[2]; private SimpleTextView[] pinnedMessageTextView = new SimpleTextView[2]; private PinnedMessageButton[] pinnedMessageButton = new PinnedMessageButton[2]; private NumberTextView pinnedCounterTextView; private int pinnedCounterTextViewX; private AnimatorSet[] pinnedNextAnimation = new AnimatorSet[2]; private boolean pinnedMessageButtonShown = false; private ImageView closePinned; private RadialProgressView pinnedProgress; private ImageView pinnedListButton; private AnimatorSet pinnedListAnimator; private FrameLayout alertView; private Runnable hideAlertViewRunnable; private TextView alertNameTextView; private TextView alertTextView; private AnimatorSet alertViewAnimator; private BlurredFrameLayout searchContainer; private View searchAsListTogglerView; private ImageView searchCalendarButton; private ImageView searchUserButton; private ImageView searchUpButton; private ImageView searchDownButton; private SearchCounterView searchCountText; private ChatActionCell floatingDateView; private ChatActionCell infoTopView; private int hideDateDelay = 500; private InstantCameraView instantCameraView; private View overlayView; private boolean currentFloatingDateOnScreen; private boolean currentFloatingTopIsNotMessage; private AnimatorSet floatingDateAnimation; private boolean scrollingFloatingDate; private boolean scrollingChatListView; private boolean checkTextureViewPosition; private boolean searchingForUser; private TLRPC.User searchingUserMessages; private TLRPC.Chat searchingChatMessages; private UndoView undoView; private UndoView topUndoView; private Bulletin pinBulletin; private boolean showPinBulletin; private int pinBullerinTag; protected boolean openKeyboardOnAttachMenuClose; private Runnable unregisterFlagSecurePasscode; private Runnable unregisterFlagSecureNoforwards; private boolean isFullyVisible; private MessageObject hintMessageObject; private int hintMessageType; private RecyclerListView messagesSearchListView; private MessagesSearchAdapter messagesSearchAdapter; private AnimatorSet messagesSearchListViewAnimation; public static final int MODE_SCHEDULED = 1; public static final int MODE_PINNED = 2; private int chatMode; private int scheduledMessagesCount = -1; private int reportType = -1; private MessageObject threadMessageObject; private boolean threadMessageVisible = true; private ArrayList threadMessageObjects; private MessageObject replyMessageHeaderObject; private int threadMessageId; private int replyOriginalMessageId; private TLRPC.Chat replyOriginalChat; private boolean isComments; private boolean threadMessageAdded; private boolean scrollToThreadMessage; private int threadMaxInboxReadId; private int threadMaxOutboxReadId; private int replyMaxReadId; private Runnable delayedReadRunnable; private SparseArray pendingSendMessagesDict = new SparseArray<>(); private ArrayList pendingSendMessages = new ArrayList<>(); private int threadUnreadMessagesCount; public ArrayList animatingMessageObjects = new ArrayList<>(); private HashMap animatingDocuments = new HashMap<>(); private MessageObject needAnimateToMessage; private int scrollToPositionOnRecreate = -1; private int scrollToOffsetOnRecreate = 0; private ArrayList pollsToCheck = new ArrayList<>(10); private ArrayList reactionsToCheck = new ArrayList<>(10); private int editTextStart; private int editTextEnd; private Runnable checkPaddingsRunnable; private boolean wasManualScroll; private boolean fixPaddingsInLayout; private boolean globalIgnoreLayout; private int topViewWasVisible; private ArrayList pinnedMessageIds = new ArrayList<>(); private HashMap pinnedMessageObjects = new HashMap<>(); private SparseArray loadingPinnedMessages = new SparseArray<>(); private int currentPinnedMessageId; private int[] currentPinnedMessageIndex = new int[1]; private int forceNextPinnedMessageId; private boolean forceScrollToFirst; private int loadedPinnedMessagesCount; private int totalPinnedMessagesCount; private boolean loadingPinnedMessagesList; private boolean pinnedEndReached; private ValueAnimator pagedownButtonAnimation; private ValueAnimator mentiondownButtonAnimation; private ValueAnimator reactionsMentionButtonAnimation; private AnimatorSet replyButtonAnimation; private AnimatorSet editButtonAnimation; private AnimatorSet forwardButtonAnimation; private static int lastStableId = 10; private boolean openSearchKeyboard; private boolean waitingForReplyMessageLoad; private boolean ignoreAttachOnPause; private boolean allowStickersPanel; private boolean allowContextBotPanel; private boolean allowContextBotPanelSecond = true; private AnimatorSet runningAnimation; private int runningAnimationIndex = -1; private MessageObject selectedObjectToEditCaption; private MessageObject selectedObject; private MessageObject.GroupedMessages selectedObjectGroup; private ForwardingMessagesParams forwardingMessages; private CharSequence formwardingNameText; private MessageObject forwardingMessage; private MessageObject.GroupedMessages forwardingMessageGroup; private MessageObject replyingMessageObject; private int editingMessageObjectReqId; private MessageObject editingMessageObject; private boolean paused = true; private boolean pausedOnLastMessage; private boolean wasPaused; boolean firstOpen = true; private int replyImageSize; private int replyImageCacheType; private TLRPC.PhotoSize replyImageLocation; private TLRPC.PhotoSize replyImageThumbLocation; private TLObject replyImageLocationObject; private int pinnedImageSize; private int pinnedImageCacheType; private TLRPC.PhotoSize pinnedImageLocation; private TLRPC.PhotoSize pinnedImageThumbLocation; private TLObject pinnedImageLocationObject; private int linkSearchRequestId; private TLRPC.WebPage foundWebPage; private ArrayList foundUrls; private String pendingLinkSearchString; private Runnable pendingWebPageTimeoutRunnable; private Runnable waitingForCharaterEnterRunnable; private Runnable onChatMessagesLoaded; private TLRPC.ChatInvite chatInvite; private Runnable chatInviteRunnable; private boolean clearingHistory; public boolean openAnimationEnded; public boolean fragmentOpened; private long openAnimationStartTime; private boolean scrollToTopOnResume; private boolean forceScrollToTop; private boolean scrollToTopUnReadOnResume; private long dialog_id; private Long dialog_id_Long; private int lastLoadIndex = 1; private SparseArray[] selectedMessagesIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private SparseArray[] selectedMessagesCanCopyIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private SparseArray[] selectedMessagesCanStarIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private boolean hasUnfavedSelected; private int cantDeleteMessagesCount; private int cantForwardMessagesCount; private int canForwardMessagesCount; private int canEditMessagesCount; private int cantSaveMessagesCount; private int canSaveMusicCount; private int canSaveDocumentsCount; private ArrayList waitingForLoad = new ArrayList<>(); private boolean needRemovePreviousSameChatActivity = true; private int newUnreadMessageCount; private int prevSetUnreadCount = Integer.MIN_VALUE; private int newMentionsCount; private boolean hasAllMentionsLocal; private ArrayList animateSendingViews = new ArrayList<>(); private SparseArray[] messagesDict = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private SparseArray repliesMessagesDict = new SparseArray<>(); private SparseArray> replyMessageOwners = new SparseArray<>(); private HashMap> messagesByDays = new HashMap<>(); protected ArrayList messages = new ArrayList<>(); private SparseArray waitingForReplies = new SparseArray<>(); private LongSparseArray> polls = new LongSparseArray<>(); private LongSparseArray groupedMessagesMap = new LongSparseArray<>(); private int[] maxMessageId = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE}; private int[] minMessageId = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE}; private int[] maxDate = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE}; private int[] minDate = new int[2]; private boolean[] endReached = new boolean[2]; private boolean[] cacheEndReached = new boolean[2]; private boolean[] forwardEndReached = new boolean[]{true, true}; private boolean hideForwardEndReached; private boolean loading; private boolean firstLoading = true; private boolean chatWasReset; private boolean firstUnreadSent; private int loadsCount; private int last_message_id = 0; private long mergeDialogId; private boolean premiumInvoiceBot; private boolean showScrollToMessageError; private int startLoadFromMessageId; private int startLoadFromDate; private int startLoadFromMessageIdSaved; private int startLoadFromMessageOffset = Integer.MAX_VALUE; private int startFromVideoTimestamp = -1; private int startFromVideoMessageId; private boolean needSelectFromMessageId; private int returnToMessageId; private int returnToLoadIndex; private int createUnreadMessageAfterId; private boolean createUnreadMessageAfterIdLoading; private boolean loadingFromOldPosition; private float alertViewEnterProgress; private boolean first = true; private int first_unread_id; private boolean loadingForward; private MessageObject unreadMessageObject; private MessageObject scrollToMessage; private int highlightMessageId = Integer.MAX_VALUE; private int scrollToMessagePosition = -10000; private Runnable unselectRunnable; private String currentPicturePath; private ChatObject.Call groupCall; private boolean lastCallCheckFromServer; private boolean createGroupCall; protected TLRPC.ChatFull chatInfo; protected TLRPC.UserFull userInfo; private LongSparseArray botInfo = new LongSparseArray<>(); private String botUser; private long inlineReturn; private String voiceChatHash; private boolean livestream; private String attachMenuBotToOpen; private String attachMenuBotStartCommand; private MessageObject botButtons; private MessageObject botReplyButtons; private int botsCount; private boolean hasBotsCommands; private boolean hasBotWebView; private long chatEnterTime; private long chatLeaveTime; private boolean locationAlertShown; private String startVideoEdit; private FrameLayout videoPlayerContainer; private ChatMessageCell drawLaterRoundProgressCell; private AspectRatioFrameLayout aspectRatioFrameLayout; private TextureView videoTextureView; private boolean scrollToVideo; private Path aspectPath; private Paint aspectPaint; private Runnable destroyTextureViewRunnable = () -> { destroyTextureView(); }; private Paint scrimPaint; private Paint actionBarBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private float scrimPaintAlpha = 0f; private View scrimView; private float scrimViewAlpha = 1f; private String scrimViewReaction; private int popupAnimationIndex = -1; private AnimatorSet scrimAnimatorSet; public ActionBarPopupWindow scrimPopupWindow; private boolean scrimPopupWindowHideDimOnDismiss = true; private int scrimPopupX, scrimPopupY; private ActionBarMenuSubItem[] scrimPopupWindowItems; private ActionBarMenuSubItem menuDeleteItem; private Runnable updateDeleteItemRunnable = new Runnable() { @Override public void run() { if (selectedObject == null || menuDeleteItem == null) { return; } int remaining = Math.max(0, selectedObject.messageOwner.ttl_period - (getConnectionsManager().getCurrentTime() - selectedObject.messageOwner.date)); String ramainingStr; if (remaining < 24 * 60 * 60) { ramainingStr = AndroidUtilities.formatDuration(remaining, false); } else { ramainingStr = LocaleController.formatPluralString("Days", Math.round(remaining / (24 * 60 * 60.0f))); } menuDeleteItem.setSubtext(LocaleController.formatString("AutoDeleteIn", R.string.AutoDeleteIn, ramainingStr)); AndroidUtilities.runOnUIThread(updateDeleteItemRunnable, 1000); } }; private ChatActivityDelegate chatActivityDelegate; private RecyclerAnimationScrollHelper chatScrollHelper; private int postponedScrollMinMessageId; private int postponedScrollToLastMessageQueryIndex; private int postponedScrollMessageId; private boolean postponedScrollIsCanceled; private TextSelectionHelper.ChatListTextSelectionHelper textSelectionHelper; private ChatMessageCell slidingView; private boolean maybeStartTrackingSlidingView; private boolean startedTrackingSlidingView; private boolean canShowPagedownButton; private TextSelectionHint textSelectionHint; private boolean textSelectionHintWasShowed; private float lastTouchY; private ChatMessageCell dummyMessageCell; private FireworksOverlay fireworksOverlay; private boolean swipeBackEnabled = true; public static Pattern publicMsgUrlPattern; public static Pattern voiceChatUrlPattern; public static Pattern privateMsgUrlPattern; private boolean waitingForSendingMessageLoad; private ValueAnimator changeBoundAnimator; private Animator messageEditTextAnimator; private int distanceToPeer; private boolean openImport; private float chatListViewPaddingTop; private float chatListViewPaddingTopOnlyTopViews; private int chatListViewPaddingVisibleOffset; private int contentPaddingTop; private float contentPanTranslation; private float floatingDateViewOffset; private float topChatPanelViewOffset; private float pinnedMessageEnterOffset; private float topViewOffset; private TLRPC.Document preloadedGreetingsSticker; private boolean forceHistoryEmpty; private float bottomPanelTranslationY; private float bottomPanelTranslationYReverse; private boolean invalidateChatListViewTopPadding; private long activityResumeTime; private int transitionAnimationIndex; private int scrollAnimationIndex; private int scrollCallbackAnimationIndex; public boolean allowExpandPreviewByClick; private boolean showSearchAsIcon; private boolean showAudioCallAsIcon; public MessageEnterTransitionContainer messageEnterTransitionContainer; private float pullingDownOffset, pullingBottomOffset; private ChatPullingDownDrawable pullingDownDrawable; private Animator pullingDownBackAnimator; private boolean fromPullingDownTransition; private boolean toPullingDownTransition; private ChatActivity pullingDownAnimateToActivity; private float pullingDownAnimateProgress; private AnimatorSet fragmentTransition; private ChatActivity backToPreviousFragment; private Runnable fragmentTransitionRunnable = new Runnable() { @Override public void run() { if (fragmentTransition != null && !fragmentTransition.isRunning()) { fragmentTransition.start(); } } }; private boolean isPauseOnThemePreview; private ChatThemeBottomSheet chatThemeBottomSheet; public ThemeDelegate themeDelegate; private ChatActivityMemberRequestsDelegate pendingRequestsDelegate; private TLRPC.TL_channels_sendAsPeers sendAsPeersObj; private final static int OPTION_RETRY = 0; private final static int OPTION_DELETE = 1; private final static int OPTION_FORWARD = 2; private final static int OPTION_COPY = 3; private final static int OPTION_SAVE_TO_GALLERY = 4; private final static int OPTION_APPLY_LOCALIZATION_OR_THEME = 5; private final static int OPTION_SHARE = 6; private final static int OPTION_SAVE_TO_GALLERY2 = 7; private final static int OPTION_REPLY = 8; private final static int OPTION_ADD_TO_STICKERS_OR_MASKS = 9; private final static int OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC = 10; private final static int OPTION_ADD_TO_GIFS = 11; private final static int OPTION_EDIT = 12; private final static int OPTION_PIN = 13; private final static int OPTION_UNPIN = 14; private final static int OPTION_ADD_CONTACT = 15; private final static int OPTION_COPY_PHONE_NUMBER = 16; private final static int OPTION_CALL = 17; private final static int OPTION_CALL_AGAIN = 18; private final static int OPTION_RATE_CALL = 19; private final static int OPTION_ADD_STICKER_TO_FAVORITES = 20; private final static int OPTION_DELETE_STICKER_FROM_FAVORITES = 21; private final static int OPTION_COPY_LINK = 22; private final static int OPTION_REPORT_CHAT = 23; private final static int OPTION_CANCEL_SENDING = 24; private final static int OPTION_UNVOTE = 25; private final static int OPTION_STOP_POLL_OR_QUIZ = 26; private final static int OPTION_VIEW_REPLIES_OR_THREAD = 27; private final static int OPTION_STATISTICS = 28; private final static int OPTION_TRANSLATE = 29; private final static int OPTION_TRANSCRIBE = 30; private final static int OPTION_HIDE_SPONSORED_MESSAGE = 31; private final static int OPTION_SEND_NOW = 100; private final static int OPTION_EDIT_SCHEDULE_TIME = 102; private final static int[] allowedNotificationsDuringChatListAnimations = new int[]{ NotificationCenter.messagesRead, NotificationCenter.threadMessagesRead, NotificationCenter.commentsRead, NotificationCenter.messagesReadEncrypted, NotificationCenter.messagesReadContent, NotificationCenter.didLoadPinnedMessages, NotificationCenter.newDraftReceived, NotificationCenter.updateMentionsCount, NotificationCenter.didUpdateConnectionState, NotificationCenter.updateInterfaces, NotificationCenter.updateDefaultSendAsPeer, NotificationCenter.closeChats, NotificationCenter.chatInfoCantLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.didSetNewWallpapper, NotificationCenter.didApplyNewTheme }; private final DialogInterface.OnCancelListener postponedScrollCancelListener = dialog -> { postponedScrollIsCanceled = true; postponedScrollMessageId = 0; nextScrollToMessageId = 0; forceNextPinnedMessageId = 0; invalidateMessagesVisiblePart(); showPinnedProgress(false); }; private NotificationCenter.PostponeNotificationCallback postponeNotificationsWhileLoadingCallback = new NotificationCenter.PostponeNotificationCallback() { @Override public boolean needPostpone(int id, int currentAccount, Object[] args) { if (id == NotificationCenter.didReceiveNewMessages) { long did = (Long) args[0]; if (firstLoading && did == dialog_id) { return true; } } return false; } }; private int chatEmojiViewPadding; private int fixedKeyboardHeight = -1; private Runnable cancelFixedPositionRunnable; private boolean invalidateMessagesVisiblePart; private boolean scrollByTouch; int dialogFolderId; int dialogFilterId; boolean pulled = false; private static boolean replacingChatActivity = false; private PinchToZoomHelper pinchToZoomHelper; private EmojiAnimationsOverlay emojiAnimationsOverlay; public float drawingChatLisViewYoffset; public int blurredViewTopOffset; public int blurredViewBottomOffset; private ValueAnimator searchExpandAnimator; private float searchExpandProgress; public void deleteHistory(int dateSelectedStart, int dateSelectedEnd, boolean forAll) { chatAdapter.frozenMessages.clear(); for (int i = 0; i < messages.size(); i++) { MessageObject messageObject = messages.get(i); if (messageObject.messageOwner.date <= dateSelectedStart || messageObject.messageOwner.date >= dateSelectedEnd) { chatAdapter.frozenMessages.add(messageObject); } } if (chatListView != null) { chatListView.setEmptyView(null); } if (chatAdapter.frozenMessages.isEmpty()) { showProgressView(true); } chatAdapter.isFrozen = true; chatAdapter.notifyDataSetChanged(true); getUndoView().showWithAction(dialog_id, UndoView.ACTION_CLEAR_DATES, () -> { getMessagesController().deleteMessagesRange(dialog_id, ChatObject.isChannel(currentChat) ? dialog_id : 0, dateSelectedStart, dateSelectedEnd, forAll, () -> { chatAdapter.frozenMessages.clear(); chatAdapter.isFrozen = false; chatAdapter.notifyDataSetChanged(true); showProgressView(false); }); }, () -> { chatAdapter.frozenMessages.clear(); chatAdapter.isFrozen = false; chatAdapter.notifyDataSetChanged(true); showProgressView(false); }); } public void showHeaderItem(boolean show) { if (show) { if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } if (headerItem != null) { headerItem.setVisibility(View.GONE); } } else { if (attachItem != null) { attachItem.setVisibility(View.GONE); } if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } } } else { if (attachItem != null) { attachItem.setVisibility(View.GONE); } if (headerItem != null) { headerItem.setVisibility(View.GONE); } } } private interface ChatActivityDelegate { default void openReplyMessage(int mid) { } default void openSearch(String text) { } default void onUnpin(boolean all, boolean hide) { } default void onReport() { } } ForwardingPreviewView forwardingPreviewView; private class UnreadCounterTextView extends View { private int currentCounter; private String currentCounterString; private int textWidth; private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private RectF rect = new RectF(); private int circleWidth; private int rippleColor; private StaticLayout textLayout; private StaticLayout textLayoutOut; private int layoutTextWidth; private TextPaint layoutPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); Drawable selectableBackground; ValueAnimator replaceAnimator; float replaceProgress = 1f; boolean animatedFromBottom; int textColor; int panelBackgroundColor; int counterColor; CharSequence lastText; public UnreadCounterTextView(Context context) { super(context); textPaint.setTextSize(AndroidUtilities.dp(13)); textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); layoutPaint.setTextSize(AndroidUtilities.dp(15)); layoutPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); } public void setText(CharSequence text, boolean animatedFromBottom) { if (lastText == text) { return; } lastText = text; this.animatedFromBottom = animatedFromBottom; textLayoutOut = textLayout; layoutTextWidth = (int) Math.ceil(layoutPaint.measureText(text, 0, text.length())); textLayout = new StaticLayout(text, layoutPaint, layoutTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); setContentDescription(text); invalidate(); if (textLayoutOut != null) { if (replaceAnimator != null) { replaceAnimator.cancel(); } replaceProgress = 0; replaceAnimator = ValueAnimator.ofFloat(0,1f); replaceAnimator.addUpdateListener(animation -> { replaceProgress = (float) animation.getAnimatedValue(); invalidate(); }); replaceAnimator.setDuration(150); replaceAnimator.start(); } } public void setText(CharSequence text) { layoutTextWidth = (int) Math.ceil(layoutPaint.measureText(text, 0, text.length())); textLayout = new StaticLayout(text, layoutPaint, layoutTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); setContentDescription(text); invalidate(); } @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (selectableBackground != null) { selectableBackground.setState(getDrawableState()); } } @Override public boolean verifyDrawable(Drawable drawable) { if (selectableBackground != null) { return selectableBackground == drawable || super.verifyDrawable(drawable); } return super.verifyDrawable(drawable); } @Override public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (selectableBackground != null) { selectableBackground.jumpToCurrentState(); } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (textLayout != null) { int lineWidth = (int) Math.ceil(textLayout.getLineWidth(0)); int contentWidth; if (getMeasuredWidth() == ((View)getParent()).getMeasuredWidth()) { contentWidth = getMeasuredWidth() - AndroidUtilities.dp(96); } else { if (botInfo != null) { contentWidth = getMeasuredWidth(); } else { contentWidth = lineWidth + (circleWidth > 0 ? circleWidth + AndroidUtilities.dp(8) : 0); contentWidth += AndroidUtilities.dp(48); } } int x = (getMeasuredWidth() - contentWidth) / 2; rect.set( x, getMeasuredHeight() / 2f - contentWidth / 2f, x + contentWidth, getMeasuredHeight() / 2f + contentWidth / 2f ); if (!rect.contains(event.getX(), event.getY())) { setPressed(false); return false; } } } return super.onTouchEvent(event); } public void updateCounter() { int newCount; if (ChatObject.isChannel(currentChat) && !currentChat.megagroup && chatInfo != null && chatInfo.linked_chat_id != 0) { TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(-chatInfo.linked_chat_id); if (dialog != null) { newCount = dialog.unread_count; } else { newCount = 0; } } else { newCount = 0; } if (currentCounter != newCount) { currentCounter = newCount; if (currentCounter == 0) { currentCounterString = null; circleWidth = 0; } else { currentCounterString = AndroidUtilities.formatWholeNumber(currentCounter, 0); textWidth = (int) Math.ceil(textPaint.measureText(currentCounterString)); int newWidth = Math.max(AndroidUtilities.dp(20), AndroidUtilities.dp(12) + textWidth); if (circleWidth != newWidth) { circleWidth = newWidth; } } invalidate(); } } @Override protected void onDraw(Canvas canvas) { Layout layout = textLayout; int color = getThemedColor(isEnabled() ? Theme.key_chat_fieldOverlayText : Theme.key_windowBackgroundWhiteGrayText); if (textColor != color) { layoutPaint.setColor(textColor = color); } color = getThemedColor(Theme.key_chat_messagePanelBackground); if (panelBackgroundColor != color) { textPaint.setColor(panelBackgroundColor = color); } color = getThemedColor(Theme.key_chat_goDownButtonCounterBackground); if (counterColor != color) { paint.setColor(counterColor = color); } if (getParent() != null) { int contentWidth = getMeasuredWidth(); int x = (getMeasuredWidth() - contentWidth) / 2; if (rippleColor != getThemedColor(Theme.key_chat_fieldOverlayText) || selectableBackground == null) { selectableBackground = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(60), 0, ColorUtils.setAlphaComponent(rippleColor = getThemedColor(Theme.key_chat_fieldOverlayText), 26)); selectableBackground.setCallback(this); } int start = (getLeft() + x) <= 0 ? x - AndroidUtilities.dp(20) : x; int end = x + contentWidth > ((View) getParent()).getMeasuredWidth() ? x + contentWidth + AndroidUtilities.dp(20) : x + contentWidth; selectableBackground.setBounds( start, getMeasuredHeight() / 2 - contentWidth / 2, end, getMeasuredHeight() / 2 + contentWidth / 2 ); selectableBackground.draw(canvas); } if (textLayout != null) { canvas.save(); if (replaceProgress != 1f && textLayoutOut != null) { int oldAlpha = layoutPaint.getAlpha(); canvas.save(); canvas.translate((getMeasuredWidth() - textLayoutOut.getWidth()) / 2 - circleWidth / 2, (getMeasuredHeight() - textLayout.getHeight()) / 2); canvas.translate(0, (animatedFromBottom ? -1f : 1f) * AndroidUtilities.dp(18) * replaceProgress); layoutPaint.setAlpha((int) (oldAlpha * (1f - replaceProgress))); textLayoutOut.draw(canvas); canvas.restore(); canvas.save(); canvas.translate((getMeasuredWidth() - layoutTextWidth) / 2 - circleWidth / 2, (getMeasuredHeight() - textLayout.getHeight()) / 2); canvas.translate(0, (animatedFromBottom ? 1f : -1f) * AndroidUtilities.dp(18) * (1f - replaceProgress)); layoutPaint.setAlpha((int) (oldAlpha * (replaceProgress))); textLayout.draw(canvas); canvas.restore(); layoutPaint.setAlpha(oldAlpha); } else { canvas.translate((getMeasuredWidth() - layoutTextWidth) / 2 - circleWidth / 2, (getMeasuredHeight() - textLayout.getHeight()) / 2); textLayout.draw(canvas); } canvas.restore(); } if (currentCounterString != null) { if (layout != null) { int lineWidth = (int) Math.ceil(layout.getLineWidth(0)); int x = (getMeasuredWidth() - lineWidth) / 2 + lineWidth - circleWidth / 2 + AndroidUtilities.dp(6); rect.set(x, getMeasuredHeight() / 2 - AndroidUtilities.dp(10), x + circleWidth, getMeasuredHeight() / 2 + AndroidUtilities.dp(10)); canvas.drawRoundRect(rect, AndroidUtilities.dp(10), AndroidUtilities.dp(10), paint); canvas.drawText(currentCounterString, rect.centerX() - textWidth / 2.0f, rect.top + AndroidUtilities.dp(14.5f), textPaint); } } } } private PhotoViewer.PhotoViewerProvider photoViewerProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { return ChatActivity.this.getPlaceForPhoto(messageObject, fileLocation, needPreview, false); } @Override public boolean validateGroupId(long groupId) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(groupId); return groupedMessages != null && groupedMessages.messages.size() > 1; } }; private ArrayList botContextResults; private PhotoViewer.PhotoViewerProvider botContextProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { if (index < 0 || index >= botContextResults.size() || mentionContainer == null || mentionContainer.getListView() == null) { return null; } int count = mentionContainer.getListView().getChildCount(); Object result = botContextResults.get(index); for (int a = 0; a < count; a++) { ImageReceiver imageReceiver = null; View view = mentionContainer.getListView().getChildAt(a); if (view instanceof ContextLinkCell) { ContextLinkCell cell = (ContextLinkCell) view; if (cell.getResult() == result) { imageReceiver = cell.getPhotoImage(); } } if (imageReceiver != null) { int[] coords = new int[2]; view.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; object.viewY = coords[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight); // object.clipTopAddition = (int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4)); object.parentView = mentionContainer.getListView(); object.imageReceiver = imageReceiver; object.thumb = imageReceiver.getBitmapSafe(); object.radius = imageReceiver.getRoundRadius(); return object; } } return null; } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { if (index < 0 || index >= botContextResults.size()) { return; } sendBotInlineResult((TLRPC.BotInlineResult) botContextResults.get(index), notify, scheduleDate); } }; private final static int copy = 10; private final static int forward = 11; private final static int delete = 12; private final static int chat_enc_timer = 13; private final static int chat_menu_attach = 14; private final static int clear_history = 15; private final static int delete_chat = 16; private final static int share_contact = 17; private final static int mute = 18; private final static int report = 21; private final static int star = 22; private final static int edit = 23; private final static int add_shortcut = 24; private final static int save_to = 25; private final static int auto_delete_timer = 26; private final static int change_colors = 27; private final static int bot_help = 30; private final static int bot_settings = 31; private final static int call = 32; private final static int video_call = 33; private final static int attach_photo = 0; private final static int attach_gallery = 1; private final static int attach_video = 2; private final static int text_bold = 50; private final static int text_italic = 51; private final static int text_mono = 52; private final static int text_link = 53; private final static int text_regular = 54; private final static int text_strike = 55; private final static int text_underline = 56; private final static int text_spoiler = 57; private final static int search = 40; private final static int id_chat_compose_panel = 1000; RecyclerListView.OnItemLongClickListenerExtended onItemLongClickListener = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isSelectionMode() || inPreviewMode) { return false; } wasManualScroll = true; boolean result = true; if (!actionBar.isActionModeShowed() && (reportType < 0 || (view instanceof ChatActionCell && ((ChatActionCell) view).getMessageObject().messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL))) { result = createMenu(view, false, true, x, y); } else { boolean outside = false; if (view instanceof ChatMessageCell) { outside = !((ChatMessageCell) view).isInsideBackground(x, y); } processRowSelect(view, outside, x, y); } if (view instanceof ChatMessageCell) { startMultiselect(position); result = true; } return result; } }; private void startMultiselect(int position) { int indexOfMessage = position - chatAdapter.messagesStartRow; if (indexOfMessage < 0 || indexOfMessage >= messages.size()) { return; } MessageObject messageObject = messages.get(indexOfMessage); final boolean unselect = selectedMessagesIds[0].get(messageObject.getId(), null) == null && selectedMessagesIds[1].get(messageObject.getId(), null) == null; SparseArray alreadySelectedMessagesIds = new SparseArray<>(); for (int i = 0; i < selectedMessagesIds[0].size(); i++) { alreadySelectedMessagesIds.put(selectedMessagesIds[0].keyAt(i), selectedMessagesIds[0].valueAt(i)); } for (int i = 0; i < selectedMessagesIds[1].size(); i++) { alreadySelectedMessagesIds.put(selectedMessagesIds[1].keyAt(i), selectedMessagesIds[1].valueAt(i)); } chatListView.startMultiselect(position, false, new RecyclerListView.onMultiSelectionChanged() { boolean limitReached; @Override public void onSelectionChanged(int position, boolean selected, float x, float y) { int i = position - chatAdapter.messagesStartRow; if (unselect) { selected = !selected; } if (i >= 0 && i < messages.size()) { MessageObject messageObject = messages.get(i); if (selected && (selectedMessagesIds[0].indexOfKey(messageObject.getId()) >= 0 || selectedMessagesIds[1].indexOfKey(messageObject.getId()) >= 0)) { return; } if (!selected && selectedMessagesIds[0].indexOfKey(messageObject.getId()) < 0 && selectedMessagesIds[1].indexOfKey(messageObject.getId()) < 0) { return; } if (messageObject.contentType == 0) { if (selected && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() >= 100) { limitReached = true; } else { limitReached = false; } RecyclerView.ViewHolder holder = chatListView.findViewHolderForAdapterPosition(position); if (holder != null && holder.itemView instanceof ChatMessageCell) { processRowSelect(holder.itemView, false, x, y); } else { addToSelectedMessages(messageObject, false); updateActionModeTitle(); updateVisibleRows(); } } } } @Override public boolean canSelect(int position) { int i = position - chatAdapter.messagesStartRow; if (i >= 0 && i < messages.size()) { MessageObject messageObject = messages.get(i); if (messageObject.contentType == 0) { if (!unselect && alreadySelectedMessagesIds.get(messageObject.getId(), null) == null) { return true; } if (unselect && alreadySelectedMessagesIds.get(messageObject.getId(), null) != null) { return true; } } } return false; } @Override public int checkPosition(int position, boolean selectionTop) { int i = position - chatAdapter.messagesStartRow; if (i >= 0 && i < messages.size()) { MessageObject messageObject = messages.get(i); if (messageObject.contentType == 0 && messageObject.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); if (groupedMessages != null) { MessageObject messageObject1 = groupedMessages.messages.get(selectionTop ? 0 : groupedMessages.messages.size() - 1); return chatAdapter.messagesStartRow + messages.indexOf(messageObject1); } } } return position; } @Override public boolean limitReached() { return limitReached; } @Override public void getPaddings(int[] paddings) { paddings[0] = (int) chatListViewPaddingTop; paddings[1] = blurredViewBottomOffset; } @Override public void scrollBy(int dy) { chatListView.scrollBy(0, dy); } }); } RecyclerListView.OnItemClickListenerExtended onItemClickListener = new RecyclerListView.OnItemClickListenerExtended() { @Override public void onItemClick(View view, int position, float x, float y) { if (inPreviewMode) { return; } wasManualScroll = true; if (view instanceof ChatActionCell && ((ChatActionCell) view).getMessageObject().isDateObject) { Bundle bundle = new Bundle(); int date = ((ChatActionCell) view).getMessageObject().messageOwner.date; bundle.putLong("dialog_id", dialog_id); bundle.putInt("type", CalendarActivity.TYPE_CHAT_ACTIVITY); CalendarActivity calendarActivity = new CalendarActivity(bundle, SharedMediaLayout.FILTER_PHOTOS_AND_VIDEOS, date); presentFragment(calendarActivity); return; } if (actionBar.isActionModeShowed() || reportType >= 0) { boolean outside = false; if (view instanceof ChatMessageCell) { if (textSelectionHelper.isSelected(((ChatMessageCell) view).getMessageObject())) { return; } outside = !((ChatMessageCell) view).isInsideBackground(x, y); } processRowSelect(view, outside, x, y); return; } createMenu(view, true, false, x, y); } @Override public boolean hasDoubleTap(View view, int position) { TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(getMediaDataController().getDoubleTapReaction()); if (reaction == null) { return false; } boolean available = dialog_id >= 0; if (!available && chatInfo != null) { for (String s : chatInfo.available_reactions) { if (s.equals(reaction.reaction)) { available = true; break; } } } if (!available || !(view instanceof ChatMessageCell)) { return false; } ChatMessageCell cell = (ChatMessageCell) view; return !cell.getMessageObject().isSending() && !cell.getMessageObject().isEditing() && cell.getMessageObject().type != 16 && !actionBar.isActionModeShowed() && !isSecretChat() && !isInScheduleMode() && !cell.getMessageObject().isSponsored(); } @Override public void onDoubleTap(View view, int position, float x, float y) { if (!(view instanceof ChatMessageCell) || getParentActivity() == null || isSecretChat() || isInScheduleMode() || isInPreviewMode()) { return; } ChatMessageCell cell = (ChatMessageCell) view; MessageObject primaryMessage = cell.getPrimaryMessageObject(); ReactionsEffectOverlay.removeCurrent(false); TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(getMediaDataController().getDoubleTapReaction()); if (reaction == null || cell.getMessageObject().isSponsored()) { return; } boolean available = dialog_id >= 0; if (!available && chatInfo != null) { for (String s : chatInfo.available_reactions) { if (s.equals(reaction.reaction)) { available = true; break; } } } if (!available) { return; } selectReaction(primaryMessage, null, x, y, reaction, true, false); } }; private final ChatScrollCallback chatScrollHelperCallback = new ChatScrollCallback(); private final Runnable showScheduledOrNoSoundRunnable = () -> { if (getParentActivity() == null || fragmentView == null || chatActivityEnterView == null) { return; } View anchor = chatActivityEnterView.getSendButton(); if (anchor == null || chatActivityEnterView.getEditField().getText().length() < 5) { return; } SharedConfig.increaseScheduledOrNoSuoundHintShowed(); if (scheduledOrNoSoundHint == null) { scheduledOrNoSoundHint = new HintView(getParentActivity(), 4, themeDelegate); scheduledOrNoSoundHint.setShowingDuration(5000); scheduledOrNoSoundHint.setAlpha(0); scheduledOrNoSoundHint.setVisibility(View.INVISIBLE); scheduledOrNoSoundHint.setText(LocaleController.getString("ScheduledOrNoSoundHint", R.string.ScheduledOrNoSoundHint)); contentView.addView(scheduledOrNoSoundHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); } scheduledOrNoSoundHint.showForView(anchor, true); }; public ChatActivity(Bundle args) { super(args); } @Override public boolean onFragmentCreate() { final long chatId = arguments.getLong("chat_id", 0); final long userId = arguments.getLong("user_id", 0); final int encId = arguments.getInt("enc_id", 0); dialogFolderId = arguments.getInt("dialog_folder_id", 0); dialogFilterId = arguments.getInt("dialog_filter_id", 0); chatMode = arguments.getInt("chatMode", 0); voiceChatHash = arguments.getString("voicechat", null); livestream = !TextUtils.isEmpty(arguments.getString("livestream", null)); attachMenuBotToOpen = arguments.getString("attach_bot", null); attachMenuBotStartCommand = arguments.getString("attach_bot_start_command", null); inlineReturn = arguments.getLong("inline_return", 0); String inlineQuery = arguments.getString("inline_query"); premiumInvoiceBot = arguments.getBoolean("premium_bot", false); startLoadFromMessageId = arguments.getInt("message_id", 0); startLoadFromDate = arguments.getInt("start_from_date", 0); startFromVideoTimestamp = arguments.getInt("video_timestamp", -1); threadUnreadMessagesCount = arguments.getInt("unread_count", 0); if (startFromVideoTimestamp >= 0) { startFromVideoMessageId = startLoadFromMessageId; } reportType = arguments.getInt("report", -1); pulled = arguments.getBoolean("pulled", false); boolean historyPreloaded = arguments.getBoolean("historyPreloaded", false); if (highlightMessageId != 0 && highlightMessageId != Integer.MAX_VALUE) { startLoadFromMessageId = highlightMessageId; } int migrated_to = arguments.getInt("migrated_to", 0); scrollToTopOnResume = arguments.getBoolean("scrollToTopOnResume", false); needRemovePreviousSameChatActivity = arguments.getBoolean("need_remove_previous_same_chat_activity", true); if (chatId != 0) { currentChat = getMessagesController().getChat(chatId); if (currentChat == null) { final CountDownLatch countDownLatch = new CountDownLatch(1); final MessagesStorage messagesStorage = getMessagesStorage(); messagesStorage.getStorageQueue().postRunnable(() -> { currentChat = messagesStorage.getChat(chatId); countDownLatch.countDown(); }); try { countDownLatch.await(); } catch (Exception e) { FileLog.e(e); } if (currentChat != null) { getMessagesController().putChat(currentChat, true); } else { return false; } } dialog_id = -chatId; if (ChatObject.isChannel(currentChat)) { getMessagesController().startShortPoll(currentChat, classGuid, false); } } else if (userId != 0) { currentUser = getMessagesController().getUser(userId); if (currentUser == null) { final MessagesStorage messagesStorage = getMessagesStorage(); final CountDownLatch countDownLatch = new CountDownLatch(1); messagesStorage.getStorageQueue().postRunnable(() -> { currentUser = messagesStorage.getUser(userId); countDownLatch.countDown(); }); try { countDownLatch.await(); } catch (Exception e) { FileLog.e(e); } if (currentUser != null) { getMessagesController().putUser(currentUser, true); } else { return false; } } dialog_id = userId; botUser = arguments.getString("botUser"); if (inlineQuery != null) { getMessagesController().sendBotStart(currentUser, inlineQuery); } else if (premiumInvoiceBot && !TextUtils.isEmpty(botUser)) { getMessagesController().sendBotStart(currentUser, botUser); botUser = null; premiumInvoiceBot = false; } } else if (encId != 0) { currentEncryptedChat = getMessagesController().getEncryptedChat(encId); final MessagesStorage messagesStorage = getMessagesStorage(); if (currentEncryptedChat == null) { final CountDownLatch countDownLatch = new CountDownLatch(1); messagesStorage.getStorageQueue().postRunnable(() -> { currentEncryptedChat = messagesStorage.getEncryptedChat(encId); countDownLatch.countDown(); }); try { countDownLatch.await(); } catch (Exception e) { FileLog.e(e); } if (currentEncryptedChat != null) { getMessagesController().putEncryptedChat(currentEncryptedChat, true); } else { return false; } } currentUser = getMessagesController().getUser(currentEncryptedChat.user_id); if (currentUser == null) { final CountDownLatch countDownLatch = new CountDownLatch(1); messagesStorage.getStorageQueue().postRunnable(() -> { currentUser = messagesStorage.getUser(currentEncryptedChat.user_id); countDownLatch.countDown(); }); try { countDownLatch.await(); } catch (Exception e) { FileLog.e(e); } if (currentUser != null) { getMessagesController().putUser(currentUser, true); } else { return false; } } dialog_id = DialogObject.makeEncryptedDialogId(encId); maxMessageId[0] = maxMessageId[1] = Integer.MIN_VALUE; minMessageId[0] = minMessageId[1] = Integer.MAX_VALUE; } else { return false; } dialog_id_Long = dialog_id; themeDelegate = new ThemeDelegate(); if (themeDelegate.isThemeChangeAvailable()) { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.needSetDayNightTheme); } if (currentUser != null && Build.VERSION.SDK_INT < 23) { MediaController.getInstance().startMediaObserver(); } getNotificationCenter().addPostponeNotificationsCallback(postponeNotificationsWhileLoadingCallback); if (chatMode != MODE_SCHEDULED) { if (threadMessageId == 0) { getNotificationCenter().addObserver(this, NotificationCenter.screenshotTook); getNotificationCenter().addObserver(this, NotificationCenter.encryptedChatUpdated); getNotificationCenter().addObserver(this, NotificationCenter.messagesReadEncrypted); getNotificationCenter().addObserver(this, NotificationCenter.botKeyboardDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.updateMentionsCount); getNotificationCenter().addObserver(this, NotificationCenter.newDraftReceived); getNotificationCenter().addObserver(this, NotificationCenter.chatOnlineCountDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.peerSettingsDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.didLoadPinnedMessages); getNotificationCenter().addObserver(this, NotificationCenter.commentsRead); getNotificationCenter().addObserver(this, NotificationCenter.changeRepliesCounter); getNotificationCenter().addObserver(this, NotificationCenter.messagesRead); getNotificationCenter().addObserver(this, NotificationCenter.didLoadChatInviter); getNotificationCenter().addObserver(this, NotificationCenter.groupCallUpdated); } else { getNotificationCenter().addObserver(this, NotificationCenter.threadMessagesRead); } getNotificationCenter().addObserver(this, NotificationCenter.removeAllMessagesFromDialog); getNotificationCenter().addObserver(this, NotificationCenter.messagesReadContent); getNotificationCenter().addObserver(this, NotificationCenter.chatSearchResultsAvailable); getNotificationCenter().addObserver(this, NotificationCenter.chatSearchResultsLoading); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateMessagesViews); getNotificationCenter().addObserver(this, NotificationCenter.didUpdatePollResults); if (currentEncryptedChat != null) { getNotificationCenter().addObserver(this, NotificationCenter.didVerifyMessagesStickers); } } getNotificationCenter().addObserver(this, NotificationCenter.messagesDidLoad); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.invalidateMotionBackground); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateConnectionState); getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); getNotificationCenter().addObserver(this, NotificationCenter.updateDefaultSendAsPeer); if (chatMode != MODE_PINNED) { getNotificationCenter().addObserver(this, NotificationCenter.didReceiveNewMessages); } if (chatMode == 0) { getNotificationCenter().addObserver(this, NotificationCenter.didLoadSponsoredMessages); } getNotificationCenter().addObserver(this, NotificationCenter.didLoadSendAsPeers); getNotificationCenter().addObserver(this, NotificationCenter.closeChats); getNotificationCenter().addObserver(this, NotificationCenter.messagesDeleted); getNotificationCenter().addObserver(this, NotificationCenter.historyCleared); getNotificationCenter().addObserver(this, NotificationCenter.messageReceivedByServer); getNotificationCenter().addObserver(this, NotificationCenter.messageReceivedByAck); getNotificationCenter().addObserver(this, NotificationCenter.messageSendError); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.contactsDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingProgressDidChanged); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidReset); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingGoingToStop); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingPlayStateChanged); getNotificationCenter().addObserver(this, NotificationCenter.blockedUsersDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.fileNewChunkAvailable); getNotificationCenter().addObserver(this, NotificationCenter.didCreatedNewDeleteTask); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidStart); getNotificationCenter().addObserver(this, NotificationCenter.updateMessageMedia); getNotificationCenter().addObserver(this, NotificationCenter.voiceTranscriptionUpdate); getNotificationCenter().addObserver(this, NotificationCenter.animatedEmojiDocumentLoaded); getNotificationCenter().addObserver(this, NotificationCenter.replaceMessagesObjects); getNotificationCenter().addObserver(this, NotificationCenter.notificationsSettingsUpdated); getNotificationCenter().addObserver(this, NotificationCenter.replyMessagesDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.didReceivedWebpages); getNotificationCenter().addObserver(this, NotificationCenter.didReceivedWebpagesInUpdates); getNotificationCenter().addObserver(this, NotificationCenter.botInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoCantLoad); getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.pinnedInfoDidLoad); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didApplyNewTheme); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.goingToPreviewTheme); getNotificationCenter().addObserver(this, NotificationCenter.channelRightsUpdated); getNotificationCenter().addObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateReactions); getNotificationCenter().addObserver(this, NotificationCenter.videoLoadingStateChanged); getNotificationCenter().addObserver(this, NotificationCenter.scheduledMessagesUpdated); getNotificationCenter().addObserver(this, NotificationCenter.diceStickersDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.dialogDeleted); getNotificationCenter().addObserver(this, NotificationCenter.chatAvailableReactionsUpdated); getNotificationCenter().addObserver(this, NotificationCenter.dialogsUnreadReactionsCounterChanged); getNotificationCenter().addObserver(this, NotificationCenter.groupStickersDidLoad); super.onFragmentCreate(); if (chatMode == MODE_PINNED) { ArrayList messageObjects = new ArrayList<>(); for (int a = 0, N = pinnedMessageIds.size(); a < N; a++) { Integer id = pinnedMessageIds.get(a); MessageObject object = pinnedMessageObjects.get(id); if (object != null) { MessageObject o = new MessageObject(object.currentAccount, object.messageOwner, true, false); o.replyMessageObject = object.replyMessageObject; o.mediaExists = object.mediaExists; o.attachPathExists = object.attachPathExists; messageObjects.add(o); } } int loadIndex = lastLoadIndex++; waitingForLoad.add(loadIndex); getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, messageObjects.size(), messageObjects, false, 0, last_message_id, 0, 0, 2, true, classGuid, loadIndex, pinnedMessageIds.get(0), 0, MODE_PINNED); } else if (!forceHistoryEmpty) { loading = true; } if (isThreadChat()) { if (highlightMessageId == startLoadFromMessageId) { needSelectFromMessageId = true; } } else { getMessagesController().setLastCreatedDialogId(dialog_id, chatMode == MODE_SCHEDULED, true); if (chatMode == 0) { if (currentEncryptedChat == null) { getMediaDataController().loadBotKeyboard(dialog_id); } getMessagesController().loadPeerSettings(currentUser, currentChat); if (startLoadFromMessageId == 0) { SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); int messageId = sharedPreferences.getInt("diditem" + dialog_id, 0); if (messageId != 0) { wasManualScroll = true; loadingFromOldPosition = true; startLoadFromMessageOffset = sharedPreferences.getInt("diditemo" + dialog_id, 0); startLoadFromMessageId = messageId; } } else { showScrollToMessageError = true; needSelectFromMessageId = true; } } } boolean loadInfo = false; if (currentChat != null) { chatInfo = getMessagesController().getChatFull(currentChat.id); groupCall = getMessagesController().getGroupCall(currentChat.id, true); if (ChatObject.isChannel(currentChat) && !getMessagesController().isChannelAdminsLoaded(currentChat.id)) { getMessagesController().loadChannelAdmins(currentChat.id, true); } fillInviterId(false); if (chatMode != MODE_PINNED) { getMessagesStorage().loadChatInfo(currentChat.id, ChatObject.isChannel(currentChat), null, true, false, startLoadFromMessageId); } if (chatMode == 0 && chatInfo != null && ChatObject.isChannel(currentChat) && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; } loadInfo = chatInfo == null; checkGroupCallJoin(false); } else if (currentUser != null) { if (chatMode != MODE_PINNED) { getMessagesController().loadUserInfo(currentUser, true, classGuid, startLoadFromMessageId); } loadInfo = userInfo == null; } if (forceHistoryEmpty) { endReached[0] = endReached[1] = true; forwardEndReached[0] = forwardEndReached[1] = true; firstLoading = false; } if (chatMode != MODE_PINNED && !forceHistoryEmpty) { waitingForLoad.add(lastLoadIndex); if (startLoadFromDate != 0) { getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, startLoadFromDate, true, 0, classGuid, 4, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId)) { startLoadFromMessageIdSaved = startLoadFromMessageId; if (migrated_to != 0) { mergeDialogId = migrated_to; getMessagesController().loadMessages(mergeDialogId, 0, loadInfo, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else { getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } else { if (historyPreloaded) { lastLoadIndex++; } else { getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, AndroidUtilities.isTablet() || isThreadChat() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } } if (chatMode == 0 && !isThreadChat()) { waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++); } if (chatMode == 0) { if (userId != 0 && currentUser.bot) { getMediaDataController().loadBotInfo(userId, userId, true, classGuid); } else if (chatInfo instanceof TLRPC.TL_chatFull) { for (int a = 0; a < chatInfo.participants.participants.size(); a++) { TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); TLRPC.User user = getMessagesController().getUser(participant.user_id); if (user != null && user.bot) { getMediaDataController().loadBotInfo(user.id, -chatInfo.id, true, classGuid); } } } if (AndroidUtilities.isTablet()) { getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, false); } if (currentUser != null && !UserObject.isReplyUser(currentUser)) { userBlocked = getMessagesController().blockePeers.indexOfKey(currentUser.id) >= 0; } if (currentEncryptedChat != null && AndroidUtilities.getMyLayerVersion(currentEncryptedChat.layer) != SecretChatHelper.CURRENT_SECRET_CHAT_LAYER) { getSecretChatHelper().sendNotifyLayerMessage(currentEncryptedChat, null); } } if (chatInfo != null && chatInfo.linked_chat_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(chatInfo.linked_chat_id); if (chat != null && chat.megagroup) { getMessagesController().startShortPoll(chat, classGuid, false); } } if (chatInvite != null) { int timeout = chatInvite.expires - getConnectionsManager().getCurrentTime(); if (timeout < 0) { timeout = 10; } AndroidUtilities.runOnUIThread(chatInviteRunnable = () -> { chatInviteRunnable = null; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { builder.setMessage(LocaleController.getString("JoinByPeekChannelText", R.string.JoinByPeekChannelText)); builder.setTitle(LocaleController.getString("JoinByPeekChannelTitle", R.string.JoinByPeekChannelTitle)); } else { builder.setMessage(LocaleController.getString("JoinByPeekGroupText", R.string.JoinByPeekGroupText)); builder.setTitle(LocaleController.getString("JoinByPeekGroupTitle", R.string.JoinByPeekGroupTitle)); } builder.setPositiveButton(LocaleController.getString("JoinByPeekJoin", R.string.JoinByPeekJoin), (dialogInterface, i) -> { if (bottomOverlayChatText != null) { bottomOverlayChatText.callOnClick(); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialogInterface, i) -> finishFragment()); showDialog(builder.create()); }, timeout * 1000L); } return true; } private void fillInviterId(boolean load) { if (currentChat == null || chatInfo == null || ChatObject.isNotInChat(currentChat) || currentChat.creator) { return; } if (chatInfo.inviterId != 0) { chatInviterId = chatInfo.inviterId; return; } if (chatInfo.participants != null) { if (chatInfo.participants.self_participant != null) { chatInviterId = chatInfo.participants.self_participant.inviter_id; return; } long selfId = getUserConfig().getClientUserId(); for (int a = 0, N = chatInfo.participants.participants.size(); a < N; a++) { TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); if (participant.user_id == selfId) { chatInviterId = participant.inviter_id; return; } } } if (load && chatInviterId == 0) { getMessagesController().checkChatInviter(currentChat.id, false); } } private void hideUndoViews() { if (undoView != null) { undoView.hide(true, 0); } if (pinBulletin != null) { pinBulletin.hide(false, 0); } if (topUndoView != null) { topUndoView.hide(true, 0); } } public int getOtherSameChatsDiff() { if (parentLayout == null || parentLayout.fragmentsStack == null) { return 0; } int cur = parentLayout.fragmentsStack.indexOf(this); if (cur == -1) { cur = parentLayout.fragmentsStack.size(); } int i = cur; for (int a = 0; a < parentLayout.fragmentsStack.size(); a++) { BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.dialog_id == dialog_id) { i = a; break; } } } return i - cur; } @Override public void onFragmentDestroy() { super.onFragmentDestroy(); if (chatActivityEnterView != null) { chatActivityEnterView.onDestroy(); } if (avatarContainer != null) { avatarContainer.onDestroy(); } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().onDestroy(); } if (chatAttachAlert != null) { chatAttachAlert.dismissInternal(); } getNotificationCenter().onAnimationFinish(transitionAnimationIndex); getNotificationCenter().onAnimationFinish(scrollAnimationIndex); getNotificationCenter().onAnimationFinish(scrollCallbackAnimationIndex); hideUndoViews(); if (chatInviteRunnable != null) { AndroidUtilities.cancelRunOnUIThread(chatInviteRunnable); chatInviteRunnable = null; } getNotificationCenter().removePostponeNotificationsCallback(postponeNotificationsWhileLoadingCallback); getMessagesController().setLastCreatedDialogId(dialog_id, chatMode == MODE_SCHEDULED, false); getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.invalidateMotionBackground); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateConnectionState); getNotificationCenter().removeObserver(this, NotificationCenter.updateInterfaces); getNotificationCenter().removeObserver(this, NotificationCenter.updateDefaultSendAsPeer); getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages); getNotificationCenter().removeObserver(this, NotificationCenter.closeChats); getNotificationCenter().removeObserver(this, NotificationCenter.messagesRead); getNotificationCenter().removeObserver(this, NotificationCenter.threadMessagesRead); getNotificationCenter().removeObserver(this, NotificationCenter.commentsRead); getNotificationCenter().removeObserver(this, NotificationCenter.changeRepliesCounter); getNotificationCenter().removeObserver(this, NotificationCenter.messagesDeleted); getNotificationCenter().removeObserver(this, NotificationCenter.historyCleared); getNotificationCenter().removeObserver(this, NotificationCenter.messageReceivedByServer); getNotificationCenter().removeObserver(this, NotificationCenter.messageReceivedByAck); getNotificationCenter().removeObserver(this, NotificationCenter.messageSendError); getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.didLoadChatInviter); getNotificationCenter().removeObserver(this, NotificationCenter.groupCallUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.encryptedChatUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.messagesReadEncrypted); getNotificationCenter().removeObserver(this, NotificationCenter.removeAllMessagesFromDialog); getNotificationCenter().removeObserver(this, NotificationCenter.contactsDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingProgressDidChanged); getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingDidReset); getNotificationCenter().removeObserver(this, NotificationCenter.screenshotTook); getNotificationCenter().removeObserver(this, NotificationCenter.blockedUsersDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.fileNewChunkAvailable); getNotificationCenter().removeObserver(this, NotificationCenter.didCreatedNewDeleteTask); getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingDidStart); getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingGoingToStop); getNotificationCenter().removeObserver(this, NotificationCenter.updateMessageMedia); getNotificationCenter().removeObserver(this, NotificationCenter.voiceTranscriptionUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.animatedEmojiDocumentLoaded); getNotificationCenter().removeObserver(this, NotificationCenter.replaceMessagesObjects); getNotificationCenter().removeObserver(this, NotificationCenter.notificationsSettingsUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.replyMessagesDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.didReceivedWebpages); getNotificationCenter().removeObserver(this, NotificationCenter.didReceivedWebpagesInUpdates); getNotificationCenter().removeObserver(this, NotificationCenter.messagesReadContent); getNotificationCenter().removeObserver(this, NotificationCenter.botInfoDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.botKeyboardDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.chatSearchResultsAvailable); getNotificationCenter().removeObserver(this, NotificationCenter.chatSearchResultsLoading); getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingPlayStateChanged); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateMessagesViews); getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoCantLoad); getNotificationCenter().removeObserver(this, NotificationCenter.didLoadPinnedMessages); getNotificationCenter().removeObserver(this, NotificationCenter.peerSettingsDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.newDraftReceived); getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.pinnedInfoDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didApplyNewTheme); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.goingToPreviewTheme); getNotificationCenter().removeObserver(this, NotificationCenter.channelRightsUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.updateMentionsCount); getNotificationCenter().removeObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdatePollResults); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateReactions); getNotificationCenter().removeObserver(this, NotificationCenter.chatOnlineCountDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.videoLoadingStateChanged); getNotificationCenter().removeObserver(this, NotificationCenter.scheduledMessagesUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.diceStickersDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.dialogDeleted); getNotificationCenter().removeObserver(this, NotificationCenter.chatAvailableReactionsUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.didLoadSponsoredMessages); getNotificationCenter().removeObserver(this, NotificationCenter.didLoadSendAsPeers); getNotificationCenter().removeObserver(this, NotificationCenter.dialogsUnreadReactionsCounterChanged); getNotificationCenter().removeObserver(this, NotificationCenter.groupStickersDidLoad); if (currentEncryptedChat != null) { getNotificationCenter().removeObserver(this, NotificationCenter.didVerifyMessagesStickers); } NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.needSetDayNightTheme); if (chatMode == 0 && AndroidUtilities.isTablet()) { getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true); } if (currentUser != null) { MediaController.getInstance().stopMediaObserver(); } if (unregisterFlagSecureNoforwards != null) { unregisterFlagSecureNoforwards.run(); unregisterFlagSecureNoforwards = null; } if (unregisterFlagSecurePasscode != null) { unregisterFlagSecurePasscode.run(); unregisterFlagSecurePasscode = null; } if (currentUser != null) { getMessagesController().cancelLoadFullUser(currentUser.id); } AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); if (chatAttachAlert != null) { chatAttachAlert.onDestroy(); } AndroidUtilities.unlockOrientation(getParentActivity()); if (ChatObject.isChannel(currentChat)) { getMessagesController().startShortPoll(currentChat, classGuid, true); if (chatInfo != null && chatInfo.linked_chat_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(chatInfo.linked_chat_id); getMessagesController().startShortPoll(chat, classGuid, true); } } if (textSelectionHelper != null) { textSelectionHelper.clear(); } if (chatListItemAnimator != null) { chatListItemAnimator.onDestroy(); } if (pinchToZoomHelper != null) { pinchToZoomHelper.clear(); } chatThemeBottomSheet = null; ActionBarLayout parentLayout = getParentLayout(); if (parentLayout != null && parentLayout.fragmentsStack != null) { BackButtonMenu.clearPulledDialogs(this, parentLayout.fragmentsStack.indexOf(this) - (replacingChatActivity ? 0 : 1)); } replacingChatActivity = false; } @Override public View createView(Context context) { textSelectionHelper = new TextSelectionHelper.ChatListTextSelectionHelper() { @Override public int getParentTopPadding() { return (int) chatListViewPaddingTop; } @Override public int getParentBottomPadding() { return blurredViewBottomOffset; } @Override protected int getThemedColor(String key) { Integer color = themeDelegate.getColor(key); return color != null ? color : super.getThemedColor(key); } @Override protected Theme.ResourcesProvider getResourcesProvider() { return themeDelegate; } }; if (reportType >= 0) { actionBar.setBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefault)); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); actionBar.setTitleColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); actionBar.setSubtitleColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); } actionBarBackgroundPaint.setColor(getThemedColor(Theme.key_actionBarDefault)); if (chatMessageCellsCache.isEmpty()) { for (int a = 0; a < 15; a++) { chatMessageCellsCache.add(new ChatMessageCell(context, true, themeDelegate)); } } for (int a = 1; a >= 0; a--) { selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } scheduledOrNoSoundHint = null; infoTopView = null; aspectRatioFrameLayout = null; videoTextureView = null; searchAsListHint = null; mediaBanTooltip = null; noSoundHintView = null; forwardHintView = null; checksHintView = null; textSelectionHint = null; emojiButtonRed = null; gifHintTextView = null; pollHintView = null; timerHintView = null; videoPlayerContainer = null; voiceHintTextView = null; blurredView = null; dummyMessageCell = null; cantDeleteMessagesCount = 0; canEditMessagesCount = 0; cantForwardMessagesCount = 0; canForwardMessagesCount = 0; cantSaveMessagesCount = 0; canSaveMusicCount = 0; canSaveDocumentsCount = 0; hasOwnBackground = true; if (chatAttachAlert != null) { try { if (chatAttachAlert.isShowing()) { chatAttachAlert.dismiss(); } } catch (Exception ignore) { } chatAttachAlert.onDestroy(); chatAttachAlert = null; } Theme.createChatResources(context, false); actionBar.setAddToContainer(false); if (inPreviewMode) { actionBar.setBackButtonDrawable(null); } else { actionBar.setBackButtonDrawable(new BackDrawable(reportType >= 0)); } actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(final int id) { if (id == -1) { if (actionBar.isActionModeShowed()) { clearSelectionMode(); } else { if (!checkRecordLocked(true)) { finishFragment(); } } } else if (id == copy) { SpannableStringBuilder str = new SpannableStringBuilder(); long previousUid = 0; for (int a = 1; a >= 0; a--) { ArrayList ids = new ArrayList<>(); for (int b = 0; b < selectedMessagesCanCopyIds[a].size(); b++) { ids.add(selectedMessagesCanCopyIds[a].keyAt(b)); } if (currentEncryptedChat == null) { Collections.sort(ids); } else { Collections.sort(ids, Collections.reverseOrder()); } for (int b = 0; b < ids.size(); b++) { Integer messageId = ids.get(b); MessageObject messageObject = selectedMessagesCanCopyIds[a].get(messageId); if (str.length() != 0) { str.append("\n\n"); } str.append(getMessageContent(messageObject, previousUid, ids.size() != 1 && (currentUser == null || !currentUser.self))); previousUid = messageObject.getFromChatId(); } } if (str.length() != 0) { AndroidUtilities.addToClipboard(str); undoView.showWithAction(0, UndoView.ACTION_TEXT_COPIED, null); } clearSelectionMode(); } else if (id == delete) { if (getParentActivity() == null) { return; } createDeleteMessagesAlert(null, null); } else if (id == forward) { openForward(true); } else if (id == save_to) { ArrayList messageObjects = new ArrayList<>(); for (int a = 1; a >= 0; a--) { for (int b = 0; b < selectedMessagesIds[a].size(); b++) { messageObjects.add(selectedMessagesIds[a].valueAt(b)); } selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } boolean isMusic = canSaveMusicCount > 0; hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); MediaController.saveFilesFromMessages(getParentActivity(), getAccountInstance(), messageObjects, (count) -> { if (count > 0) { if (getParentActivity() == null) { return; } BulletinFactory.of(ChatActivity.this).createDownloadBulletin(isMusic ? BulletinFactory.FileType.AUDIOS : BulletinFactory.FileType.UNKNOWNS, count, themeDelegate).show(); } }); } else if (id == chat_enc_timer) { if (getParentActivity() == null) { return; } showDialog(AlertsCreator.createTTLAlert(getParentActivity(), currentEncryptedChat, themeDelegate).create()); } else if (id == clear_history || id == delete_chat || id == auto_delete_timer) { if (getParentActivity() == null) { return; } boolean canDeleteHistory = chatInfo != null && chatInfo.can_delete_channel; if (id == auto_delete_timer || id == clear_history && currentEncryptedChat == null && ((currentUser != null && !UserObject.isUserSelf(currentUser) && !UserObject.isDeleted(currentUser)) || (chatInfo != null && chatInfo.can_delete_channel))) { AlertsCreator.createClearDaysDialogAlert(ChatActivity.this, -1, currentUser, currentChat, canDeleteHistory, new MessagesStorage.BooleanCallback() { @Override public void run(boolean revoke) { if (revoke && (currentUser != null || canDeleteHistory)) { getMessagesStorage().getMessagesCount(dialog_id, (count) -> { if (count >= 50) { AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, true, false, true, currentChat, currentUser, false, false, canDeleteHistory, (param) -> performHistoryClear(true, canDeleteHistory), themeDelegate); } else { performHistoryClear(true, canDeleteHistory); } }); } else { performHistoryClear(revoke, canDeleteHistory); } } }, getResourceProvider()); return; } AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, id == clear_history, currentChat, currentUser, currentEncryptedChat != null, true, canDeleteHistory, (param) -> { if (id == clear_history && ChatObject.isChannel(currentChat) && (!currentChat.megagroup || !TextUtils.isEmpty(currentChat.username))) { getMessagesController().deleteDialog(dialog_id, 2, param); } else { if (id != clear_history) { getNotificationCenter().removeObserver(ChatActivity.this, NotificationCenter.closeChats); getNotificationCenter().postNotificationName(NotificationCenter.closeChats); finishFragment(); getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat, param); } else { performHistoryClear(param, canDeleteHistory); } } }, themeDelegate); } else if (id == share_contact) { if (currentUser == null || getParentActivity() == null) { return; } if (addToContactsButton.getTag() != null) { shareMyContact((Integer) addToContactsButton.getTag(), null); } else { Bundle args = new Bundle(); args.putLong("user_id", currentUser.id); args.putBoolean("addContact", true); presentFragment(new ContactAddActivity(args)); } } else if (id == mute) { toggleMute(false); } else if (id == add_shortcut) { try { getMediaDataController().installShortcut(currentUser.id); } catch (Exception e) { FileLog.e(e); } } else if (id == report) { AlertsCreator.createReportAlert(getParentActivity(), dialog_id, 0, ChatActivity.this, themeDelegate, null); } else if (id == star) { for (int a = 0; a < 2; a++) { for (int b = 0; b < selectedMessagesCanStarIds[a].size(); b++) { MessageObject msg = selectedMessagesCanStarIds[a].valueAt(b); getMediaDataController().addRecentSticker(MediaDataController.TYPE_FAVE, msg, msg.getDocument(), (int) (System.currentTimeMillis() / 1000), !hasUnfavedSelected); } } clearSelectionMode(); } else if (id == edit) { MessageObject messageObject = null; for (int a = 1; a >= 0; a--) { if (messageObject == null && selectedMessagesIds[a].size() == 1) { ArrayList ids = new ArrayList<>(); for (int b = 0; b < selectedMessagesIds[a].size(); b++) { ids.add(selectedMessagesIds[a].keyAt(b)); } messageObject = messagesDict[a].get(ids.get(0)); } selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } startEditingMessageObject(messageObject); hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } else if (id == chat_menu_attach) { ActionBarMenuSubItem attach = new ActionBarMenuSubItem(context, false, true, true, getResourceProvider()); attach.setTextAndIcon(LocaleController.getString("AttachMenu", R.string.AttachMenu), R.drawable.input_attach); attach.setOnClickListener(view -> { headerItem.closeSubMenu(); if (chatAttachAlert != null) { chatAttachAlert.setEditingMessageObject(null); } openAttachMenu(); }); headerItem.toggleSubMenu(attach, attachItem); } else if (id == bot_help) { getSendMessagesHelper().sendMessage("/help", dialog_id, null, null, null, false, null, null, null, true, 0, null); } else if (id == bot_settings) { getSendMessagesHelper().sendMessage("/settings", dialog_id, null, null, null, false, null, null, null, true, 0, null); } else if (id == search) { openSearchWithText(null); } else if (id == call || id == video_call) { if (currentUser != null && getParentActivity() != null) { VoIPHelper.startCall(currentUser, id == video_call, userInfo != null && userInfo.video_calls_available, getParentActivity(), getMessagesController().getUserFull(currentUser.id), getAccountInstance()); } } else if (id == text_bold) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedBold(); } } else if (id == text_italic) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedItalic(); } } else if (id == text_spoiler) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedSpoiler(); } } else if (id == text_mono) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedMono(); } } else if (id == text_strike) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedStrike(); } } else if (id == text_underline) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedUnderline(); } } else if (id == text_link) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedUrl(); } } else if (id == text_regular) { if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedRegular(); } } else if (id == change_colors) { showChatThemeBottomSheet(); } } }); View backButton = actionBar.getBackButton(); backButton.setOnLongClickListener(e -> { scrimPopupWindow = BackButtonMenu.show(this, backButton, dialog_id, themeDelegate); if (scrimPopupWindow != null) { scrimPopupWindow.setOnDismissListener(() -> { scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); if (scrimPopupWindowHideDimOnDismiss) { dimBehindView(false); } else { scrimPopupWindowHideDimOnDismiss = true; } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } }); chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); dimBehindView(backButton, 0.3f); hideHints(false); if (topUndoView != null) { topUndoView.hide(true, 1); } if (undoView != null) { undoView.hide(true, 1); } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } return true; } else { return false; } }); actionBar.setInterceptTouchEventListener((view, motionEvent) -> { if (chatThemeBottomSheet != null) { chatThemeBottomSheet.close(); return true; } return false; }); if (avatarContainer != null) { avatarContainer.onDestroy(); } avatarContainer = new ChatAvatarContainer(context, this, currentEncryptedChat != null, themeDelegate); avatarContainer.allowShorterStatus = true; avatarContainer.premiumIconHiddable = true; AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 1f, false); if (inPreviewMode || inBubbleMode) { avatarContainer.setOccupyStatusBar(false); } if (reportType >= 0) { if (reportType == AlertsCreator.REPORT_TYPE_SPAM) { actionBar.setTitle(LocaleController.getString("ReportChatSpam", R.string.ReportChatSpam)); } else if (reportType == AlertsCreator.REPORT_TYPE_VIOLENCE) { actionBar.setTitle(LocaleController.getString("ReportChatViolence", R.string.ReportChatViolence)); } else if (reportType == AlertsCreator.REPORT_TYPE_CHILD_ABUSE) { actionBar.setTitle(LocaleController.getString("ReportChatChild", R.string.ReportChatChild)); } else if (reportType == AlertsCreator.REPORT_TYPE_PORNOGRAPHY) { actionBar.setTitle(LocaleController.getString("ReportChatPornography", R.string.ReportChatPornography)); } else if (reportType == AlertsCreator.REPORT_TYPE_ILLEGAL_DRUGS) { actionBar.setTitle(LocaleController.getString("ReportChatIllegalDrugs", R.string.ReportChatIllegalDrugs)); } else if (reportType == AlertsCreator.REPORT_TYPE_PERSONAL_DETAILS) { actionBar.setTitle(LocaleController.getString("ReportChatPersonalDetails", R.string.ReportChatPersonalDetails)); } actionBar.setSubtitle(LocaleController.getString("ReportSelectMessages", R.string.ReportSelectMessages)); } else if (startLoadFromDate != 0) { final int date = startLoadFromDate; actionBar.setOnClickListener((v) -> { jumpToDate(date); }); actionBar.setTitle(LocaleController.formatDateChat(startLoadFromDate, false)); actionBar.setSubtitle(LocaleController.getString("Loading", R.string.Loading)); TLRPC.TL_messages_getHistory gh1 = new TLRPC.TL_messages_getHistory(); gh1.peer = getMessagesController().getInputPeer(dialog_id); gh1.offset_date = startLoadFromDate; gh1.limit = 1; gh1.add_offset = -1; int req = getConnectionsManager().sendRequest(gh1, (response, error) -> { if (response instanceof TLRPC.messages_Messages) { List l = ((TLRPC.messages_Messages) response).messages; if (!l.isEmpty()) { TLRPC.TL_messages_getHistory gh2 = new TLRPC.TL_messages_getHistory(); gh2.peer = getMessagesController().getInputPeer(dialog_id); gh2.offset_date = startLoadFromDate + 60 * 60 * 24; gh2.limit = 1; getConnectionsManager().sendRequest(gh2, (response1, error1) -> { if (response1 instanceof TLRPC.messages_Messages) { List l2 = ((TLRPC.messages_Messages) response1).messages; int count = 0; if (!l2.isEmpty()) { count = ((TLRPC.messages_Messages) response).offset_id_offset - ((TLRPC.messages_Messages) response1).offset_id_offset; } else { count = ((TLRPC.messages_Messages) response).offset_id_offset; } int finalCount = count; AndroidUtilities.runOnUIThread(() -> { if (finalCount != 0) { AndroidUtilities.runOnUIThread(() -> actionBar.setSubtitle(LocaleController.formatPluralString("messages", finalCount))); } else { actionBar.setSubtitle(LocaleController.getString("NoMessagesForThisDay", R.string.NoMessagesForThisDay)); } }); } }); } else { actionBar.setSubtitle(LocaleController.getString("NoMessagesForThisDay", R.string.NoMessagesForThisDay)); } } }); getConnectionsManager().bindRequestToGuid(req, classGuid); } else { actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : (chatMode == MODE_PINNED ? 10 : 0), 0, 40, 0)); } ActionBarMenu menu = actionBar.createMenu(); if (currentEncryptedChat == null && chatMode == 0 && reportType < 0) { searchIconItem = menu.addItem(search, R.drawable.ic_ab_search); searchIconItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem = menu.addItem(0, R.drawable.ic_ab_search, themeDelegate).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { boolean searchWas; @Override public boolean canCollapseSearch() { if (messagesSearchListView.getTag() != null) { showMessagesSearchListView(false); return false; } return true; } @Override public void onSearchCollapse() { searchCalendarButton.setVisibility(View.VISIBLE); if (searchUserButton != null) { searchUserButton.setVisibility(View.VISIBLE); } if (searchingForUser) { mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchingForUser = false; } mentionContainer.setReversed(false); mentionContainer.getAdapter().setSearchingMentions(false); searchingUserMessages = null; searchingChatMessages = null; searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); searchItem.setSearchFieldCaption(null); AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 0.95f, true); if (editTextItem != null && editTextItem.getTag() != null) { if (headerItem != null) { headerItem.setVisibility(View.GONE); } if (editTextItem != null) { editTextItem.setVisibility(View.VISIBLE); } if (attachItem != null) { attachItem.setVisibility(View.GONE); } if (searchIconItem != null && showSearchAsIcon) { searchIconItem.setVisibility(View.GONE); } if (audioCallIconItem != null && showAudioCallAsIcon) { audioCallIconItem.setVisibility(View.GONE); } } else if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer()) && (currentChat == null || ChatObject.canSendMessages(currentChat))) { if (headerItem != null) { headerItem.setVisibility(View.GONE); } if (editTextItem != null) { editTextItem.setVisibility(View.GONE); } if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } if (searchIconItem != null && showSearchAsIcon) { searchIconItem.setVisibility(View.GONE); } if (audioCallIconItem != null && showAudioCallAsIcon) { audioCallIconItem.setVisibility(View.GONE); } } else { if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } if (audioCallIconItem != null && showAudioCallAsIcon) { audioCallIconItem.setVisibility(View.VISIBLE); } if (searchIconItem != null && showSearchAsIcon) { searchIconItem.setVisibility(View.VISIBLE); } if (editTextItem != null) { editTextItem.setVisibility(View.GONE); } if (attachItem != null) { attachItem.setVisibility(View.GONE); } } if (threadMessageId == 0 && !UserObject.isReplyUser(currentUser) || threadMessageObject != null && threadMessageObject.getRepliesCount() == 0) { searchItem.setVisibility(View.GONE); } searchItemVisible = false; getMediaDataController().clearFoundMessageObjects(); if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } removeSelectedMessageHighlight(); updateBottomOverlay(); updatePinnedMessageView(true); updateVisibleRows(); } @Override public void onSearchExpand() { if (threadMessageId != 0 || UserObject.isReplyUser(currentUser)) { openSearchWithText(null); } if (!openSearchKeyboard) { return; } saveKeyboardPositionBeforeTransition(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); AndroidUtilities.runOnUIThread(() -> { searchWas = false; searchItem.getSearchField().requestFocus(); AndroidUtilities.showKeyboard(searchItem.getSearchField()); removeKeyboardPositionBeforeTransition(); }, 500); } @Override public void onSearchPressed(EditText editText) { searchWas = true; updateSearchButtons(0, 0, -1); getMediaDataController().searchMessagesInChat(editText.getText().toString(), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); } @Override public void onTextChanged(EditText editText) { showMessagesSearchListView(false); if (searchingForUser) { mentionContainer.getAdapter().searchUsernameOrHashtag("@" + editText.getText().toString(), 0, messages, true, true); } else if (searchingUserMessages == null && searchingChatMessages == null && searchUserButton != null && TextUtils.equals(editText.getText(), LocaleController.getString("SearchFrom", R.string.SearchFrom))) { searchUserButton.callOnClick(); } } @Override public void onCaptionCleared() { if (searchingUserMessages != null || searchingChatMessages != null) { searchUserButton.callOnClick(); } else { if (searchingForUser) { mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchingForUser = false; searchItem.setSearchFieldText("", true); } searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); searchCalendarButton.setVisibility(View.VISIBLE); searchUserButton.setVisibility(View.VISIBLE); searchingUserMessages = null; searchingChatMessages = null; } } @Override public boolean forceShowClear() { return searchingForUser; } }); searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); if (threadMessageId == 0 && !UserObject.isReplyUser(currentUser) || threadMessageObject != null && threadMessageObject.getRepliesCount() == 0) { searchItem.setVisibility(View.GONE); } searchItemVisible = false; } editTextItem = menu.addItem(0, R.drawable.ic_ab_other, themeDelegate); editTextItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); editTextItem.setTag(null); editTextItem.setVisibility(View.GONE); editTextItem.addSubItem(text_spoiler, LocaleController.getString("Spoiler", R.string.Spoiler)); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_bold, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString("Italic", R.string.Italic)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_italic, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_mono, stringBuilder); if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_strike, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString("Underline", R.string.Underline)); run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); editTextItem.addSubItem(text_underline, stringBuilder); } editTextItem.addSubItem(text_link, LocaleController.getString("CreateLink", R.string.CreateLink)); editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0) { TLRPC.UserFull userFull = null; if (currentUser != null) { audioCallIconItem = menu.addItem(call, R.drawable.ic_call, themeDelegate); audioCallIconItem.setContentDescription(LocaleController.getString("Call", R.string.Call)); userFull = getMessagesController().getUserFull(currentUser.id); if (userFull != null && userFull.phone_calls_available) { showAudioCallAsIcon = !inPreviewMode; audioCallIconItem.setVisibility(View.VISIBLE); } else { showAudioCallAsIcon = false; audioCallIconItem.setVisibility(View.GONE); } } headerItem = menu.addItem(0, R.drawable.ic_ab_other, themeDelegate); headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); if (currentUser == null || !currentUser.self) { chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, headerItem.getPopupLayout().getSwipeBack(), false, false, new ChatNotificationsPopupWrapper.Callback() { @Override public void dismiss() { headerItem.toggleSubMenu(); } @Override public void toggleSound() { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); boolean enabled = !preferences.getBoolean("sound_enabled_" + dialog_id, true); preferences.edit().putBoolean("sound_enabled_" + dialog_id, enabled).apply(); if (BulletinFactory.canShowBulletin(ChatActivity.this)) { BulletinFactory.createSoundEnabledBulletin(ChatActivity.this, enabled ? NotificationsController.SETTING_SOUND_ON : NotificationsController.SETTING_SOUND_OFF, getResourceProvider()).show(); } updateTitleIcons(); } @Override public void muteFor(int timeInSeconds) { if (timeInSeconds == 0) { if (getMessagesController().isDialogMuted(dialog_id)) { ChatActivity.this.toggleMute(true); } if (BulletinFactory.canShowBulletin(ChatActivity.this)) { BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_UNMUTE, timeInSeconds, getResourceProvider()).show(); } } else { getNotificationsController().muteUntil(dialog_id, timeInSeconds); if (BulletinFactory.canShowBulletin(ChatActivity.this)) { BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show(); } } } @Override public void showCustomize() { if (dialog_id != 0) { if (currentUser != null) { getMessagesController().putUser(currentUser, true); } Bundle args = new Bundle(); args.putLong("dialog_id", dialog_id); presentFragment(new ProfileNotificationsActivity(args, themeDelegate)); } } @Override public void toggleMute() { ChatActivity.this.toggleMute(true); BulletinFactory.createMuteBulletin(ChatActivity.this, getMessagesController().isDialogMuted(dialog_id), themeDelegate).show(); } }, getResourceProvider()); muteItem = headerItem.addSwipeBackItem(R.drawable.msg_mute, null, null, chatNotificationsPopupWrapper.windowLayout); muteItem.setOnClickListener(view -> { boolean muted = MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id); if (muted) { updateTitleIcons(true); AndroidUtilities.runOnUIThread(() -> { ChatActivity.this.toggleMute(true); }, 150); headerItem.toggleSubMenu(); BulletinFactory.createMuteBulletin(ChatActivity.this, false, themeDelegate).show(); } else { muteItem.openSwipeBack(); } }); muteItemGap = headerItem.addColoredGap(); } if (currentUser != null) { headerItem.addSubItem(call, R.drawable.msg_callback, LocaleController.getString("Call", R.string.Call), themeDelegate); if (Build.VERSION.SDK_INT >= 18) { headerItem.addSubItem(video_call, R.drawable.msg_videocall, LocaleController.getString("VideoCall", R.string.VideoCall), themeDelegate); } if (userFull != null && userFull.phone_calls_available) { headerItem.showSubItem(call); if (userFull.video_calls_available) { headerItem.showSubItem(video_call); } else { headerItem.hideSubItem(video_call); } } else { headerItem.hideSubItem(call); headerItem.hideSubItem(video_call); } } if (searchItem != null) { headerItem.addSubItem(search, R.drawable.msg_search, LocaleController.getString("Search", R.string.Search), themeDelegate); } if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { headerItem.addSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat), themeDelegate); } if (currentUser != null) { addContactItem = headerItem.addSubItem(share_contact, R.drawable.msg_addcontact, "", themeDelegate); } if (currentEncryptedChat != null) { timeItem2 = headerItem.addSubItem(chat_enc_timer, R.drawable.msg_autodelete, LocaleController.getString("SetTimer", R.string.SetTimer), themeDelegate); } clearHistoryItem = headerItem.addSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory), themeDelegate); if (themeDelegate.isThemeChangeAvailable()) { headerItem.addSubItem(change_colors, R.drawable.msg_colors, LocaleController.getString("ChangeColors", R.string.ChangeColors), themeDelegate); } if (ChatObject.isChannel(currentChat) && !currentChat.creator) { if (!ChatObject.isNotInChat(currentChat)) { if (currentChat.megagroup) { headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu), themeDelegate); } else { headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu), themeDelegate); } } } else if (!ChatObject.isChannel(currentChat)) { if (currentChat != null) { headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit), themeDelegate); } else { headerItem.addSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser), themeDelegate); } } if (currentUser != null && currentUser.self) { headerItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut), themeDelegate); } if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { headerItem.addSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings), themeDelegate); headerItem.addSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp), themeDelegate); updateBotButtons(); } } menu.setVisibility(inMenuMode ? View.GONE : View.VISIBLE); updateTitle(); avatarContainer.updateOnlineCount(); avatarContainer.updateSubtitle(); updateTitleIcons(); if (chatMode == 0 && !isThreadChat() && reportType < 0) { attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other, themeDelegate).setOverrideMenuClick(true).setAllowCloseAnimation(false); attachItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); attachItem.setVisibility(View.GONE); } actionModeViews.clear(); if (inPreviewMode) { if (headerItem != null) { headerItem.setAlpha(0.0f); } if (attachItem != null) { attachItem.setAlpha(0.0f); } } final ActionBarMenu actionMode = actionBar.createActionMode(); selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); selectedMessagesCountTextView.setTextColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); if (currentEncryptedChat == null) { actionModeViews.add(actionMode.addItemWithWidth(save_to, R.drawable.msg_download, AndroidUtilities.dp(54), LocaleController.getString("SaveToMusic", R.string.SaveToMusic))); actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); } else { actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); } actionMode.getItem(edit).setVisibility(canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); actionMode.getItem(copy).setVisibility(!getMessagesController().isChatNoForwards(currentChat) && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); actionMode.getItem(star).setVisibility(selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size() != 0 ? View.VISIBLE : View.GONE); actionMode.getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); checkActionBarMenu(false); scrimPaint = new Paint(); fragmentView = new SizeNotifierFrameLayout(context, parentLayout) { int inputFieldHeight = 0; int lastHeight; int lastWidth; ArrayList drawTimeAfter = new ArrayList<>(); ArrayList drawNamesAfter = new ArrayList<>(); ArrayList drawCaptionAfter = new ArrayList<>(); Paint backgroundPaint; int backgroundColor; @Override protected void drawList(Canvas blurCanvas, boolean top) { float cilpTop = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4); for (int i = 0; i < chatListView.getChildCount(); i++) { View child = chatListView.getChildAt(i); if (top && child.getY() > cilpTop + AndroidUtilities.dp(40)) { continue; } if (!top && child.getY() + child.getMeasuredHeight() < AndroidUtilities.dp(203)) { continue; } blurCanvas.save(); if (top) { blurCanvas.translate(chatListView.getX() + child.getX(), chatListView.getY() + child.getY() - contentPanTranslation); } else { blurCanvas.translate(chatListView.getX() + child.getX(), chatListView.getTop() + child.getY()); } if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; cell.drawForBlur = true; if (cell.drawBackgroundInParent()) { cell.drawBackgroundInternal(blurCanvas, true); } child.draw(blurCanvas); if (cell.hasOutboundsContent()) { ((ChatMessageCell) child).drawOutboundsContent(blurCanvas); } cell.drawForBlur = false; } else { child.draw(blurCanvas); } blurCanvas.restore(); } } @Override protected int getScrollOffset() { return chatListView.computeVerticalScrollOffset(); } @Override protected float getBottomOffset() { return chatListView.getBottom(); } @Override protected float getListTranslationY() { return chatListView.getTranslationY(); } { adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { @Override protected void onTransitionStart(boolean keyboardVisible, int contentHeight) { wasManualScroll = true; if (chatActivityEnterView != null) { chatActivityEnterView.onAdjustPanTransitionStart(keyboardVisible, contentHeight); } if (mentionContainer != null) { mentionContainer.onPanTransitionStart(); } if (mediaBanTooltip != null) { mediaBanTooltip.hide(false); } } @Override protected void onTransitionEnd() { if (chatActivityEnterView != null) { chatActivityEnterView.onAdjustPanTransitionEnd(); } if (mentionContainer != null) { mentionContainer.onPanTransitionEnd(); } } @Override protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { return; } contentPanTranslation = y; if (chatAttachAlert != null && chatAttachAlert.isShowing()) { setNonNoveTranslation(y); } else { actionBar.setTranslationY(y); emptyViewContainer.setTranslationY(y / 2); progressView.setTranslationY(y / 2); contentView.setBackgroundTranslation((int) y); instantCameraView.onPanTranslationUpdate(y); if (blurredView != null) { blurredView.drawable.onPanTranslationUpdate(y); } setFragmentPanTranslationOffset((int) y); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } chatListView.invalidate(); updateBulletinLayout(); if (chatActivityEnterView != null) { chatActivityEnterView.onAdjustPanTransitionUpdate(y, progress, keyboardVisible); } if (mentionContainer != null) { mentionContainer.onPanTransitionUpdate(y); } } @Override protected boolean heightAnimationEnabled() { ActionBarLayout actionBarLayout = getParentLayout(); if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { return false; } if (System.currentTimeMillis() - activityResumeTime < 250) { return false; } if ((ChatActivity.this == actionBarLayout.getLastFragment() && actionBarLayout.isTransitionAnimationInProgress()) || actionBarLayout.isPreviewOpenAnimationInProgress() || isPaused || !openAnimationEnded || (chatAttachAlert != null && chatAttachAlert.isShowing())) { return false; } if (chatActivityEnterView != null && chatActivityEnterView.getTrendingStickersAlert() != null && chatActivityEnterView.getTrendingStickersAlert().isShowing()) { return false; } return true; } @Override protected int startOffset() { int keyboardSize = getKeyboardHeight(); if (keyboardSize <= AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing()) { return chatActivityEnterView.getEmojiPadding(); } return 0; } }; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); adjustPanLayoutHelper.onAttach(); chatActivityEnterView.setAdjustPanLayoutHelper(adjustPanLayoutHelper); MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null && (messageObject.isRoundVideo() || messageObject.isVideo()) && messageObject.eventId == 0 && messageObject.getDialogId() == dialog_id) { MediaController.getInstance().setTextureView(createTextureView(false), aspectRatioFrameLayout, videoPlayerContainer, true); } if (pullingDownDrawable != null) { pullingDownDrawable.onAttach(); } emojiAnimationsOverlay.onAttachedToWindow(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); adjustPanLayoutHelper.onDetach(); if (pullingDownDrawable != null) { pullingDownDrawable.onDetach(); pullingDownDrawable = null; } emojiAnimationsOverlay.onDetachedFromWindow(); AndroidUtilities.runOnUIThread(() -> { ReactionsEffectOverlay.removeCurrent(true); }); } private float x, y; private long pressTime; @Override public boolean dispatchTouchEvent(MotionEvent ev) { float expandY; if (AndroidUtilities.isInMultiwindow || isInBubbleMode()) { expandY = chatActivityEnterView.getEmojiView() != null ? chatActivityEnterView.getEmojiView().getY() : chatActivityEnterView.getY(); } else { expandY = chatActivityEnterView.getY(); } if (scrimView != null || chatActivityEnterView != null && chatActivityEnterView.isStickersExpanded() && ev.getY() < expandY) { return false; } lastTouchY = ev.getY(); TextSelectionHelper.TextSelectionOverlay selectionOverlay = textSelectionHelper.getOverlayView(context); ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); if (textSelectionHelper.isSelectionMode() && textSelectionHelper.getOverlayView(context).onTouchEvent(ev)) { return true; } else { ev.offsetLocation(selectionOverlay.getX(), selectionOverlay.getY()); } if (selectionOverlay.checkOnTap(ev)) { ev.setAction(MotionEvent.ACTION_CANCEL); } if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelper.isSelectionMode() && (ev.getY() < chatListView.getTop() || ev.getY() > chatListView.getBottom())) { ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); if (textSelectionHelper.getOverlayView(context).onTouchEvent(ev)) { ev.offsetLocation(selectionOverlay.getX(), selectionOverlay.getY()); return super.dispatchTouchEvent(ev); } else { return true; } } if (pinchToZoomHelper.isInOverlayMode()) { return pinchToZoomHelper.onTouchEvent(ev); } if (AvatarPreviewer.hasVisibleInstance()) { AvatarPreviewer.getInstance().onTouchEvent(ev); return true; } boolean r = false; if (isInPreviewMode() && allowExpandPreviewByClick) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { boolean pressedOnPageDownButtons = false; int[] off = new int[2]; getLocationInWindow(off); int[] pos = new int[2]; if (pagedownButton != null) { pagedownButton.getLocationInWindow(pos); AndroidUtilities.rectTmp2.set(pos[0] - off[0], pos[1] - off[1], pos[0] - off[0] + pagedownButton.getMeasuredWidth(), pos[1] - off[1] + pagedownButton.getMeasuredHeight()); if (AndroidUtilities.rectTmp2.contains((int) ev.getX(), (int) ev.getY())) { pressedOnPageDownButtons = true; } } if (!pressedOnPageDownButtons && mentiondownButton != null) { mentiondownButton.getLocationInWindow(pos); AndroidUtilities.rectTmp2.set(pos[0] - off[0], pos[1] - off[1], pos[0] - off[0] + mentiondownButton.getMeasuredWidth(), pos[1] - off[1] + mentiondownButton.getMeasuredHeight()); if (AndroidUtilities.rectTmp2.contains((int) ev.getX(), (int) ev.getY())) { pressedOnPageDownButtons = true; } } if (!pressedOnPageDownButtons) { x = ev.getX(); y = ev.getY(); pressTime = SystemClock.elapsedRealtime(); r = true; } else { pressTime = -1; } } else if (ev.getAction() == MotionEvent.ACTION_UP) { if (MathUtils.distance(x, y, ev.getX(), ev.getY()) < AndroidUtilities.dp(6) && SystemClock.elapsedRealtime() - pressTime <= ViewConfiguration.getTapTimeout()) { parentLayout.expandPreviewFragment(); ev.setAction(MotionEvent.ACTION_CANCEL); } pressTime = -1; } else if (ev.getAction() == MotionEvent.ACTION_CANCEL) { pressTime = -1; } } return super.dispatchTouchEvent(ev) || r; } @Override protected void onDraw(Canvas canvas) { if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) != null) { return; } if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) == null && (instantCameraView.blurFullyDrawing() || (blurredView != null && blurredView.fullyDrawing() && blurredView.getTag() != null))) { return; } super.onDraw(canvas); } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if ((scrimView != null || messageEnterTransitionContainer.isRunning()) && (child == pagedownButton || child == mentiondownButton || child == floatingDateView || child == fireworksOverlay || child == reactionsMentiondownButton || child == gifHintTextView || child == undoView || child == topUndoView)) { return false; } if (child == fragmentContextView && fragmentContextView.isCallStyle()) { return true; } if (child == undoView && PhotoViewer.getInstance().isVisible()) { return true; } if (toPullingDownTransition && child == chatListView) { return true; } if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) != null) { boolean needBlur; if (((int) getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND)) == BlurBehindDrawable.STATIC_CONTENT) { needBlur = child == actionBar || child == fragmentContextView || child == pinnedMessageView; } else { needBlur = child == chatListView || child == chatActivityEnterView || chatActivityEnterView.isPopupView(child); } if (!needBlur) { return false; } } else if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) == null && (instantCameraView.blurFullyDrawing() || (blurredView != null && blurredView.fullyDrawing() && blurredView.getTag() != null))) { boolean needBlur = child == actionBar || child == chatListView || child == pinnedMessageView || child == fragmentContextView; if (needBlur) { return false; } } boolean result; MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); boolean isRoundVideo = false; boolean isVideo = messageObject != null && messageObject.eventId == 0 && ((isRoundVideo = messageObject.isRoundVideo()) || messageObject.isVideo()); if (child == videoPlayerContainer) { canvas.save(); float transitionOffset = 0; if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; } canvas.translate(0, -pullingDownOffset - transitionOffset); if (messageObject != null && messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { if (Theme.chat_roundVideoShadow != null && aspectRatioFrameLayout.isDrawingReady()) { int x = (int) child.getX() - AndroidUtilities.dp(3); int y = (int) child.getY() - AndroidUtilities.dp(2); canvas.save(); canvas.scale(videoPlayerContainer.getScaleX(), videoPlayerContainer.getScaleY(), child.getX(), child.getY()); Theme.chat_roundVideoShadow.setAlpha(255); Theme.chat_roundVideoShadow.setBounds(x, y, x + AndroidUtilities.roundPlayingMessageSize + AndroidUtilities.dp(6), y + AndroidUtilities.roundPlayingMessageSize + AndroidUtilities.dp(6)); Theme.chat_roundVideoShadow.draw(canvas); canvas.restore(); } result = super.drawChild(canvas, child, drawingTime); } else { if (child.getTag() == null) { float oldTranslation = child.getTranslationY(); child.setTranslationY(-AndroidUtilities.dp(1000)); result = super.drawChild(canvas, child, drawingTime); child.setTranslationY(oldTranslation); } else { result = false; } } canvas.restore(); } else { result = super.drawChild(canvas, child, drawingTime); if (isVideo && child == chatListView && messageObject.type != 5 && videoPlayerContainer != null && videoPlayerContainer.getTag() != null) { canvas.save(); float transitionOffset = 0; if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; } canvas.translate(0, -pullingDownOffset - transitionOffset + pullingBottomOffset); super.drawChild(canvas, videoPlayerContainer, drawingTime); if (drawLaterRoundProgressCell != null) { canvas.save(); canvas.translate(drawLaterRoundProgressCell.getX(), drawLaterRoundProgressCell.getTop() + chatListView.getY()); if (isRoundVideo) { drawLaterRoundProgressCell.drawRoundProgress(canvas); invalidate(); drawLaterRoundProgressCell.invalidate(); } else { drawLaterRoundProgressCell.drawOverlays(canvas); if (drawLaterRoundProgressCell.needDrawTime()) { drawLaterRoundProgressCell.drawTime(canvas, drawLaterRoundProgressCell.getAlpha(), true); } } canvas.restore(); } canvas.restore(); } } if (child == actionBar && parentLayout != null) { parentLayout.drawHeaderShadow(canvas, actionBar.getVisibility() == VISIBLE ? (int) actionBar.getTranslationY() + actionBar.getMeasuredHeight() + (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) : 0); } return result; } @Override protected boolean isActionBarVisible() { return actionBar.getVisibility() == VISIBLE; } private void drawChildElement(Canvas canvas, float listTop, ChatMessageCell cell, int type) { canvas.save(); float canvasOffsetX = chatListView.getLeft() + cell.getLeft(); float canvasOffsetY = chatListView.getY() + cell.getY(); float alpha = cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f; canvas.clipRect(chatListView.getLeft(), listTop, chatListView.getRight(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset); canvas.translate(canvasOffsetX, canvasOffsetY); cell.setInvalidatesParent(true); if (type == 0) { cell.drawTime(canvas, alpha, true); } else if (type == 1) { cell.drawNamesLayout(canvas, alpha); } else { cell.drawCaptionLayout(canvas, cell.getCurrentPosition() != null && (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0, alpha); } cell.setInvalidatesParent(false); canvas.restore(); } @Override protected void dispatchDraw(Canvas canvas) { chatActivityEnterView.checkAnimation(); updateChatListViewTopPadding(); if (invalidateMessagesVisiblePart || (chatListItemAnimator != null && chatListItemAnimator.isRunning())) { invalidateMessagesVisiblePart = false; updateMessagesVisiblePart(false); } updateTextureViewPosition(false); updatePagedownButtonsPosition(); super.dispatchDraw(canvas); if (fragmentContextView != null && fragmentContextView.isCallStyle()) { float alpha = (blurredView != null && blurredView.getVisibility() == View.VISIBLE) ? 1f - blurredView.getAlpha() : 1f; if (alpha > 0) { if (alpha == 1f) { canvas.save(); } else { canvas.saveLayerAlpha(fragmentContextView.getX(), fragmentContextView.getY() - AndroidUtilities.dp(30), fragmentContextView.getX() + fragmentContextView.getMeasuredWidth(), fragmentContextView.getY() + fragmentContextView.getMeasuredHeight(), (int) (255 * alpha), Canvas.ALL_SAVE_FLAG); } canvas.translate(fragmentContextView.getX(), fragmentContextView.getY()); fragmentContextView.setDrawOverlay(true); fragmentContextView.draw(canvas); fragmentContextView.setDrawOverlay(false); canvas.restore(); } } if (chatActivityEnterView != null) { if (chatActivityEnterView.panelAnimationInProgress() && chatActivityEnterView.getEmojiPadding() < bottomPanelTranslationY) { int color = getThemedColor(Theme.key_chat_emojiPanelBackground); if (backgroundPaint == null) { backgroundPaint = new Paint(); } if (backgroundColor != color) { backgroundPaint.setColor(backgroundColor = color); } int offset = (int) (bottomPanelTranslationY - chatActivityEnterView.getEmojiPadding()) + 3; canvas.drawRect(0, getMeasuredHeight() - offset, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); setFragmentPanTranslationOffset(chatActivityEnterView.getEmojiPadding()); } } for (int a = 0, N = animateSendingViews.size(); a < N; a++) { ChatMessageCell cell = animateSendingViews.get(a); MessageObject.SendAnimationData data = cell.getMessageObject().sendAnimationData; if (data != null) { canvas.save(); ImageReceiver imageReceiver = cell.getPhotoImage(); canvas.translate(data.currentX, data.currentY); canvas.scale(data.currentScale, data.currentScale); canvas.translate(-imageReceiver.getCenterX(), -imageReceiver.getCenterY()); cell.setTimeAlpha(data.timeAlpha); animateSendingViews.get(a).draw(canvas); canvas.restore(); } } if (scrimViewReaction == null || scrimView == null) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (scrimView != null ? scrimViewAlpha : 1f))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } if (scrimView != null) { if (scrimView == reactionsMentiondownButton || scrimView == mentiondownButton) { if (scrimViewAlpha < 1f) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (1f - scrimViewAlpha))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } } else if (scrimView instanceof ImageView) { int c = canvas.save(); if (scrimViewAlpha < 1f) { canvas.saveLayerAlpha(scrimView.getLeft(), scrimView.getTop(), scrimView.getRight(), scrimView.getBottom(), (int) (255 * scrimViewAlpha), Canvas.ALL_SAVE_FLAG); } canvas.translate(scrimView.getLeft(), scrimView.getTop()); if (scrimView == actionBar.getBackButton()) { int r = Math.max(scrimView.getMeasuredWidth(), scrimView.getMeasuredHeight()) / 2; canvas.drawCircle(r, r, r * 0.7f, actionBarBackgroundPaint); } scrimView.draw(canvas); canvas.restoreToCount(c); if (scrimViewAlpha < 1f) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (1f - scrimViewAlpha))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } } else { float listTop = chatListView.getY() + chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4); MessageObject.GroupedMessages scrimGroup; if (scrimView instanceof ChatMessageCell) { scrimGroup = ((ChatMessageCell) scrimView).getCurrentMessagesGroup(); } else { scrimGroup = null; } boolean groupedBackgroundWasDraw = false; int count = chatListView.getChildCount(); for (int num = 0; num < count; num++) { View child = chatListView.getChildAt(num); MessageObject.GroupedMessages group; MessageObject.GroupedMessagePosition position; ChatMessageCell cell; if (child instanceof ChatMessageCell) { cell = (ChatMessageCell) child; group = cell.getCurrentMessagesGroup(); position = cell.getCurrentPosition(); } else { position = null; group = null; cell = null; } if (child != scrimView && (scrimGroup == null || scrimGroup != group) || child.getAlpha() == 0f) { continue; } if (!groupedBackgroundWasDraw && cell != null && scrimGroup != null && scrimGroup.transitionParams.cell != null) { float x = scrimGroup.transitionParams.cell.getNonAnimationTranslationX(true); float l = (scrimGroup.transitionParams.left + x + scrimGroup.transitionParams.offsetLeft); float t = (scrimGroup.transitionParams.top + scrimGroup.transitionParams.offsetTop); float r = (scrimGroup.transitionParams.right + x + scrimGroup.transitionParams.offsetRight); float b = (scrimGroup.transitionParams.bottom + scrimGroup.transitionParams.offsetBottom); if (!scrimGroup.transitionParams.backgroundChangeBounds) { t += scrimGroup.transitionParams.cell.getTranslationY(); b += scrimGroup.transitionParams.cell.getTranslationY(); } if (t < chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(20)) { t = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(20); } if (b > chatListView.getMeasuredHeight() + AndroidUtilities.dp(20)) { b = chatListView.getMeasuredHeight() + AndroidUtilities.dp(20); } boolean selected = true; for (int a = 0, N = scrimGroup.messages.size(); a < N; a++) { MessageObject object = scrimGroup.messages.get(a); int index = object.getDialogId() == dialog_id ? 0 : 1; if (selectedMessagesIds[index].indexOfKey(object.getId()) < 0) { selected = false; break; } } canvas.save(); canvas.clipRect(0, listTop + (mentionContainer != null ? mentionContainer.clipTop() : 0), getMeasuredWidth(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset - (mentionContainer != null ? mentionContainer.clipBottom() : 0)); canvas.translate(0, chatListView.getY()); scrimGroup.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, scrimGroup.transitionParams.pinnedTop, scrimGroup.transitionParams.pinnedBotton, selected, contentView.getKeyboardHeight()); canvas.restore(); groupedBackgroundWasDraw = true; } if (cell != null && cell.getPhotoImage().isAnimationRunning()) { invalidate(); } float viewClipLeft = chatListView.getLeft(); float viewClipTop = listTop; float viewClipRight = chatListView.getRight(); float viewClipBottom = chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset; if (mentionContainer != null) { viewClipTop += mentionContainer.clipTop(); viewClipBottom -= mentionContainer.clipBottom(); } if (cell == null || !cell.getTransitionParams().animateBackgroundBoundsInner) { viewClipLeft = Math.max(viewClipLeft, chatListView.getLeft() + child.getX()); viewClipTop = Math.max(viewClipTop, chatListView.getTop() + child.getY()); viewClipRight = Math.min(viewClipRight, chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); viewClipBottom = Math.min(viewClipBottom, chatListView.getY() + child.getY() + child.getMeasuredHeight()); } if (viewClipTop < viewClipBottom) { if (child.getAlpha() != 1f) { canvas.saveLayerAlpha(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom, (int) (255 * child.getAlpha()), Canvas.ALL_SAVE_FLAG); } else { canvas.save(); } if (cell != null) { cell.setInvalidatesParent(true); cell.setScrimReaction(scrimViewReaction); } canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY()); if (cell != null && scrimGroup == null && cell.drawBackgroundInParent()) { cell.drawBackgroundInternal(canvas, true); } child.draw(canvas); if (cell != null && cell.hasOutboundsContent()) { cell.drawOutboundsContent(canvas); } canvas.restore(); if (cell != null) { cell.setInvalidatesParent(false); cell.setScrimReaction(null); } } if (position != null || (cell != null && cell.getTransitionParams().animateBackgroundBoundsInner)) { if (position == null || position.last || position.minX == 0 && position.minY == 0) { if (position == null || position.last) { drawTimeAfter.add(cell); } if (position == null || (position.minX == 0 && position.minY == 0 && cell.hasNameLayout())) { drawNamesAfter.add(cell); } } if (position == null || (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { drawCaptionAfter.add(cell); } } if (scrimViewReaction != null && cell != null) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); if (viewClipTop < viewClipBottom) { float alpha = child.getAlpha() * scrimViewAlpha; if (alpha < 1f) { canvas.saveLayerAlpha(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom, (int) (255 * alpha), Canvas.ALL_SAVE_FLAG); } else { canvas.save(); } canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY()); cell.drawScrimReaction(canvas, scrimViewReaction); canvas.restore(); } } } int size = drawTimeAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { drawChildElement(canvas, listTop, drawTimeAfter.get(a), 0); } drawTimeAfter.clear(); } size = drawNamesAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { drawChildElement(canvas, listTop, drawNamesAfter.get(a), 1); } drawNamesAfter.clear(); } size = drawCaptionAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawCaptionAfter.get(a); if (cell.getCurrentPosition() == null && !cell.getTransitionParams().animateBackgroundBoundsInner) { continue; } drawChildElement(canvas, listTop, cell, 2); } drawCaptionAfter.clear(); } } if (scrimViewReaction == null && scrimViewAlpha < 1f) { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * (1f - scrimViewAlpha))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } } if (scrimView != null || messageEnterTransitionContainer.isRunning()) { if (mentionContainer == null || mentionContainer.getVisibility() != View.VISIBLE) { if (pagedownButton != null && pagedownButton.getTag() != null) { super.drawChild(canvas, pagedownButton, SystemClock.uptimeMillis()); } if (mentiondownButton != null && mentiondownButton.getTag() != null) { super.drawChild(canvas, mentiondownButton, SystemClock.uptimeMillis()); } if (reactionsMentiondownButton != null && reactionsMentiondownButton.getTag() != null) { super.drawChild(canvas, reactionsMentiondownButton, SystemClock.uptimeMillis()); } } if (floatingDateView != null && floatingDateView.getTag() != null) { super.drawChild(canvas, floatingDateView, SystemClock.uptimeMillis()); } if (fireworksOverlay != null) { super.drawChild(canvas, fireworksOverlay, SystemClock.uptimeMillis()); } if (gifHintTextView != null) { super.drawChild(canvas, gifHintTextView, SystemClock.uptimeMillis()); } if (undoView != null && undoView.getVisibility() == View.VISIBLE) { super.drawChild(canvas, undoView, SystemClock.uptimeMillis()); } if (topUndoView != null && undoView.getVisibility() == View.VISIBLE) { super.drawChild(canvas, topUndoView, SystemClock.uptimeMillis()); } } if (fixedKeyboardHeight > 0 && keyboardHeight < AndroidUtilities.dp(20)) { int color = getThemedColor(Theme.key_windowBackgroundWhite); if (backgroundPaint == null) { backgroundPaint = new Paint(); } if (backgroundColor != color) { backgroundPaint.setColor(backgroundColor = color); } canvas.drawRect(0,getMeasuredHeight() - fixedKeyboardHeight, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); } if (pullingDownDrawable != null && pullingDownDrawable.needDrawBottomPanel()) { int top, bottom; if (chatActivityEnterView != null && chatActivityEnterView.getVisibility() == View.VISIBLE) { top = chatActivityEnterView.getTop() + AndroidUtilities.dp2(2); bottom = chatActivityEnterView.getBottom(); } else { top = bottomOverlayChat.getTop() + AndroidUtilities.dp2(2); bottom = bottomOverlayChat.getBottom(); } top -= (int) ((pullingDownAnimateToActivity == null ? 0 : pullingDownAnimateToActivity.pullingBottomOffset) * pullingDownAnimateProgress); pullingDownDrawable.drawBottomPanel(canvas, top, bottom, getMeasuredWidth()); } if (pullingDownAnimateToActivity != null) { canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) (255 * pullingDownAnimateProgress), Canvas.ALL_SAVE_FLAG); pullingDownAnimateToActivity.fragmentView.draw(canvas); canvas.restore(); } emojiAnimationsOverlay.draw(canvas); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int allHeight; int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = allHeight = MeasureSpec.getSize(heightMeasureSpec); if (lastWidth != widthSize) { globalIgnoreLayout = true; lastWidth = widthMeasureSpec; if (!inPreviewMode && currentUser != null && currentUser.self) { SimpleTextView textView = avatarContainer.getTitleTextView(); int textWidth = (int) textView.getPaint().measureText(textView.getText(), 0, textView.getText().length()); if (widthSize - AndroidUtilities.dp(96 + 56) > textWidth + AndroidUtilities.dp(10)) { showSearchAsIcon = !showAudioCallAsIcon; } else { showSearchAsIcon = false; } } else { showSearchAsIcon = false; } if (showSearchAsIcon || showAudioCallAsIcon) { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { ((MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(96); } } else { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { ((MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(40); } } if (showSearchAsIcon) { if (!actionBar.isSearchFieldVisible() && searchIconItem != null) { searchIconItem.setVisibility(View.VISIBLE); } if (headerItem != null) { headerItem.hideSubItem(search); } } else { if (headerItem != null) { headerItem.showSubItem(search); } if (searchIconItem != null) { searchIconItem.setVisibility(View.GONE); } } if (!actionBar.isSearchFieldVisible() && audioCallIconItem != null) { audioCallIconItem.setVisibility((showAudioCallAsIcon && !showSearchAsIcon) ? View.VISIBLE : View.GONE); } if (headerItem != null) { TLRPC.UserFull userInfo = getCurrentUserInfo(); if (showAudioCallAsIcon) { headerItem.hideSubItem(call); } else if (userInfo != null && userInfo.phone_calls_available) { headerItem.showSubItem(call, true); } } globalIgnoreLayout = false; } setMeasuredDimension(widthSize, heightSize); heightSize -= getPaddingTop(); measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); int actionBarHeight = actionBar.getMeasuredHeight(); if (actionBar.getVisibility() == VISIBLE) { heightSize -= actionBarHeight; } int keyboardHeightOld = keyboardHeight + chatEmojiViewPadding; boolean keyboardVisibleOld = keyboardHeight + chatEmojiViewPadding >= AndroidUtilities.dp(20); if (lastHeight != allHeight) { measureKeyboardHeight(); } int keyboardSize = getKeyboardHeight(); if (fixedKeyboardHeight > 0 && keyboardSize <= AndroidUtilities.dp(20)) { chatEmojiViewPadding = fixedKeyboardHeight; } else { if (keyboardSize <= AndroidUtilities.dp(20)) { chatEmojiViewPadding = chatActivityEnterView.isPopupShowing() ? chatActivityEnterView.getEmojiPadding() : 0; } else { chatEmojiViewPadding = 0; } } setEmojiKeyboardHeight(chatEmojiViewPadding); boolean keyboardVisible = keyboardHeight + chatEmojiViewPadding >= AndroidUtilities.dp(20); boolean waitingChatListItemAnimator = false; if (MediaController.getInstance().getPlayingMessageObject() != null && MediaController.getInstance().getPlayingMessageObject().isRoundVideo() && keyboardVisibleOld != keyboardVisible) { for (int i = 0; i < chatListView.getChildCount(); i++) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; MessageObject messageObject = cell.getMessageObject(); if (messageObject.isRoundVideo() && MediaController.getInstance().isPlayingMessage(messageObject)) { int p = chatListView.getChildAdapterPosition(child); if (p >= 0) { chatLayoutManager.scrollToPositionWithOffset(p, (int) ((chatListView.getMeasuredHeight() - chatListViewPaddingTop - blurredViewBottomOffset + (keyboardHeight + chatEmojiViewPadding - keyboardHeightOld) - (keyboardVisible ? AndroidUtilities.roundMessageSize : AndroidUtilities.roundPlayingMessageSize)) / 2), false); chatAdapter.notifyItemChanged(p); adjustPanLayoutHelper.delayAnimation(); waitingChatListItemAnimator = true; break; } } } } } if (!waitingChatListItemAnimator) { chatActivityEnterView.runEmojiPanelAnimation(); } int childCount = getChildCount(); measureChildWithMargins(chatActivityEnterView, widthMeasureSpec, 0, heightMeasureSpec, 0); int listViewTopHeight; if (inPreviewMode) { inputFieldHeight = 0; listViewTopHeight = 0; } else { inputFieldHeight = chatActivityEnterView.getMeasuredHeight(); listViewTopHeight = AndroidUtilities.dp(49); } blurredViewTopOffset = 0; blurredViewBottomOffset = 0; if (SharedConfig.chatBlurEnabled()) { blurredViewTopOffset = actionBarHeight; blurredViewBottomOffset = AndroidUtilities.dp(203); } for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child == null || child.getVisibility() == GONE || child == chatActivityEnterView || child == actionBar) { continue; } if (child == backgroundView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(allHeight, MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == blurredView) { int h = allHeight; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { h += keyboardSize; } int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == chatListView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int h = heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) + blurredViewTopOffset + blurredViewBottomOffset; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { h += keyboardSize; } int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), h), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == progressView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - inputFieldHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.dp(2 + (chatActivityEnterView.isTopViewVisible() ? 48 : 0))), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == instantCameraView || child == overlayView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(allHeight - inputFieldHeight - chatEmojiViewPadding + AndroidUtilities.dp(3), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == emptyViewContainer) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == messagesSearchListView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(allHeight - actionBarHeight - AndroidUtilities.dp(48), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (chatActivityEnterView.isPopupView(child)) { if (inBubbleMode) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize - inputFieldHeight + actionBarHeight + getPaddingTop(), MeasureSpec.EXACTLY)); } else if (AndroidUtilities.isInMultiwindow) { if (AndroidUtilities.isTablet()) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(320), heightSize - inputFieldHeight + actionBarHeight - AndroidUtilities.statusBarHeight + getPaddingTop()), MeasureSpec.EXACTLY)); } else { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize - inputFieldHeight + actionBarHeight - AndroidUtilities.statusBarHeight + getPaddingTop(), MeasureSpec.EXACTLY)); } } else { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, MeasureSpec.EXACTLY)); } } else if (child == mentionContainer) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mentionContainer.getLayoutParams(); if (mentionContainer.getAdapter().isBannedInline()) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST)); } else { int height; mentionContainer.setIgnoreLayout(true); LinearLayoutManager layoutManager = mentionContainer.getCurrentLayoutManager(); if (layoutManager instanceof ExtendedGridLayoutManager) { int size = ((ExtendedGridLayoutManager) layoutManager).getRowsCount(widthSize); int maxHeight = size * 102; if (mentionContainer.getAdapter().isBotContext()) { if (mentionContainer.getAdapter().getBotContextSwitch() != null) { maxHeight += 34; } } height = heightSize - chatActivityEnterView.getMeasuredHeight() + (maxHeight != 0 ? AndroidUtilities.dp(2) : 0); int padding = Math.max(0, height - AndroidUtilities.dp(Math.min(maxHeight, 68 * 1.8f))); } else { int size = mentionContainer.getAdapter().getLastItemCount(); int maxHeight = 0; if (mentionContainer.getAdapter().isBotContext()) { if (mentionContainer.getAdapter().getBotContextSwitch() != null) { maxHeight += 36; size -= 1; } maxHeight += size * 68; } else { maxHeight += size * 36; } height = heightSize - chatActivityEnterView.getMeasuredHeight() + (maxHeight != 0 ? AndroidUtilities.dp(2) : 0); } layoutParams.height = height; layoutParams.topMargin = 0; mentionContainer.setIgnoreLayout(false); child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY)); } mentionContainer.setTranslationY(chatActivityEnterView.getAnimatedTop()); } else if (child == textSelectionHelper.getOverlayView(context)) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int h = heightSize + blurredViewTopOffset; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { h += keyboardSize; textSelectionHelper.setKeyboardSize(keyboardSize); } else { textSelectionHelper.setKeyboardSize(0); } child.measure(contentWidthSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); } else if (child == forwardingPreviewView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int h = allHeight - AndroidUtilities.statusBarHeight; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { h += keyboardSize; } int contentHeightSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else { measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); } } if (fixPaddingsInLayout) { globalIgnoreLayout = true; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); fixPaddingsInLayout = false; chatListView.measure(MeasureSpec.makeMeasureSpec(chatListView.getMeasuredWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(chatListView.getMeasuredHeight(), MeasureSpec.EXACTLY)); globalIgnoreLayout = false; } if (scrollToPositionOnRecreate != -1) { final int scrollTo = scrollToPositionOnRecreate; AndroidUtilities.runOnUIThread(() -> chatLayoutManager.scrollToPositionWithOffset(scrollTo, scrollToOffsetOnRecreate)); scrollToPositionOnRecreate = -1; } updateBulletinLayout(); lastHeight = allHeight; } @Override public void requestLayout() { if (globalIgnoreLayout) { return; } super.requestLayout(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); int keyboardSize = getKeyboardHeight(); int paddingBottom; if (fixedKeyboardHeight > 0 && keyboardSize <= AndroidUtilities.dp(20)) { paddingBottom = fixedKeyboardHeight; } else { paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : 0; } if (!SharedConfig.smoothKeyboard) { setBottomClip(paddingBottom); } for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child == null || child.getVisibility() == GONE) { continue; } final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final int width = child.getMeasuredWidth(); final int height = child.getMeasuredHeight(); int childLeft; int childTop; int gravity = lp.gravity; if (gravity == -1) { gravity = Gravity.TOP | Gravity.LEFT; } final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.CENTER_HORIZONTAL: childLeft = (r - l - width) / 2 + lp.leftMargin - lp.rightMargin; break; case Gravity.RIGHT: childLeft = r - width - lp.rightMargin; break; case Gravity.LEFT: default: childLeft = lp.leftMargin; } switch (verticalGravity) { case Gravity.TOP: childTop = lp.topMargin + getPaddingTop(); if (child != actionBar && actionBar.getVisibility() == VISIBLE) { childTop += actionBar.getMeasuredHeight(); if (inPreviewMode && Build.VERSION.SDK_INT >= 21) { childTop += AndroidUtilities.statusBarHeight; } } break; case Gravity.CENTER_VERTICAL: childTop = ((b - paddingBottom) - t - height) / 2 + lp.topMargin - lp.bottomMargin; break; case Gravity.BOTTOM: childTop = ((b - paddingBottom) - t) - height - lp.bottomMargin; break; default: childTop = lp.topMargin; } if (child == blurredView || child == backgroundView) { childTop = 0; } else if (child instanceof HintView || child instanceof ChecksHintView) { childTop = 0; } else if (child == mentionContainer) { childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2); mentionContainer.setTranslationY(chatActivityEnterView.getAnimatedTop()); } else if (child == pagedownButton || child == mentiondownButton || child == reactionsMentiondownButton) { if (!inPreviewMode) { childTop -= chatActivityEnterView.getMeasuredHeight(); } } else if (child == emptyViewContainer) { childTop -= inputFieldHeight / 2 - (actionBar.getVisibility() == VISIBLE ? actionBar.getMeasuredHeight() / 2 : 0); } else if (chatActivityEnterView.isPopupView(child)) { if (AndroidUtilities.isInMultiwindow || inBubbleMode) { childTop = chatActivityEnterView.getTop() - child.getMeasuredHeight() + AndroidUtilities.dp(1); } else { childTop = chatActivityEnterView.getBottom(); } } else if (child == gifHintTextView || child == voiceHintTextView || child == mediaBanTooltip) { childTop -= inputFieldHeight; } else if (child == chatListView || child == floatingDateView || child == infoTopView) { childTop -= blurredViewTopOffset; if (!inPreviewMode) { childTop -= (inputFieldHeight - AndroidUtilities.dp(51)); } childTop -= paddingBottom; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { childTop -= keyboardSize; } } else if (child == progressView) { if (chatActivityEnterView.isTopViewVisible()) { childTop -= AndroidUtilities.dp(48); } } else if (child == actionBar) { if (inPreviewMode && Build.VERSION.SDK_INT >= 21) { childTop += AndroidUtilities.statusBarHeight; } childTop -= getPaddingTop(); } else if (child == videoPlayerContainer) { childTop = actionBar.getMeasuredHeight(); childTop -= paddingBottom; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { childTop -= keyboardSize; } } else if (child == instantCameraView || child == overlayView || child == animatingImageView) { childTop = 0; } else if (child == textSelectionHelper.getOverlayView(context)) { childTop -= paddingBottom; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { childTop -= keyboardSize; } childTop -= blurredViewTopOffset; } else if (chatActivityEnterView != null && child == chatActivityEnterView.botCommandsMenuContainer) { childTop -= inputFieldHeight; } else if (child == forwardingPreviewView) { childTop = AndroidUtilities.statusBarHeight; } child.layout(childLeft, childTop, childLeft + width, childTop + height); } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); updateTextureViewPosition(false); if (!scrollingChatListView) { checkAutoDownloadMessages(false); } notifyHeightChanged(); } private void setNonNoveTranslation(float y) { contentView.setTranslationY(y); actionBar.setTranslationY(0); emptyViewContainer.setTranslationY(0); progressView.setTranslationY(0); contentPanTranslation = 0; contentView.setBackgroundTranslation(0); instantCameraView.onPanTranslationUpdate(0); if (blurredView != null) { blurredView.drawable.onPanTranslationUpdate(0); } setFragmentPanTranslationOffset(0); invalidateChatListViewTopPadding(); } @Override public void setPadding(int left, int top, int right, int bottom) { contentPaddingTop = top; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == 1 && forwardingPreviewView != null && forwardingPreviewView.isShowing()) { forwardingPreviewView.dismiss(true); return true; } return super.dispatchKeyEvent(event); } protected Drawable getNewDrawable() { Drawable drawable = themeDelegate.getWallpaperDrawable(); return drawable != null ? drawable : super.getNewDrawable(); } }; contentView = (SizeNotifierFrameLayout) fragmentView; contentView.needBlur = true; contentView.needBlurBottom = true; if (inBubbleMode) { contentView.setOccupyStatusBar(false); } contentView.setBackgroundImage(Theme.getCachedWallpaper(), Theme.isWallpaperMotion()); emptyViewContainer = new FrameLayout(context); emptyViewContainer.setVisibility(View.INVISIBLE); contentView.addView(emptyViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); emptyViewContainer.setOnTouchListener((v, event) -> true); int distance = getArguments().getInt("nearby_distance", -1); if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null && !userBlocked) { greetingsViewContainer = new ChatGreetingsView(context, currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, null, true, 0); }); greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(10), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0)); } else if (currentEncryptedChat == null) { if (!isThreadChat() && chatMode == 0 && ((currentUser != null && currentUser.self) || (currentChat != null && currentChat.creator && !ChatObject.isChannelAndNotMegaGroup(currentChat)))) { bigEmptyView = new ChatBigEmptyView(context, contentView, currentChat != null ? ChatBigEmptyView.EMPTY_VIEW_TYPE_GROUP : ChatBigEmptyView.EMPTY_VIEW_TYPE_SAVED, themeDelegate); emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); if (currentChat != null) { bigEmptyView.setStatusText(AndroidUtilities.replaceTags(LocaleController.getString("GroupEmptyTitle1", R.string.GroupEmptyTitle1))); } } else { String emptyMessage = null; if (isThreadChat()) { if (isComments) { emptyMessage = LocaleController.getString("NoComments", R.string.NoComments); } else { emptyMessage = LocaleController.getString("NoReplies", R.string.NoReplies); } } else if (chatMode == MODE_SCHEDULED) { emptyMessage = LocaleController.getString("NoScheduledMessages", R.string.NoScheduledMessages); } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { emptyMessage = LocaleController.getString("GotAQuestion", R.string.GotAQuestion); } else if (currentUser == null || currentUser.self || currentUser.deleted || userBlocked) { emptyMessage = LocaleController.getString("NoMessages", R.string.NoMessages); } if (emptyMessage == null) { greetingsViewContainer = new ChatGreetingsView(context, currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, null, true, 0); }); greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(10), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0)); } else { emptyView = new TextView(context); emptyView.setText(emptyMessage); emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(getThemedColor(Theme.key_chat_serviceText)); emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); emptyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(3)); emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } } } else { bigEmptyView = new ChatBigEmptyView(context, contentView, ChatBigEmptyView.EMPTY_VIEW_TYPE_SECRET, themeDelegate); if (currentEncryptedChat.admin_id == getUserConfig().getClientUserId()) { bigEmptyView.setStatusText(LocaleController.formatString("EncryptedPlaceholderTitleOutgoing", R.string.EncryptedPlaceholderTitleOutgoing, UserObject.getFirstName(currentUser))); } else { bigEmptyView.setStatusText(LocaleController.formatString("EncryptedPlaceholderTitleIncoming", R.string.EncryptedPlaceholderTitleIncoming, UserObject.getFirstName(currentUser))); } emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } CharSequence oldMessage; if (chatActivityEnterView != null) { chatActivityEnterView.onDestroy(); if (!chatActivityEnterView.isEditingMessage()) { oldMessage = chatActivityEnterView.getFieldText(); } else { oldMessage = null; } } else { oldMessage = null; } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().onDestroy(); } chatListView = new RecyclerListView(context, themeDelegate) { private int lastWidth; private final ArrayList drawTimeAfter = new ArrayList<>(); private final ArrayList drawNamesAfter = new ArrayList<>(); private final ArrayList drawCaptionAfter = new ArrayList<>(); private final ArrayList drawingGroups = new ArrayList<>(10); private boolean slideAnimationInProgress; private int startedTrackingX; private int startedTrackingY; private int startedTrackingPointerId; private long lastTrackingAnimationTime; private float trackAnimationProgress; private float endTrackingX; private boolean wasTrackingVibrate; private float replyButtonProgress; private long lastReplyButtonAnimationTime; private boolean ignoreLayout; private boolean invalidated; int lastH = 0; @Override public void requestLayout() { if (ignoreLayout) { return; } super.requestLayout(); } @Override public void setTranslationY(float translationY) { if (translationY != getTranslationY()) { super.setTranslationY(translationY); if (emptyViewContainer != null) { if (chatActivityEnterView != null && chatActivityEnterView.panelAnimationInProgress()) { emptyViewContainer.setTranslationY(translationY / 2f); } else { emptyViewContainer.setTranslationY(translationY / 1.7f); } } if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuContainer != null) { chatActivityEnterView.botCommandsMenuContainer.setTranslationY(translationY); } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (lastWidth != r - l) { lastWidth = r - l; hideHints(false); } int height = getMeasuredHeight(); if (lastH != height) { ignoreLayout = true; if (chatListItemAnimator != null) { chatListItemAnimator.endAnimations(); } chatScrollHelper.cancel(); ignoreLayout = false; lastH = height; } forceScrollToTop = false; if (textSelectionHelper != null && textSelectionHelper.isSelectionMode()) { textSelectionHelper.invalidate(); } } private void setGroupTranslationX(ChatMessageCell view, float dx) { MessageObject.GroupedMessages group = view.getCurrentMessagesGroup(); if (group == null) { return; } int count = getChildCount(); for (int a = 0; a < count; a++) { View child = getChildAt(a); if (child == view || !(child instanceof ChatMessageCell)) { continue; } ChatMessageCell cell = (ChatMessageCell) child; if (cell.getCurrentMessagesGroup() == group) { cell.setSlidingOffset(dx); cell.invalidate(); } } invalidate(); } @Override public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { if (scrimPopupWindow != null) { return false; } return super.requestChildRectangleOnScreen(child, rect, immediate); } @Override public boolean onInterceptTouchEvent(MotionEvent e) { textSelectionHelper.checkSelectionCancel(e); if (isFastScrollAnimationRunning()) { return false; } boolean result = super.onInterceptTouchEvent(e); if (actionBar.isActionModeShowed() || reportType >= 0) { return result; } processTouchEvent(e); return result; } @Override public void setItemAnimator(ItemAnimator animator) { if (isFastScrollAnimationRunning()) { return; } super.setItemAnimator(animator); } private void drawReplyButton(Canvas canvas) { if (slidingView == null) { return; } float translationX = slidingView.getNonAnimationTranslationX(false); long newTime = System.currentTimeMillis(); long dt = Math.min(17, newTime - lastReplyButtonAnimationTime); lastReplyButtonAnimationTime = newTime; boolean showing; if (showing = (translationX <= -AndroidUtilities.dp(50))) { if (replyButtonProgress < 1.0f) { replyButtonProgress += dt / 180.0f; if (replyButtonProgress > 1.0f) { replyButtonProgress = 1.0f; } else { invalidate(); } } } else { if (replyButtonProgress > 0.0f) { replyButtonProgress -= dt / 180.0f; if (replyButtonProgress < 0.0f) { replyButtonProgress = 0; } else { invalidate(); } } } int alpha; int alpha2; Paint chatActionBackgroundPaint = getThemedPaint(Theme.key_paint_chatActionBackground); int oldAlpha = chatActionBackgroundPaint.getAlpha(); float scale; if (showing) { if (replyButtonProgress <= 0.8f) { scale = 1.2f * (replyButtonProgress / 0.8f); } else { scale = 1.2f - 0.2f * ((replyButtonProgress - 0.8f) / 0.2f); } alpha = (int) Math.min(255, 255 * (replyButtonProgress / 0.8f)); alpha2 = (int) Math.min(oldAlpha, oldAlpha * (replyButtonProgress / 0.8f)); } else { scale = replyButtonProgress; alpha = (int) Math.min(255, 255 * replyButtonProgress); alpha2 = (int) Math.min(oldAlpha, oldAlpha * replyButtonProgress); } chatActionBackgroundPaint.setAlpha(alpha2); float x = getMeasuredWidth() + slidingView.getNonAnimationTranslationX(false) / 2; float y = slidingView.getTop() + slidingView.getMeasuredHeight() / 2; AndroidUtilities.rectTmp.set((int) (x - AndroidUtilities.dp(16) * scale), (int) (y - AndroidUtilities.dp(16) * scale), (int) (x + AndroidUtilities.dp(16) * scale), (int) (y + AndroidUtilities.dp(16) * scale)); Theme.applyServiceShaderMatrix(getMeasuredWidth(), AndroidUtilities.displaySize.y, 0, getY() + AndroidUtilities.rectTmp.top); canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16), AndroidUtilities.dp(16), chatActionBackgroundPaint); if (themeDelegate.hasGradientService()) { canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); } chatActionBackgroundPaint.setAlpha(oldAlpha); Drawable replyIconDrawable = getThemedDrawable(Theme.key_drawable_replyIcon); replyIconDrawable.setAlpha(alpha); replyIconDrawable.setBounds((int) (x - AndroidUtilities.dp(7) * scale), (int) (y - AndroidUtilities.dp(6) * scale), (int) (x + AndroidUtilities.dp(7) * scale), (int) (y + AndroidUtilities.dp(5) * scale)); replyIconDrawable.draw(canvas); replyIconDrawable.setAlpha(255); } private void processTouchEvent(MotionEvent e) { if (e != null) { wasManualScroll = true; } if (e != null && e.getAction() == MotionEvent.ACTION_DOWN && !startedTrackingSlidingView && !maybeStartTrackingSlidingView && slidingView == null && !inPreviewMode) { View view = getPressedChildView(); if (view instanceof ChatMessageCell) { if (slidingView != null) { slidingView.setSlidingOffset(0); } slidingView = (ChatMessageCell) view; MessageObject message = slidingView.getMessageObject(); if (chatMode != 0 || threadMessageObjects != null && threadMessageObjects.contains(message) || getMessageType(message) == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat)) || textSelectionHelper.isSelectionMode()) { slidingView.setSlidingOffset(0); slidingView = null; return; } startedTrackingPointerId = e.getPointerId(0); maybeStartTrackingSlidingView = true; startedTrackingX = (int) e.getX(); startedTrackingY = (int) e.getY(); } } else if (slidingView != null && e != null && e.getAction() == MotionEvent.ACTION_MOVE && e.getPointerId(0) == startedTrackingPointerId) { int dx = Math.max(AndroidUtilities.dp(-80), Math.min(0, (int) (e.getX() - startedTrackingX))); int dy = Math.abs((int) e.getY() - startedTrackingY); if (getScrollState() == SCROLL_STATE_IDLE && maybeStartTrackingSlidingView && !startedTrackingSlidingView && dx <= -AndroidUtilities.getPixelsInCM(0.4f, true) && Math.abs(dx) / 3 > dy) { MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); slidingView.onTouchEvent(event); super.onInterceptTouchEvent(event); event.recycle(); chatLayoutManager.setCanScrollVertically(false); maybeStartTrackingSlidingView = false; startedTrackingSlidingView = true; startedTrackingX = (int) e.getX(); if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } } else if (startedTrackingSlidingView) { if (Math.abs(dx) >= AndroidUtilities.dp(50)) { if (!wasTrackingVibrate) { try { performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignore) { } wasTrackingVibrate = true; } } else { wasTrackingVibrate = false; } slidingView.setSlidingOffset(dx); MessageObject messageObject = slidingView.getMessageObject(); if (messageObject.isRoundVideo() || messageObject.isVideo()) { updateTextureViewPosition(false); } setGroupTranslationX(slidingView, dx); invalidate(); } } else if (slidingView != null && (e == null || e.getPointerId(0) == startedTrackingPointerId && (e.getAction() == MotionEvent.ACTION_CANCEL || e.getAction() == MotionEvent.ACTION_UP || e.getAction() == MotionEvent.ACTION_POINTER_UP))) { if (e != null && e.getAction() != MotionEvent.ACTION_CANCEL && Math.abs(slidingView.getNonAnimationTranslationX(false)) >= AndroidUtilities.dp(50)) { showFieldPanelForReply(slidingView.getMessageObject()); } endTrackingX = slidingView.getSlidingOffsetX(); if (endTrackingX == 0) { slidingView = null; } lastTrackingAnimationTime = System.currentTimeMillis(); trackAnimationProgress = 0.0f; invalidate(); maybeStartTrackingSlidingView = false; startedTrackingSlidingView = false; chatLayoutManager.setCanScrollVertically(true); } } @Override public boolean onTouchEvent(MotionEvent e) { textSelectionHelper.checkSelectionCancel(e); if (e.getAction() == MotionEvent.ACTION_DOWN) { scrollByTouch = true; } if (pullingDownOffset != 0 && (e.getAction() == MotionEvent.ACTION_UP || e.getAction() == MotionEvent.ACTION_CANCEL)) { float progress = Math.min(1f, pullingDownOffset / AndroidUtilities.dp(110)); if (e.getAction() == MotionEvent.ACTION_UP && progress == 1 && pullingDownDrawable != null && !pullingDownDrawable.emptyStub) { if (pullingDownDrawable.animationIsRunning()) { ValueAnimator animator = ValueAnimator.ofFloat(pullingDownOffset, pullingDownOffset + AndroidUtilities.dp(8)); pullingDownBackAnimator = animator; animator.addUpdateListener(valueAnimator -> { pullingDownOffset = (float) valueAnimator.getAnimatedValue(); chatListView.invalidate(); }); animator.setDuration(200); animator.setInterpolator(CubicBezierInterpolator.DEFAULT); animator.start(); pullingDownDrawable.runOnAnimationFinish(() -> { animateToNextChat(); }); } else { animateToNextChat(); } } else { if (pullingDownDrawable != null && pullingDownDrawable.emptyStub && (System.currentTimeMillis() - pullingDownDrawable.lastShowingReleaseTime) < 500 && pullingDownDrawable.animateSwipeToRelease) { AnimatorSet animatorSet = new AnimatorSet(); pullingDownBackAnimator = animatorSet; if (pullingDownDrawable != null) { pullingDownDrawable.showBottomPanel(false); } ValueAnimator animator = ValueAnimator.ofFloat(pullingDownOffset, AndroidUtilities.dp(111)); animator.addUpdateListener(valueAnimator -> { pullingDownOffset = (float) valueAnimator.getAnimatedValue(); chatListView.invalidate(); }); animator.setDuration(400); animator.setInterpolator(CubicBezierInterpolator.DEFAULT); ValueAnimator animator2 = ValueAnimator.ofFloat(AndroidUtilities.dp(111), 0); animator2.addUpdateListener(valueAnimator -> { pullingDownOffset = (float) valueAnimator.getAnimatedValue(); chatListView.invalidate(); }); animator2.setStartDelay(600); animator2.setDuration(ChatListItemAnimator.DEFAULT_DURATION); animator2.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); animatorSet.playSequentially(animator, animator2); animatorSet.start(); } else { ValueAnimator animator = ValueAnimator.ofFloat(pullingDownOffset, 0); pullingDownBackAnimator = animator; if (pullingDownDrawable != null) { pullingDownDrawable.showBottomPanel(false); } animator.addUpdateListener(valueAnimator -> { pullingDownOffset = (float) valueAnimator.getAnimatedValue(); chatListView.invalidate(); }); animator.setDuration(ChatListItemAnimator.DEFAULT_DURATION); animator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); animator.start(); } } } if (isFastScrollAnimationRunning()) { return false; } boolean result = super.onTouchEvent(e); if (actionBar.isActionModeShowed() || reportType >= 0) { return result; } processTouchEvent(e); return startedTrackingSlidingView || result; } @Override public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { super.requestDisallowInterceptTouchEvent(disallowIntercept); if (slidingView != null) { processTouchEvent(null); } } @Override protected void onChildPressed(View child, float x, float y, boolean pressed) { super.onChildPressed(child, x, y, pressed); if (child instanceof ChatMessageCell) { ChatMessageCell chatMessageCell = (ChatMessageCell) child; MessageObject object = chatMessageCell.getMessageObject(); if (object.isMusic() || object.isDocument()) { return; } MessageObject.GroupedMessages groupedMessages = chatMessageCell.getCurrentMessagesGroup(); if (groupedMessages != null) { int count = getChildCount(); for (int a = 0; a < count; a++) { View item = getChildAt(a); if (item == child || !(item instanceof ChatMessageCell)) { continue; } ChatMessageCell cell = (ChatMessageCell) item; if (cell.getCurrentMessagesGroup() == groupedMessages) { cell.setPressed(pressed); } } } } } @Override public void onDraw(Canvas c) { super.onDraw(c); if (slidingView != null) { float translationX = slidingView.getSlidingOffsetX(); if (!maybeStartTrackingSlidingView && !startedTrackingSlidingView && endTrackingX != 0 && translationX != 0) { long newTime = System.currentTimeMillis(); long dt = newTime - lastTrackingAnimationTime; trackAnimationProgress += dt / 180.0f; if (trackAnimationProgress > 1.0f) { trackAnimationProgress = 1.0f; } lastTrackingAnimationTime = newTime; translationX = endTrackingX * (1.0f - AndroidUtilities.decelerateInterpolator.getInterpolation(trackAnimationProgress)); if (translationX == 0) { endTrackingX = 0; } setGroupTranslationX(slidingView, translationX); slidingView.setSlidingOffset(translationX); MessageObject messageObject = slidingView.getMessageObject(); if (messageObject.isRoundVideo() || messageObject.isVideo()) { updateTextureViewPosition(false); } if (trackAnimationProgress == 1f || trackAnimationProgress == 0f) { slidingView.setSlidingOffset(0); slidingView = null; } invalidate(); } drawReplyButton(c); } if (pullingDownOffset != 0 && !isInPreviewMode()) { c.save(); float transitionOffset = 0; if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset + (pullingDownAnimateToActivity == null ? 0 : pullingDownAnimateToActivity.pullingBottomOffset)) * pullingDownAnimateProgress; } c.translate(0, getMeasuredHeight() - blurredViewBottomOffset - transitionOffset); if (pullingDownDrawable == null) { pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, themeDelegate); pullingDownDrawable.onAttach(); } pullingDownDrawable.setWidth(getMeasuredWidth()); float progress = Math.min(1f, pullingDownOffset / AndroidUtilities.dp(110)); pullingDownDrawable.draw(c, chatListView, progress, 1f - pullingDownAnimateProgress); c.restore(); if (pullingDownAnimateToActivity != null) { c.saveLayerAlpha(0, 0, pullingDownAnimateToActivity.chatListView.getMeasuredWidth(), pullingDownAnimateToActivity.chatListView.getMeasuredHeight(), (int) (255 * pullingDownAnimateProgress), Canvas.ALL_SAVE_FLAG); c.translate(0, getMeasuredHeight() - pullingDownOffset - transitionOffset); pullingDownAnimateToActivity.chatListView.draw(c); c.restore(); } } else if (pullingDownDrawable != null) { pullingDownDrawable.reset(); } } @Override protected void dispatchDraw(Canvas canvas) { drawLaterRoundProgressCell = null; invalidated = false; canvas.save(); if (fragmentTransition == null || (fromPullingDownTransition && !toPullingDownTransition)) { canvas.clipRect(0, chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4), getMeasuredWidth(), getMeasuredHeight() - blurredViewBottomOffset); } selectorRect.setEmpty(); if (pullingDownOffset != 0) { canvas.save(); float transitionOffset = 0; if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; } canvas.translate(0, drawingChatLisViewYoffset = -pullingDownOffset - transitionOffset); drawChatBackgroundElements(canvas); super.dispatchDraw(canvas); drawChatForegroundElements(canvas); canvas.restore(); } else { drawChatBackgroundElements(canvas); super.dispatchDraw(canvas); drawChatForegroundElements(canvas); } canvas.restore(); } private void drawChatForegroundElements(Canvas canvas) { int size = drawTimeAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawTimeAfter.get(a); canvas.save(); canvas.translate(cell.getLeft() + cell.getNonAnimationTranslationX(false), cell.getY()); cell.drawTime(canvas, cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f, true); canvas.restore(); } drawTimeAfter.clear(); } size = drawNamesAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawNamesAfter.get(a); float canvasOffsetX = cell.getLeft() + cell.getNonAnimationTranslationX(false); float canvasOffsetY = cell.getY(); float alpha = cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f; canvas.save(); canvas.translate(canvasOffsetX, canvasOffsetY); cell.setInvalidatesParent(true); cell.drawNamesLayout(canvas, alpha); cell.setInvalidatesParent(false); canvas.restore(); } drawNamesAfter.clear(); } size = drawCaptionAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawCaptionAfter.get(a); boolean selectionOnly = false; if (cell.getCurrentPosition() != null) { selectionOnly = (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0; } float alpha = cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f; float canvasOffsetX = cell.getLeft() + cell.getNonAnimationTranslationX(false); float canvasOffsetY = cell.getY(); canvas.save(); MessageObject.GroupedMessages groupedMessages = cell.getCurrentMessagesGroup(); if (groupedMessages != null && groupedMessages.transitionParams.backgroundChangeBounds) { float x = cell.getNonAnimationTranslationX(true); float l = (groupedMessages.transitionParams.left + x + groupedMessages.transitionParams.offsetLeft); float t = (groupedMessages.transitionParams.top + groupedMessages.transitionParams.offsetTop); float r = (groupedMessages.transitionParams.right + x + groupedMessages.transitionParams.offsetRight); float b = (groupedMessages.transitionParams.bottom + groupedMessages.transitionParams.offsetBottom); if (!groupedMessages.transitionParams.backgroundChangeBounds) { t += cell.getTranslationY(); b += cell.getTranslationY(); } canvas.clipRect( l + AndroidUtilities.dp(8), t + AndroidUtilities.dp(8), r - AndroidUtilities.dp(8), b - AndroidUtilities.dp(8) ); } if (cell.getTransitionParams().wasDraw) { canvas.translate(canvasOffsetX, canvasOffsetY); cell.setInvalidatesParent(true); cell.drawCaptionLayout(canvas, selectionOnly, alpha); cell.setInvalidatesParent(false); canvas.restore(); } } drawCaptionAfter.clear(); } } private void drawChatBackgroundElements(Canvas canvas) { int count = getChildCount(); MessageObject.GroupedMessages lastDrawnGroup = null; for (int a = 0; a < count; a++) { View child = getChildAt(a); if (chatAdapter.isBot && child instanceof BotHelpCell) { BotHelpCell botCell = (BotHelpCell) child; float top = (getMeasuredHeight() - chatListViewPaddingTop - blurredViewBottomOffset) / 2 - child.getMeasuredHeight() / 2 + chatListViewPaddingTop; if (!botCell.animating() && !chatListView.fastScrollAnimationRunning) { if (child.getTop() > top) { child.setTranslationY(top - child.getTop()); } else { child.setTranslationY(0); } } break; } else if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); if (group == null || group != lastDrawnGroup) { lastDrawnGroup = group; MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); MessageBackgroundDrawable backgroundDrawable = cell.getBackgroundDrawable(); if ((backgroundDrawable.isAnimationInProgress() || cell.isDrawingSelectionBackground()) && (position == null || (position.flags & MessageObject.POSITION_FLAG_RIGHT) != 0)) { if (cell.isHighlighted() || cell.isHighlightedAnimated()) { if (position == null) { Paint backgroundPaint = getThemedPaint(Theme.key_paint_chatMessageBackgroundSelected); if (themeDelegate != null && themeDelegate.isDark || backgroundPaint == null) { backgroundPaint = Theme.chat_replyLinePaint; backgroundPaint.setColor(getThemedColor(Theme.key_chat_selectedBackground)); } else { float viewTop = (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY(); int backgroundHeight = contentView.getBackgroundSizeY(); if (themeDelegate != null) { themeDelegate.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, cell.getX(), viewTop); } else { Theme.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, cell.getX(), viewTop); } } canvas.save(); canvas.translate(0, cell.getTranslationY()); int wasAlpha = backgroundPaint.getAlpha(); backgroundPaint.setAlpha((int) (wasAlpha * cell.getHighlightAlpha() * cell.getAlpha())); canvas.drawRect(0, cell.getTop(), getMeasuredWidth(), cell.getBottom(), backgroundPaint); backgroundPaint.setAlpha(wasAlpha); canvas.restore(); } } else { int y = (int) cell.getY(); int height; canvas.save(); if (position == null) { height = cell.getMeasuredHeight(); } else { height = y + cell.getMeasuredHeight(); long time = 0; float touchX = 0; float touchY = 0; for (int i = 0; i < count; i++) { View inner = getChildAt(i); if (inner instanceof ChatMessageCell) { ChatMessageCell innerCell = (ChatMessageCell) inner; MessageObject.GroupedMessages innerGroup = innerCell.getCurrentMessagesGroup(); if (innerGroup == group) { MessageBackgroundDrawable drawable = innerCell.getBackgroundDrawable(); y = Math.min(y, (int) innerCell.getY()); height = Math.max(height, (int) innerCell.getY() + innerCell.getMeasuredHeight()); long touchTime = drawable.getLastTouchTime(); if (touchTime > time) { touchX = drawable.getTouchX() + innerCell.getX(); touchY = drawable.getTouchY() + innerCell.getY(); time = touchTime; } } } } backgroundDrawable.setTouchCoordsOverride(touchX, touchY - y); height -= y; } canvas.clipRect(0, y, getMeasuredWidth(), y + height); Paint selectedBackgroundPaint = getThemedPaint(Theme.key_paint_chatMessageBackgroundSelected); if (themeDelegate != null && !themeDelegate.isDark && selectedBackgroundPaint != null) { backgroundDrawable.setCustomPaint(selectedBackgroundPaint); float viewTop = (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY(); int backgroundHeight = contentView.getBackgroundSizeY(); if (themeDelegate != null) { themeDelegate.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, cell.getX(), viewTop); } else { Theme.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, cell.getX(), viewTop); } } else { backgroundDrawable.setCustomPaint(null); backgroundDrawable.setColor(getThemedColor(Theme.key_chat_selectedBackground)); } backgroundDrawable.setBounds(0, y, getMeasuredWidth(), y + height); backgroundDrawable.draw(canvas); canvas.restore(); } } } if (scrimView != cell && group == null && cell.drawBackgroundInParent()) { canvas.save(); canvas.translate(cell.getX(), cell.getY()); if (cell.getScaleX() != 1f) { canvas.scale( cell.getScaleX(), cell.getScaleY(), cell.getPivotX(), (cell.getHeight() >> 1) ); } cell.drawBackgroundInternal(canvas, true); canvas.restore(); } } else if (child instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) child; if (cell.hasGradientService()) { canvas.save(); canvas.translate(cell.getX(), cell.getY()); canvas.scale(cell.getScaleX(), cell.getScaleY(), cell.getMeasuredWidth() / 2f, cell.getMeasuredHeight() / 2f); cell.drawBackground(canvas, true); canvas.restore(); } } } MessageObject.GroupedMessages scrimGroup = null; if (scrimView instanceof ChatMessageCell) { scrimGroup = ((ChatMessageCell) scrimView).getCurrentMessagesGroup(); } for (int k = 0; k < 3; k++) { drawingGroups.clear(); if (k == 2 && !chatListView.isFastScrollAnimationRunning()) { continue; } for (int i = 0; i < count; i++) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; if (child.getY() > chatListView.getHeight() || child.getY() + child.getHeight() < 0) { continue; } MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); if (group == null || (k == 0 && group.messages.size() == 1) || (k == 1 && !group.transitionParams.drawBackgroundForDeletedItems)) { continue; } if ((k == 0 && cell.getMessageObject().deleted) || (k == 1 && !cell.getMessageObject().deleted)) { continue; } if ((k == 2 && !cell.willRemovedAfterAnimation()) || (k != 2 && cell.willRemovedAfterAnimation())) { continue; } if (!drawingGroups.contains(group)) { group.transitionParams.left = 0; group.transitionParams.top = 0; group.transitionParams.right = 0; group.transitionParams.bottom = 0; group.transitionParams.pinnedBotton = false; group.transitionParams.pinnedTop = false; group.transitionParams.cell = cell; drawingGroups.add(group); } group.transitionParams.pinnedTop = cell.isPinnedTop(); group.transitionParams.pinnedBotton = cell.isPinnedBottom(); int left = (cell.getLeft() + cell.getBackgroundDrawableLeft()); int right = (cell.getLeft() + cell.getBackgroundDrawableRight()); int top = (cell.getTop() + cell.getBackgroundDrawableTop()); int bottom = (cell.getTop() + cell.getBackgroundDrawableBottom()); if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_TOP) == 0) { top -= AndroidUtilities.dp(10); } if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { bottom += AndroidUtilities.dp(10); } if (cell.willRemovedAfterAnimation()) { group.transitionParams.cell = cell; } if (group.transitionParams.top == 0 || top < group.transitionParams.top) { group.transitionParams.top = top; } if (group.transitionParams.bottom == 0 || bottom > group.transitionParams.bottom) { group.transitionParams.bottom = bottom; } if (group.transitionParams.left == 0 || left < group.transitionParams.left) { group.transitionParams.left = left; } if (group.transitionParams.right == 0 || right > group.transitionParams.right) { group.transitionParams.right = right; } } } for (int i = 0; i < drawingGroups.size(); i++) { MessageObject.GroupedMessages group = drawingGroups.get(i); if (group == scrimGroup) { continue; } float x = group.transitionParams.cell.getNonAnimationTranslationX(true); float l = (group.transitionParams.left + x + group.transitionParams.offsetLeft); float t = (group.transitionParams.top + group.transitionParams.offsetTop); float r = (group.transitionParams.right + x + group.transitionParams.offsetRight); float b = (group.transitionParams.bottom + group.transitionParams.offsetBottom); if (!group.transitionParams.backgroundChangeBounds) { t += group.transitionParams.cell.getTranslationY(); b += group.transitionParams.cell.getTranslationY(); } if (t < chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(20)) { t = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(20); } if (b > chatListView.getMeasuredHeight() + AndroidUtilities.dp(20)) { b = chatListView.getMeasuredHeight() + AndroidUtilities.dp(20); } boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f; if (useScale) { canvas.save(); canvas.scale(group.transitionParams.cell.getScaleX(), group.transitionParams.cell.getScaleY(), l + (r - l) / 2, t + (b - t) / 2); } boolean selected = true; for (int a = 0, N = group.messages.size(); a < N; a++) { MessageObject object = group.messages.get(a); int index = object.getDialogId() == dialog_id ? 0 : 1; if (selectedMessagesIds[index].indexOfKey(object.getId()) < 0) { selected = false; break; } } group.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, group.transitionParams.pinnedTop, group.transitionParams.pinnedBotton, selected, contentView.getKeyboardHeight()); group.transitionParams.cell = null; group.transitionParams.drawCaptionLayout = group.hasCaption; if (useScale) { canvas.restore(); for (int ii = 0; ii < count; ii++) { View child = chatListView.getChildAt(ii); if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getCurrentMessagesGroup() == group) { ChatMessageCell cell = ((ChatMessageCell) child); int left = cell.getLeft(); int top = cell.getTop(); child.setPivotX(l - left + (r - l) / 2); child.setPivotY(t - top + (b - t) / 2); } } } } } } @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { int clipLeft = 0; int clipBottom = 0; boolean skipDraw = child == scrimView; ChatMessageCell cell; float cilpTop = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4); if (child.getY() > getMeasuredHeight() || child.getY() + child.getMeasuredHeight() < cilpTop) { skipDraw = true; } MessageObject.GroupedMessages group = null; if (child instanceof ChatMessageCell) { cell = (ChatMessageCell) child; if (animateSendingViews.contains(cell)) { skipDraw = true; } MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); group = cell.getCurrentMessagesGroup(); if (position != null) { if (position.pw != position.spanSize && position.spanSize == 1000 && position.siblingHeights == null && group.hasSibling) { clipLeft = cell.getBackgroundDrawableLeft(); } else if (position.siblingHeights != null) { clipBottom = child.getBottom() - AndroidUtilities.dp(1 + (cell.isPinnedBottom() ? 1 : 0)); } } if (cell.needDelayRoundProgressDraw()) { drawLaterRoundProgressCell = cell; } if (!skipDraw && scrimView instanceof ChatMessageCell) { ChatMessageCell cell2 = (ChatMessageCell) scrimView; if (cell2.getCurrentMessagesGroup() != null && cell2.getCurrentMessagesGroup() == group) { skipDraw = true; } } if (skipDraw) { cell.getPhotoImage().skipDraw(); } } else { cell = null; } if (clipLeft != 0) { canvas.save(); } else if (clipBottom != 0) { canvas.save(); } boolean result; if (!skipDraw) { boolean clipToGroupBounds = group != null && group.transitionParams.backgroundChangeBounds; if (clipToGroupBounds) { canvas.save(); float x = cell.getNonAnimationTranslationX(true); float l = (group.transitionParams.left + x + group.transitionParams.offsetLeft); float t = (group.transitionParams.top + group.transitionParams.offsetTop); float r = (group.transitionParams.right + x + group.transitionParams.offsetRight); float b = (group.transitionParams.bottom + group.transitionParams.offsetBottom); canvas.clipRect( l + AndroidUtilities.dp(4), t + AndroidUtilities.dp(4), r - AndroidUtilities.dp(4), b - AndroidUtilities.dp(4) ); } if (cell != null && clipToGroupBounds) { cell.clipToGroupBounds = true; result = super.drawChild(canvas, child, drawingTime); cell.clipToGroupBounds = false; } else { result = super.drawChild(canvas, child, drawingTime); } if (clipToGroupBounds) { canvas.restore(); } if (cell != null && cell.hasOutboundsContent()) { canvas.save(); canvas.translate(cell.getX(), cell.getY()); cell.drawOutboundsContent(canvas); canvas.restore(); } } else { result = false; } if (clipLeft != 0 || clipBottom != 0) { canvas.restore(); } if (child.getTranslationY() != 0) { canvas.save(); canvas.translate(0, child.getTranslationY()); } if (cell != null) { cell.drawCheckBox(canvas); } if (child.getTranslationY() != 0) { canvas.restore(); } if (child.getTranslationY() != 0) { canvas.save(); canvas.translate(0, child.getTranslationY()); } if (cell != null) { MessageObject message = cell.getMessageObject(); MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); if (!skipDraw) { if (position != null || cell.getTransitionParams().animateBackgroundBoundsInner) { if (position == null || (position.last || position.minX == 0 && position.minY == 0)) { if (position == null || position.last) { drawTimeAfter.add(cell); } if ((position == null || (position.minX == 0 && position.minY == 0)) && cell.hasNameLayout()) { drawNamesAfter.add(cell); } } if (position != null || cell.getTransitionParams().transformGroupToSingleMessage || cell.getTransitionParams().animateBackgroundBoundsInner) { if (position == null || (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { drawCaptionAfter.add(cell); } } } if (videoPlayerContainer != null && (message.isRoundVideo() || message.isVideo()) && MediaController.getInstance().isPlayingMessage(message)) { ImageReceiver imageReceiver = cell.getPhotoImage(); float newX = imageReceiver.getImageX() + cell.getX(); float newY = cell.getY() + imageReceiver.getImageY() + chatListView.getY() - videoPlayerContainer.getTop(); if (videoPlayerContainer.getTranslationX() != newX || videoPlayerContainer.getTranslationY() != newY) { videoPlayerContainer.setTranslationX(newX); videoPlayerContainer.setTranslationY(newY); fragmentView.invalidate(); videoPlayerContainer.invalidate(); } } } ImageReceiver imageReceiver = cell.getAvatarImage(); if (imageReceiver != null) { MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (cell.getMessageObject().deleted) { if (child.getTranslationY() != 0) { canvas.restore(); } imageReceiver.setVisible(false, false); return result; } boolean replaceAnimation = chatListView.isFastScrollAnimationRunning() || (groupedMessages != null && groupedMessages.transitionParams.backgroundChangeBounds); int top = replaceAnimation ? child.getTop() : (int) child.getY(); if (cell.drawPinnedBottom()) { int p; if (cell.willRemovedAfterAnimation()) { p = chatScrollHelper.positionToOldView.indexOfValue(child); if (p >= 0) { p = chatScrollHelper.positionToOldView.keyAt(p); } } else { ViewHolder holder = chatListView.getChildViewHolder(child); p = holder.getAdapterPosition(); } if (p >= 0) { int nextPosition; if (groupedMessages != null && position != null) { int idx = groupedMessages.posArray.indexOf(position); int size = groupedMessages.posArray.size(); if ((position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { nextPosition = p - size + idx; } else { nextPosition = p - 1; for (int a = idx + 1; a < size; a++) { if (groupedMessages.posArray.get(a).minY > position.maxY) { break; } else { nextPosition--; } } } } else { nextPosition = p - 1; } if (cell.willRemovedAfterAnimation()) { View view = chatScrollHelper.positionToOldView.get(nextPosition); if (view != null) { if (child.getTranslationY() != 0) { canvas.restore(); } imageReceiver.setVisible(false, false); return result; } } else { ViewHolder holder = chatListView.findViewHolderForAdapterPosition(nextPosition); if (holder != null) { if (child.getTranslationY() != 0) { canvas.restore(); } imageReceiver.setVisible(false, false); return result; } } } } float tx = cell.getSlidingOffsetX() + cell.getCheckBoxTranslation(); int y = (int) ((replaceAnimation ? child.getTop() : child.getY()) + cell.getLayoutHeight() + cell.getTransitionParams().deltaBottom); int maxY = chatListView.getMeasuredHeight() - chatListView.getPaddingBottom(); if (cell.isPlayingRound() || cell.getTransitionParams().animatePlayingRound) { if (cell.getTransitionParams().animatePlayingRound) { float progressLocal = cell.getTransitionParams().animateChangeProgress; if (!cell.isPlayingRound()) { progressLocal = 1f - progressLocal; } int fromY = y; int toY = Math.min(y, maxY); y = (int) (fromY * progressLocal + toY * (1f - progressLocal)); } } else { if (y > maxY) { y = maxY; } } if (!replaceAnimation && child.getTranslationY() != 0) { canvas.restore(); } if (cell.drawPinnedTop()) { int p; if (cell.willRemovedAfterAnimation()) { p = chatScrollHelper.positionToOldView.indexOfValue(child); if (p >= 0) { p = chatScrollHelper.positionToOldView.keyAt(p); } } else { ViewHolder holder = chatListView.getChildViewHolder(child); p = holder.getAdapterPosition(); } if (p >= 0) { int tries = 0; while (true) { if (tries >= 20) { break; } tries++; int prevPosition; if (groupedMessages != null && position != null) { int idx = groupedMessages.posArray.indexOf(position); if (idx < 0) { break; } int size = groupedMessages.posArray.size(); if ((position.flags & MessageObject.POSITION_FLAG_TOP) != 0) { prevPosition = p + idx + 1; } else { prevPosition = p + 1; for (int a = idx - 1; a >= 0; a--) { if (groupedMessages.posArray.get(a).maxY < position.minY) { break; } else { prevPosition++; } } } } else { prevPosition = p + 1; } if (cell.willRemovedAfterAnimation()) { View view = chatScrollHelper.positionToOldView.get(prevPosition); if (view != null) { top = view.getTop(); if (view instanceof ChatMessageCell) { cell = (ChatMessageCell) view; if (!cell.drawPinnedTop()) { break; } else { p = prevPosition; } } else { break; } } else { break; } } else { ViewHolder holder = chatListView.findViewHolderForAdapterPosition(prevPosition); if (holder != null) { top = holder.itemView.getTop(); if (holder.itemView instanceof ChatMessageCell) { cell = (ChatMessageCell) holder.itemView; if (!cell.drawPinnedTop()) { break; } else { p = prevPosition; } } else { break; } } else { break; } } } } } if (y - AndroidUtilities.dp(48) < top) { y = top + AndroidUtilities.dp(48); } if (!cell.drawPinnedBottom()) { int cellBottom = replaceAnimation ? cell.getBottom() : (int) (cell.getY() + cell.getMeasuredHeight() + cell.getTransitionParams().deltaBottom); if (y > cellBottom) { y = cellBottom; } } canvas.save(); if (tx != 0) { canvas.translate(tx, 0); } if (cell.getCurrentMessagesGroup() != null) { if (cell.getCurrentMessagesGroup().transitionParams.backgroundChangeBounds) { y -= cell.getTranslationY(); } } imageReceiver.setImageY(y - AndroidUtilities.dp(44)); if (cell.shouldDrawAlphaLayer()) { imageReceiver.setAlpha(cell.getAlpha()); canvas.scale( cell.getScaleX(), cell.getScaleY(), cell.getX() + cell.getPivotX(), cell.getY() + (cell.getHeight() >> 1) ); } else { imageReceiver.setAlpha(1f); } imageReceiver.setVisible(true, false); imageReceiver.draw(canvas); canvas.restore(); if (!replaceAnimation && child.getTranslationY() != 0) { canvas.save(); } } } if (child.getTranslationY() != 0) { canvas.restore(); } return result; } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { if (currentEncryptedChat != null) { return; } super.onInitializeAccessibilityNodeInfo(info); if (Build.VERSION.SDK_INT >= 19) { AccessibilityNodeInfo.CollectionInfo collection = info.getCollectionInfo(); if (collection != null) { info.setCollectionInfo(AccessibilityNodeInfo.CollectionInfo.obtain(collection.getRowCount(), 1, false)); } } } @Override public AccessibilityNodeInfo createAccessibilityNodeInfo() { if (currentEncryptedChat != null) { return null; } return super.createAccessibilityNodeInfo(); } @Override public void invalidate() { if (invalidated && slidingView == null) { return; } invalidated = true; super.invalidate(); contentView.invalidateBlur(); } }; if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) { chatListView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } chatListView.setAccessibilityEnabled(false); chatListView.setNestedScrollingEnabled(false); chatListView.setInstantClick(true); chatListView.setDisableHighlightState(true); chatListView.setTag(1); chatListView.setVerticalScrollBarEnabled(!SharedConfig.chatBlurEnabled()); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); chatListView.setAnimateEmptyView(true, 1); chatListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); chatListViewPaddingTop = 0; invalidateChatListViewTopPadding(); if (MessagesController.getGlobalMainSettings().getBoolean("view_animations", true)) { chatListItemAnimator = new ChatListItemAnimator(this, chatListView, themeDelegate) { Runnable finishRunnable; @Override public void checkIsRunning() { if (scrollAnimationIndex == -1) { scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, allowedNotificationsDuringChatListAnimations, false); } } @Override public void onAnimationStart() { if (scrollAnimationIndex == -1) { scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, allowedNotificationsDuringChatListAnimations, false); } if (finishRunnable != null) { AndroidUtilities.cancelRunOnUIThread(finishRunnable); finishRunnable = null; } if (BuildVars.LOGS_ENABLED) { FileLog.d("chatItemAnimator disable notifications"); } chatActivityEnterView.getAdjustPanLayoutHelper().runDelayedAnimation(); chatActivityEnterView.runEmojiPanelAnimation(); } @Override protected void onAllAnimationsDone() { super.onAllAnimationsDone(); if (finishRunnable != null) { AndroidUtilities.cancelRunOnUIThread(finishRunnable); } AndroidUtilities.runOnUIThread(finishRunnable = () -> { if (scrollAnimationIndex != -1) { getNotificationCenter().onAnimationFinish(scrollAnimationIndex); scrollAnimationIndex = -1; } if (BuildVars.LOGS_ENABLED) { FileLog.d("chatItemAnimator enable notifications"); } }); } @Override public void endAnimations() { super.endAnimations(); if (finishRunnable != null) { AndroidUtilities.cancelRunOnUIThread(finishRunnable); } AndroidUtilities.runOnUIThread(finishRunnable = () -> { if (scrollAnimationIndex != -1) { getNotificationCenter().onAnimationFinish(scrollAnimationIndex); scrollAnimationIndex = -1; } if (BuildVars.LOGS_ENABLED) { FileLog.d("chatItemAnimator enable notifications"); } }); } }; } chatLayoutManager = new GridLayoutManagerFixed(context, 1000, LinearLayoutManager.VERTICAL, true) { boolean computingScroll; @Override public int getStarForFixGap() { int padding = (int) chatListViewPaddingTop; if (isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } return padding; } @Override protected int getParentStart() { if (computingScroll) { return (int) chatListViewPaddingTop; } return 0; } @Override public int getStartAfterPadding() { if (computingScroll) { return (int) chatListViewPaddingTop; } return super.getStartAfterPadding(); } @Override public int getTotalSpace() { if (computingScroll) { return (int) (getHeight() - chatListViewPaddingTop - getPaddingBottom()); } return super.getTotalSpace(); } @Override public int computeVerticalScrollExtent(RecyclerView.State state) { computingScroll = true; int r = super.computeVerticalScrollExtent(state); computingScroll = false; return r; } @Override public int computeVerticalScrollOffset(RecyclerView.State state) { computingScroll = true; int r = super.computeVerticalScrollOffset(state); computingScroll = false; return r; } @Override public int computeVerticalScrollRange(RecyclerView.State state) { computingScroll = true; int r = super.computeVerticalScrollRange(state); computingScroll = false; return r; } @Override public void scrollToPositionWithOffset(int position, int offset, boolean bottom) { if (!bottom) { offset = (int) (offset - getPaddingTop() + chatListViewPaddingTop); } super.scrollToPositionWithOffset(position, offset, bottom); } @Override public boolean supportsPredictiveItemAnimations() { return true; } @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { scrollByTouch = false; LinearSmoothScrollerCustom linearSmoothScroller = new LinearSmoothScrollerCustom(recyclerView.getContext(), LinearSmoothScrollerCustom.POSITION_MIDDLE); linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); } @Override public boolean shouldLayoutChildFromOpositeSide(View child) { if (child instanceof ChatMessageCell) { return !((ChatMessageCell) child).getMessageObject().isOutOwner(); } return false; } @Override protected boolean hasSiblingChild(int position) { if (position >= chatAdapter.messagesStartRow && position < chatAdapter.messagesEndRow) { int index = position - chatAdapter.messagesStartRow; if (index >= 0 && index < messages.size()) { MessageObject message = messages.get(index); MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { MessageObject.GroupedMessagePosition pos = group.positions.get(message); if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { return false; } int count = group.posArray.size(); for (int a = 0; a < count; a++) { MessageObject.GroupedMessagePosition p = group.posArray.get(a); if (p == pos) { continue; } if (p.minY <= pos.minY && p.maxY >= pos.minY) { return true; } } } } } return false; } @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { if (BuildVars.DEBUG_PRIVATE_VERSION) { super.onLayoutChildren(recycler, state); } else { try { super.onLayoutChildren(recycler, state); } catch (Exception e) { FileLog.e(e); AndroidUtilities.runOnUIThread(() -> chatAdapter.notifyDataSetChanged(false)); } } } @Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { if (dy < 0 && pullingDownOffset != 0) { pullingDownOffset += dy; if (pullingDownOffset < 0) { dy = (int) pullingDownOffset; pullingDownOffset = 0; chatListView.invalidate(); } else { dy = 0; } } int n = chatListView.getChildCount(); int scrolled = 0; boolean foundTopView = false; for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); float padding = chatListViewPaddingTop; if (isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } if (chatListView.getChildAdapterPosition(child) == chatAdapter.getItemCount() - 1) { int dyLocal = dy; if (child.getTop() - dy > padding) { dyLocal = (int) (child.getTop() - padding); } scrolled = super.scrollVerticallyBy(dyLocal, recycler, state); foundTopView = true; break; } } if (!foundTopView) { scrolled = super.scrollVerticallyBy(dy, recycler, state); } if (dy > 0 && scrolled == 0 && ChatObject.isChannel(currentChat) && !currentChat.megagroup && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && reportType < 0) { if (pullingDownOffset == 0 && pullingDownDrawable != null) { pullingDownDrawable.updateDialog(); } if (pullingDownBackAnimator != null) { pullingDownBackAnimator.removeAllListeners(); pullingDownBackAnimator.cancel(); } float k; if (pullingDownOffset < AndroidUtilities.dp(110)) { float progress = pullingDownOffset / AndroidUtilities.dp(110); k = 0.65f * (1f - progress) + 0.45f * progress; } else if (pullingDownOffset < AndroidUtilities.dp(160)) { float progress = (pullingDownOffset - AndroidUtilities.dp(110)) / AndroidUtilities.dp(50); k = 0.45f * (1f - progress) + 0.05f * progress; } else { k = 0.05f; } pullingDownOffset += dy * k; ReactionsEffectOverlay.onScrolled((int) (dy * k)); chatListView.invalidate(); } if (pullingDownOffset == 0) { chatListView.setOverScrollMode(View.OVER_SCROLL_ALWAYS); } else { chatListView.setOverScrollMode(View.OVER_SCROLL_NEVER); } if (pullingDownDrawable != null) { pullingDownDrawable.showBottomPanel(pullingDownOffset > 0 && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING); } return scrolled; } }; chatLayoutManager.setSpanSizeLookup(new GridLayoutManagerFixed.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (position >= chatAdapter.messagesStartRow && position < chatAdapter.messagesEndRow) { int idx = position - chatAdapter.messagesStartRow; if (idx >= 0 && idx < messages.size()) { MessageObject message = messages.get(idx); MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { return groupedMessages.positions.get(message).spanSize; } } } return 1000; } }); chatListView.setLayoutManager(chatLayoutManager); chatListView.addItemDecoration(new RecyclerView.ItemDecoration() { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.bottom = 0; if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); if (group != null) { MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); if (position != null && position.siblingHeights != null) { float maxHeight = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f; int h = cell.getExtraInsetHeight(); for (int a = 0; a < position.siblingHeights.length; a++) { h += (int) Math.ceil(maxHeight * position.siblingHeights[a]); } h += (position.maxY - position.minY) * Math.round(7 * AndroidUtilities.density); int count = group.posArray.size(); for (int a = 0; a < count; a++) { MessageObject.GroupedMessagePosition pos = group.posArray.get(a); if (pos.minY != position.minY || pos.minX == position.minX && pos.maxX == position.maxX && pos.minY == position.minY && pos.maxY == position.maxY) { continue; } if (pos.minY == position.minY) { h -= (int) Math.ceil(maxHeight * pos.ph) - AndroidUtilities.dp(4); break; } } outRect.bottom = -h; } } } } }); contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); chatListView.setOnItemLongClickListener(onItemLongClickListener); chatListView.setOnItemClickListener(onItemClickListener); chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { private float totalDy = 0; private boolean scrollUp; private final int scrollValue = AndroidUtilities.dp(100); @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (pollHintCell != null) { pollHintView.showForMessageCell(pollHintCell, -1, pollHintX, pollHintY, true); pollHintCell = null; } scrollingFloatingDate = false; scrollingChatListView = false; checkTextureViewPosition = false; hideFloatingDateView(true); checkAutoDownloadMessages(scrollUp); if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startSpoilers); chatListView.setOverScrollMode(RecyclerView.OVER_SCROLL_ALWAYS); textSelectionHelper.stopScrolling(); updateVisibleRows(); scrollByTouch = false; } else { if (newState == RecyclerView.SCROLL_STATE_SETTLING) { wasManualScroll = true; scrollingChatListView = true; } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { pollHintCell = null; wasManualScroll = true; scrollingFloatingDate = true; checkTextureViewPosition = true; scrollingChatListView = true; } if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopSpoilers); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { chatListView.invalidate(); scrollUp = dy < 0; int firstVisibleItem = chatLayoutManager.findFirstVisibleItemPosition(); if (dy != 0 && (scrollByTouch && recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) || recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { if (forceNextPinnedMessageId != 0) { if ((!scrollUp || forceScrollToFirst)) { forceNextPinnedMessageId = 0; } else if (!chatListView.isFastScrollAnimationRunning() && firstVisibleItem != RecyclerView.NO_POSITION) { int lastVisibleItem = chatLayoutManager.findLastVisibleItemPosition(); MessageObject messageObject = null; boolean foundForceNextPinnedView = false; for (int i = lastVisibleItem; i >= firstVisibleItem; i--) { View view = chatLayoutManager.findViewByPosition(i); if (view instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) view).getMessageObject(); } else if (view instanceof ChatActionCell) { messageObject = ((ChatActionCell) view).getMessageObject(); } if (messageObject != null) { if (forceNextPinnedMessageId == messageObject.getId()) { foundForceNextPinnedView = true; break; } } } if (!foundForceNextPinnedView && messageObject != null && messageObject.getId() < forceNextPinnedMessageId) { forceNextPinnedMessageId = 0; } } } } if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { forceScrollToFirst = false; if (!wasManualScroll && dy != 0) { wasManualScroll = true; } } if (dy != 0) { hideHints(true); } if (dy != 0 && scrollingFloatingDate && !currentFloatingTopIsNotMessage) { if (highlightMessageId != Integer.MAX_VALUE) { removeSelectedMessageHighlight(); updateVisibleRows(); } showFloatingDateView(true); } checkScrollForLoad(true); if (firstVisibleItem != RecyclerView.NO_POSITION) { int totalItemCount = chatAdapter.getItemCount(); if (firstVisibleItem == 0 && forwardEndReached[0]) { if (dy >= 0) { canShowPagedownButton = false; updatePagedownButtonVisibility(true); } } else { if (dy > 0) { if (pagedownButton.getTag() == null) { totalDy += dy; if (totalDy > scrollValue) { totalDy = 0; canShowPagedownButton = true; updatePagedownButtonVisibility(true); pagedownButtonShowedByScroll = true; } } } else { if (pagedownButtonShowedByScroll && pagedownButton.getTag() != null) { totalDy += dy; if (totalDy < -scrollValue) { canShowPagedownButton = false; updatePagedownButtonVisibility(true); totalDy = 0; } } } } } invalidateMessagesVisiblePart(); textSelectionHelper.onParentScrolled(); emojiAnimationsOverlay.onScrolled(dy); ReactionsEffectOverlay.onScrolled(dy); } }); animatingImageView = new ClippingImageView(context); animatingImageView.setVisibility(View.GONE); contentView.addView(animatingImageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); progressView = new FrameLayout(context); progressView.setVisibility(View.INVISIBLE); contentView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); progressView2 = new View(context); progressView2.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(18), progressView2, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); progressView.addView(progressView2, LayoutHelper.createFrame(36, 36, Gravity.CENTER)); progressBar = new RadialProgressView(context, themeDelegate); progressBar.setSize(AndroidUtilities.dp(28)); progressBar.setProgressColor(getThemedColor(Theme.key_chat_serviceText)); progressView.addView(progressBar, LayoutHelper.createFrame(32, 32, Gravity.CENTER)); floatingDateView = new ChatActionCell(context, false, themeDelegate) { @Override public void setTranslationY(float translationY) { if (getTranslationY() != translationY) { invalidate(); } super.setTranslationY(translationY); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (getAlpha() == 0 || actionBar.isActionModeShowed() || reportType >= 0) { return false; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { if (getAlpha() == 0 || actionBar.isActionModeShowed() || reportType >= 0) { return false; } return super.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { float clipTop = chatListView.getY() + chatListViewPaddingTop - getY(); clipTop -= AndroidUtilities.dp(4); if (clipTop > 0) { if (clipTop < getMeasuredHeight()) { canvas.save(); canvas.clipRect(0, clipTop, getMeasuredWidth(), getMeasuredHeight()); super.onDraw(canvas); canvas.restore(); } } else { super.onDraw(canvas); } } }; floatingDateView.setCustomDate((int) (System.currentTimeMillis() / 1000), false, false); floatingDateView.setAlpha(0.0f); floatingDateView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); floatingDateView.setInvalidateColors(true); contentView.addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 4, 0, 0)); floatingDateView.setOnClickListener(view -> { if (floatingDateView.getAlpha() == 0 || actionBar.isActionModeShowed() || reportType >= 0) { return; } Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis((long) floatingDateView.getCustomDate() * 1000); int year = calendar.get(Calendar.YEAR); int monthOfYear = calendar.get(Calendar.MONTH); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); calendar.clear(); calendar.set(year, monthOfYear, dayOfMonth); jumpToDate((int) (calendar.getTime().getTime() / 1000)); }); if (currentChat != null) { pendingRequestsDelegate = new ChatActivityMemberRequestsDelegate(this, currentChat, this::invalidateChatListViewTopPadding); pendingRequestsDelegate.setChatInfo(chatInfo, false); contentView.addView(pendingRequestsDelegate.getView(), ViewGroup.LayoutParams.MATCH_PARENT, pendingRequestsDelegate.getViewHeight()); } if (currentEncryptedChat == null) { pinnedMessageView = new BlurredFrameLayout(context, contentView) { float lastY; float startY; { setOnLongClickListener(v -> { if (AndroidUtilities.isTablet() || isThreadChat()) { return false; } startY = lastY; openPinnedMessagesList(true); return true; }); } @Override public boolean onTouchEvent(MotionEvent event) { lastY = event.getY(); if (event.getAction() == MotionEvent.ACTION_UP) { finishPreviewFragment(); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { float dy = startY - lastY; movePreviewFragment(dy); if (dy < 0) { startY = lastY; } } return super.onTouchEvent(event); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (setPinnedTextTranslationX) { for (int a = 0; a < pinnedNextAnimation.length; a++) { if (pinnedNextAnimation[a] != null) { pinnedNextAnimation[a].start(); } } setPinnedTextTranslationX = false; } } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (child == pinnedLineView) { canvas.save(); canvas.clipRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(48)); } boolean result; if (child == pinnedMessageTextView[0] || child == pinnedMessageTextView[1]) { canvas.save(); canvas.clipRect(0,0,getMeasuredWidth() - AndroidUtilities.dp(38),getMeasuredHeight()); result = super.drawChild(canvas, child, drawingTime); canvas.restore(); } else { result = super.drawChild(canvas, child, drawingTime); if (child == pinnedLineView) { canvas.restore(); } } return result; } }; pinnedMessageView.setTag(1); pinnedMessageEnterOffset = -AndroidUtilities.dp(50); pinnedMessageView.setVisibility(View.GONE); pinnedMessageView.setBackgroundResource(R.drawable.blockpanel); pinnedMessageView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); pinnedMessageView.backgroundPaddingBottom = AndroidUtilities.dp(2); pinnedMessageView.getBackground().mutate().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); contentView.addView(pinnedMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); pinnedMessageView.setOnClickListener(v -> { wasManualScroll = true; if (isThreadChat()) { scrollToMessageId(threadMessageId, 0, true, 0, true, 0); } else if (currentPinnedMessageId != 0) { int currentPinned = currentPinnedMessageId; int forceNextPinnedMessageId = 0; if (!pinnedMessageIds.isEmpty()) { if (currentPinned == pinnedMessageIds.get(pinnedMessageIds.size() - 1)) { forceNextPinnedMessageId = pinnedMessageIds.get(0) + 1; forceScrollToFirst = true; } else { forceNextPinnedMessageId = currentPinned - 1; forceScrollToFirst = false; } } this.forceNextPinnedMessageId = forceNextPinnedMessageId; if (!forceScrollToFirst) { forceNextPinnedMessageId = -forceNextPinnedMessageId; } scrollToMessageId(currentPinned, 0, true, 0, true, forceNextPinnedMessageId); updateMessagesVisiblePart(false); } }); pinnedMessageView.setEnabled(!isInPreviewMode()); View selector = new View(context); selector.setBackground(Theme.getSelectorDrawable(false)); pinnedMessageView.addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 2)); pinnedLineView = new PinnedLineView(context, themeDelegate); pinnedMessageView.addView(pinnedLineView, LayoutHelper.createFrame(2, 48, Gravity.LEFT | Gravity.TOP, 8, 0, 0, 0)); pinnedCounterTextView = new NumberTextView(context); pinnedCounterTextView.setAddNumber(); pinnedCounterTextView.setTextSize(14); pinnedCounterTextView.setTextColor(getThemedColor(Theme.key_chat_topPanelTitle)); pinnedCounterTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); pinnedMessageView.addView(pinnedCounterTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 7, 44, 0)); for (int a = 0; a < 2; a++) { pinnedNameTextView[a] = new TrackingWidthSimpleTextView(context); pinnedNameTextView[a].setTextSize(14); pinnedNameTextView[a].setTextColor(getThemedColor(Theme.key_chat_topPanelTitle)); pinnedNameTextView[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); pinnedMessageView.addView(pinnedNameTextView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 7.3f, 44, 0)); pinnedMessageTextView[a] = new SimpleTextView(context) { @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); if (this == pinnedMessageTextView[0] && pinnedNextAnimation[1] != null) { if (forceScrollToFirst && translationY < 0) { pinnedLineView.setTranslationY(translationY / 2); } else { pinnedLineView.setTranslationY(0); } } } }; pinnedMessageTextView[a].setTextSize(14); pinnedMessageTextView[a].setTextColor(getThemedColor(Theme.key_chat_topPanelMessage)); pinnedMessageView.addView(pinnedMessageTextView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 25.3f, 44, 0)); pinnedMessageButton[a] = new PinnedMessageButton(context); pinnedMessageView.addView(pinnedMessageButton[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.RIGHT, 0, 10, 14, 0)); pinnedMessageImageView[a] = new BackupImageView(context); pinnedMessageImageView[a].setRoundRadius(AndroidUtilities.dp(2)); pinnedMessageView.addView(pinnedMessageImageView[a], LayoutHelper.createFrame(32, 32, Gravity.TOP | Gravity.LEFT, 17, 8, 0, 0)); if (a == 1) { pinnedNameTextView[a].setVisibility(View.INVISIBLE); pinnedMessageButton[a].setVisibility(View.INVISIBLE); pinnedMessageTextView[a].setVisibility(View.INVISIBLE); pinnedMessageImageView[a].setVisibility(View.INVISIBLE); } } pinnedListButton = new ImageView(context); pinnedListButton.setImageResource(R.drawable.msg_pinnedlist); pinnedListButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); pinnedListButton.setScaleType(ImageView.ScaleType.CENTER); pinnedListButton.setContentDescription(LocaleController.getString("AccPinnedMessagesList", R.string.AccPinnedMessagesList)); pinnedListButton.setVisibility(View.INVISIBLE); pinnedListButton.setAlpha(0.0f); pinnedListButton.setScaleX(0.4f); pinnedListButton.setScaleY(0.4f); if (Build.VERSION.SDK_INT >= 21) { pinnedListButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff)); } pinnedMessageView.addView(pinnedListButton, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 7, 0)); pinnedListButton.setOnClickListener(v -> openPinnedMessagesList(false)); closePinned = new ImageView(context); closePinned.setImageResource(R.drawable.miniplayer_close); closePinned.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); closePinned.setScaleType(ImageView.ScaleType.CENTER); closePinned.setContentDescription(LocaleController.getString("Close", R.string.Close)); pinnedProgress = new RadialProgressView(context, themeDelegate); pinnedProgress.setVisibility(View.GONE); pinnedProgress.setSize(AndroidUtilities.dp(16)); pinnedProgress.setStrokeWidth(2f); pinnedProgress.setProgressColor(getThemedColor(Theme.key_chat_topPanelLine)); pinnedMessageView.addView(pinnedProgress, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); if (threadMessageId != 0) { closePinned.setVisibility(View.GONE); } if (Build.VERSION.SDK_INT >= 21) { closePinned.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14))); } pinnedMessageView.addView(closePinned, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); closePinned.setOnClickListener(v -> { if (getParentActivity() == null) { return; } boolean allowPin; if (currentChat != null) { allowPin = ChatObject.canPinMessages(currentChat); } else if (currentEncryptedChat == null) { if (userInfo != null) { allowPin = userInfo.can_pin_message; } else { allowPin = false; } } else { allowPin = false; } if (allowPin) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("UnpinMessageAlertTitle", R.string.UnpinMessageAlertTitle)); builder.setMessage(LocaleController.getString("UnpinMessageAlert", R.string.UnpinMessageAlert)); builder.setPositiveButton(LocaleController.getString("UnpinMessage", R.string.UnpinMessage), (dialogInterface, i) -> { MessageObject messageObject = pinnedMessageObjects.get(currentPinnedMessageId); if (messageObject == null) { messageObject = messagesDict[0].get(currentPinnedMessageId); } unpinMessage(messageObject); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } else if (!pinnedMessageIds.isEmpty()) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putInt("pin_" + dialog_id, pinnedMessageIds.get(0)).commit(); updatePinnedMessageView(true); } }); } topChatPanelView = new BlurredFrameLayout(context, contentView) { private boolean ignoreLayout; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); if (addToContactsButton != null && addToContactsButton.getVisibility() == VISIBLE && reportSpamButton != null && reportSpamButton.getVisibility() == VISIBLE) { width = (width - AndroidUtilities.dp(31)) / 2; } ignoreLayout = true; if (reportSpamButton != null && reportSpamButton.getVisibility() == VISIBLE) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) reportSpamButton.getLayoutParams(); layoutParams.width = width; if (addToContactsButton != null && addToContactsButton.getVisibility() == VISIBLE) { reportSpamButton.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); layoutParams.leftMargin = width; layoutParams.width -= AndroidUtilities.dp(15); } else { reportSpamButton.setPadding(AndroidUtilities.dp(48), 0, AndroidUtilities.dp(48), 0); layoutParams.leftMargin = 0; } } if (addToContactsButton != null && addToContactsButton.getVisibility() == VISIBLE) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) addToContactsButton.getLayoutParams(); layoutParams.width = width; if (reportSpamButton != null && reportSpamButton.getVisibility() == VISIBLE) { addToContactsButton.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(4), 0); } else { addToContactsButton.setPadding(AndroidUtilities.dp(48), 0, AndroidUtilities.dp(48), 0); layoutParams.leftMargin = 0; } } ignoreLayout = false; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public void requestLayout() { if (ignoreLayout) { return; } super.requestLayout(); } }; topChatPanelView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); topChatPanelView.backgroundPaddingBottom = AndroidUtilities.dp(2); topChatPanelView.setTag(1); topChatPanelViewOffset = -AndroidUtilities.dp(50); invalidateChatListViewTopPadding(); topChatPanelView.setVisibility(View.GONE); topChatPanelView.setBackgroundResource(R.drawable.blockpanel); topChatPanelView.getBackground().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); contentView.addView(topChatPanelView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); reportSpamButton = new TextView(context); reportSpamButton.setTextColor(getThemedColor(Theme.key_chat_reportSpam)); if (Build.VERSION.SDK_INT >= 21) { reportSpamButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_chat_reportSpam) & 0x19ffffff, 3)); } reportSpamButton.setTag(Theme.key_chat_reportSpam); reportSpamButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); reportSpamButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); reportSpamButton.setSingleLine(true); reportSpamButton.setMaxLines(1); reportSpamButton.setGravity(Gravity.CENTER); topChatPanelView.addView(reportSpamButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 1)); reportSpamButton.setOnClickListener(v2 -> AlertsCreator.showBlockReportSpamAlert(ChatActivity.this, dialog_id, currentUser, currentChat, currentEncryptedChat, reportSpamButton.getTag(R.id.object_tag) != null, chatInfo, param -> { if (param == 0) { updateTopPanel(true); } else { finishFragment(); } }, themeDelegate)); addToContactsButton = new TextView(context); addToContactsButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); addToContactsButton.setVisibility(View.GONE); addToContactsButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); addToContactsButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); addToContactsButton.setSingleLine(true); addToContactsButton.setMaxLines(1); addToContactsButton.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); addToContactsButton.setGravity(Gravity.CENTER); if (Build.VERSION.SDK_INT >= 21) { addToContactsButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_chat_addContact) & 0x19ffffff, 3)); } topChatPanelView.addView(addToContactsButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 1)); addToContactsButton.setOnClickListener(v -> { if (addToContactsButtonArchive) { getMessagesController().addDialogToFolder(dialog_id, 0, 0, 0); undoView.showWithAction(dialog_id, UndoView.ACTION_CHAT_UNARCHIVED, null); SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); SharedPreferences.Editor editor = preferences.edit(); editor.putBoolean("dialog_bar_archived" + dialog_id, false); editor.putBoolean("dialog_bar_block" + dialog_id, false); editor.putBoolean("dialog_bar_report" + dialog_id, false); editor.commit(); updateTopPanel(false); getNotificationsController().clearDialogNotificationsSettings(dialog_id); } else if (addToContactsButton.getTag() != null && (Integer) addToContactsButton.getTag() == 4) { if (chatInfo != null && chatInfo.participants != null) { LongSparseArray users = new LongSparseArray<>(); for (int a = 0; a < chatInfo.participants.participants.size(); a++) { users.put(chatInfo.participants.participants.get(a).user_id, null); } long chatId = chatInfo.id; InviteMembersBottomSheet bottomSheet = new InviteMembersBottomSheet(context, currentAccount, users, chatInfo.id, ChatActivity.this, themeDelegate); bottomSheet.setDelegate((users1, fwdCount) -> { for (int a = 0, N = users1.size(); a < N; a++) { TLRPC.User user = users1.get(a); getMessagesController().addUserToChat(chatId, user, fwdCount, null, ChatActivity.this, null); } getMessagesController().hidePeerSettingsBar(dialog_id, currentUser, currentChat); updateTopPanel(true); updateInfoTopView(true); }); bottomSheet.show(); } } else if (addToContactsButton.getTag() != null) { shareMyContact(1, null); } else { Bundle args = new Bundle(); args.putLong("user_id", currentUser.id); args.putBoolean("addContact", true); ContactAddActivity activity = new ContactAddActivity(args); activity.setDelegate(() -> undoView.showWithAction(dialog_id, UndoView.ACTION_CONTACT_ADDED, currentUser)); presentFragment(activity); } }); closeReportSpam = new ImageView(context); closeReportSpam.setImageResource(R.drawable.miniplayer_close); closeReportSpam.setContentDescription(LocaleController.getString("Close", R.string.Close)); if (Build.VERSION.SDK_INT >= 21) { closeReportSpam.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_chat_topPanelClose) & 0x19ffffff)); } closeReportSpam.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); closeReportSpam.setScaleType(ImageView.ScaleType.CENTER); topChatPanelView.addView(closeReportSpam, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); closeReportSpam.setOnClickListener(v -> { long did = dialog_id; if (currentEncryptedChat != null) { did = currentUser.id; } getMessagesController().hidePeerSettingsBar(did, currentUser, currentChat); updateTopPanel(true); updateInfoTopView(true); }); alertView = new FrameLayout(context); alertView.setTag(1); alertView.setVisibility(View.GONE); alertView.setBackgroundResource(R.drawable.blockpanel); alertView.getBackground().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); contentView.addView(alertView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); alertNameTextView = new TextView(context); alertNameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); alertNameTextView.setTextColor(getThemedColor(Theme.key_chat_topPanelTitle)); alertNameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); alertNameTextView.setSingleLine(true); alertNameTextView.setEllipsize(TextUtils.TruncateAt.END); alertNameTextView.setMaxLines(1); alertView.addView(alertNameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 8, 5, 8, 0)); alertTextView = new TextView(context); alertTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); alertTextView.setTextColor(getThemedColor(Theme.key_chat_topPanelMessage)); alertTextView.setSingleLine(true); alertTextView.setEllipsize(TextUtils.TruncateAt.END); alertTextView.setMaxLines(1); alertView.addView(alertTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 8, 23, 8, 0)); pagedownButton = new FrameLayout(context); pagedownButton.setVisibility(View.INVISIBLE); contentView.addView(pagedownButton, LayoutHelper.createFrame(66, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -3, 5)); pagedownButton.setOnClickListener(view -> { wasManualScroll = true; textSelectionHelper.cancelTextSelectionRunnable(); if (createUnreadMessageAfterId != 0) { scrollToMessageId(createUnreadMessageAfterId, 0, false, returnToLoadIndex, true, 0); } else if (returnToMessageId > 0) { scrollToMessageId(returnToMessageId, 0, true, returnToLoadIndex, true, 0); } else { scrollToLastMessage(false); if (!pinnedMessageIds.isEmpty()) { forceScrollToFirst = true; forceNextPinnedMessageId = pinnedMessageIds.get(0); } } }); mentiondownButton = new FrameLayout(context); mentiondownButton.setVisibility(View.INVISIBLE); contentView.addView(mentiondownButton, LayoutHelper.createFrame(46, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5)); mentiondownButton.setOnClickListener(new View.OnClickListener() { private void loadLastUnreadMention() { wasManualScroll = true; if (hasAllMentionsLocal) { getMessagesStorage().getUnreadMention(dialog_id, param -> { if (param == 0) { hasAllMentionsLocal = false; loadLastUnreadMention(); } else { scrollToMessageId(param, 0, false, 0, true, 0); } }); } else { final MessagesStorage messagesStorage = getMessagesStorage(); TLRPC.TL_messages_getUnreadMentions req = new TLRPC.TL_messages_getUnreadMentions(); req.peer = getMessagesController().getInputPeer(dialog_id); req.limit = 1; req.add_offset = newMentionsCount - 1; getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; if (error != null || res.messages.isEmpty()) { if (res != null) { newMentionsCount = res.count; } else { newMentionsCount = 0; } messagesStorage.resetMentionsCount(dialog_id, newMentionsCount); if (newMentionsCount == 0) { hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); loadLastUnreadMention(); } } else { int id = res.messages.get(0).id; MessageObject object = messagesDict[0].get(id); messagesStorage.markMessageAsMention(dialog_id, id); if (object != null) { object.messageOwner.media_unread = true; object.messageOwner.mentioned = true; } scrollToMessageId(id, 0, false, 0, true, 0); } })); } } @Override public void onClick(View view) { loadLastUnreadMention(); } }); mentiondownButton.setOnLongClickListener(view -> { scrimPopupWindow = ReadAllMentionsMenu.show(ReadAllMentionsMenu.TYPE_MENTIONS, getParentActivity(), contentView, view, getResourceProvider(), () -> { for (int a = 0; a < messages.size(); a++) { MessageObject messageObject = messages.get(a); if (messageObject.messageOwner.mentioned && !messageObject.isContentUnread()) { messageObject.setContentIsRead(); } } newMentionsCount = 0; getMessagesController().markMentionsAsRead(dialog_id); hasAllMentionsLocal = true; showMentionDownButton(false, true); if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } }); dimBehindView(mentiondownButton, true); scrimPopupWindow.setOnDismissListener(() -> { scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); dimBehindView(false); if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } }); view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); return true; }); updateMessageListAccessibilityVisibility(); reactionsMentiondownButton = new FrameLayout(context); contentView.addView(reactionsMentiondownButton, LayoutHelper.createFrame(46, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5)); mentionContainer = new MentionsContainerView(context, dialog_id, threadMessageId, ChatActivity.this, themeDelegate) { @Override protected boolean canOpen() { return bottomOverlay.getVisibility() != View.VISIBLE || searchingForUser; } @Override protected void onOpen() { if (allowStickersPanel && (!getAdapter().isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { if (currentEncryptedChat != null && getAdapter().isBotContext()) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (!preferences.getBoolean("secretbot", false)) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("SecretChatContextBotAlert", R.string.SecretChatContextBotAlert)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); preferences.edit().putBoolean("secretbot", true).commit(); } } } updateMessageListAccessibilityVisibility(); } @Override protected void onClose() { updateMessageListAccessibilityVisibility(); } @Override protected void onContextSearch(boolean searching) { if (chatActivityEnterView != null) { chatActivityEnterView.setCaption(getAdapter().getBotCaption()); chatActivityEnterView.showContextProgress(searching); } } @Override protected void onContextClick(TLRPC.BotInlineResult result) { if (getParentActivity() == null || result.content == null) { return; } if (result.type.equals("video") || result.type.equals("web_player_video")) { int[] size = MessageObject.getInlineResultWidthAndHeight(result); EmbedBottomSheet.show(getParentActivity(), null, botContextProvider, result.title != null ? result.title : "", result.description, result.content.url, result.content.url, size[0], size[1], isKeyboardVisible()); } else { processExternalUrl(0, result.content.url, false); } } }; contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); final ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker(TLRPC.Document sticker, String query, Object parent, boolean notify, int scheduleDate) { chatActivityEnterView.onStickerSelected(sticker, query, parent, null, true, notify, scheduleDate); } @Override public boolean needSend() { return false; } @Override public boolean canSchedule() { return ChatActivity.this.canScheduleMessage(); } @Override public boolean isInScheduleMode() { return chatMode == MODE_SCHEDULED; } @Override public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { if (set == null || getParentActivity() == null) { return; } TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); inputStickerSet.access_hash = set.access_hash; inputStickerSet.id = set.id; StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate); alert.setCalcMandatoryInsets(isKeyboardVisible()); alert.setClearsInputField(clearsInputField); showDialog(alert); } @Override public long getDialogId() { return dialog_id; } }; mentionContainer.getListView().setOnTouchListener((v, event) -> { return ContentPreviewViewer.getInstance().onTouch(event, mentionContainer.getListView(), 0, mentionsOnItemClickListener, mentionContainer.getAdapter().isStickers() ? contentPreviewViewerDelegate : null, themeDelegate); }); if (!ChatObject.isChannel(currentChat) || currentChat.megagroup) { mentionContainer.getAdapter().setBotInfo(botInfo); } mentionContainer.getAdapter().setParentFragment(this); mentionContainer.getAdapter().setChatInfo(chatInfo); mentionContainer.getAdapter().setNeedUsernames(currentChat != null); mentionContainer.getAdapter().setNeedBotContext(true); mentionContainer.getAdapter().setBotsCount(currentChat != null ? botsCount : 1); mentionContainer.getListView().setOnItemClickListener(mentionsOnItemClickListener = (view, position) -> { if (position == 0 || mentionContainer.getAdapter().isBannedInline()) { return; } position--; Object object = mentionContainer.getAdapter().getItem(position); int start = mentionContainer.getAdapter().getResultStartPosition(); int len = mentionContainer.getAdapter().getResultLength(); if (object instanceof TLRPC.TL_document) { if (chatMode == 0 && checkSlowMode(view)) { return; } MessageObject.SendAnimationData sendAnimationData = null; if (view instanceof StickerCell) { sendAnimationData = ((StickerCell) view).getSendAnimationData(); } TLRPC.TL_document document = (TLRPC.TL_document) object; Object parent = mentionContainer.getAdapter().getItemParent(position); String query = MessageObject.findAnimatedEmojiEmoticon(document); if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), parent, null, notify, scheduleDate), themeDelegate); } else { getSendMessagesHelper().sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), parent, sendAnimationData, true, 0); } hideFieldPanel(false); chatActivityEnterView.addStickerToRecent(document); chatActivityEnterView.setFieldText(""); } else if (object instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) object; if (searchingForUser && searchContainer.getVisibility() == View.VISIBLE) { searchUserMessages(null, chat); } else { if (chat.username != null) { chatActivityEnterView.replaceWithText(start, len, "@" + chat.username + " ", false); } } } else if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; if (searchingForUser && searchContainer.getVisibility() == View.VISIBLE) { searchUserMessages(user, null); } else { if (user.username != null) { chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " ", false); } else { String name = UserObject.getFirstName(user, false); Spannable spannable = new SpannableString(name + " "); spannable.setSpan(new URLSpanUserMention("" + user.id, 3), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); chatActivityEnterView.replaceWithText(start, len, spannable, false); } } } else if (object instanceof String) { if (mentionContainer.getAdapter().isBotCommands()) { if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> { getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, notify, scheduleDate, null); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); }, themeDelegate); } else { if (checkSlowMode(view)) { return; } getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, null); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); } } else { chatActivityEnterView.replaceWithText(start, len, object + " ", false); } } else if (object instanceof TLRPC.BotInlineResult) { if (chatActivityEnterView.getFieldText() == null || chatMode != MODE_SCHEDULED && checkSlowMode(view)) { return; } TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) object; if (currentEncryptedChat != null) { int error = 0; if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaAuto && "game".equals(result.type)) { error = 1; } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaInvoice) { error = 2; } if (error != 0) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("SendMessageTitle", R.string.SendMessageTitle)); if (error == 1) { builder.setMessage(LocaleController.getString("GameCantSendSecretChat", R.string.GameCantSendSecretChat)); } else { builder.setMessage(LocaleController.getString("InvoiceCantSendSecretChat", R.string.InvoiceCantSendSecretChat)); } builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); return; } } if ((result.type.equals("photo") && (result.photo != null || result.content != null) || result.type.equals("gif") && (result.document != null || result.content != null) || result.type.equals("video") && (result.document != null/* || result.content_url != null*/))) { ArrayList arrayList = botContextResults = new ArrayList<>(mentionContainer.getAdapter().getSearchResultBotContext()); PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionContainer.getAdapter().getItemPosition(position), 3, false, botContextProvider, ChatActivity.this); } else { if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> sendBotInlineResult(result, notify, scheduleDate), themeDelegate); } else { sendBotInlineResult(result, true, 0); } } } else if (object instanceof TLRPC.TL_inlineBotSwitchPM) { processInlineBotContextPM((TLRPC.TL_inlineBotSwitchPM) object); } else if (object instanceof MediaDataController.KeywordResult) { String code = ((MediaDataController.KeywordResult) object).emoji; chatActivityEnterView.addEmojiToRecent(code); if (code != null && code.startsWith("animated_")) { try { long documentId = Long.parseLong(code.substring(9)); TLRPC.Document document = AnimatedEmojiDrawable.findDocument(currentAccount, documentId); SpannableString emoji = new SpannableString(MessageObject.findAnimatedEmojiEmoticon(document)); AnimatedEmojiSpan span; if (document != null) { span = new AnimatedEmojiSpan(document, chatActivityEnterView.getEditField().getPaint().getFontMetricsInt()); } else { span = new AnimatedEmojiSpan(documentId, chatActivityEnterView.getEditField().getPaint().getFontMetricsInt()); } emoji.setSpan(span, 0, emoji.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); chatActivityEnterView.replaceWithText(start, len, emoji, false); } catch (Exception ignore) { chatActivityEnterView.replaceWithText(start, len, code, true); } } else { chatActivityEnterView.replaceWithText(start, len, code, true); } mentionContainer.updateVisibility(false); } }); mentionContainer.getListView().setOnItemLongClickListener((view, position) -> { if (getParentActivity() == null || !mentionContainer.getAdapter().isLongClickEnabled()) { return false; } Object object = mentionContainer.getAdapter().getItem(position); if (object instanceof String) { if (mentionContainer.getAdapter().isBotCommands()) { if (URLSpanBotCommand.enabled) { chatActivityEnterView.setFieldText(""); chatActivityEnterView.setCommand(null, (String) object, true, currentChat != null && currentChat.megagroup); return true; } return false; } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionContainer.getAdapter().clearRecentHashtags()); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); return true; } } return false; }); pagedownButtonImage = new ImageView(context); pagedownButtonImage.setImageResource(R.drawable.pagedown); pagedownButtonImage.setScaleType(ImageView.ScaleType.CENTER); pagedownButtonImage.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); pagedownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); Drawable drawable; if (Build.VERSION.SDK_INT >= 21) { pagedownButtonImage.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); } }); drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); } else { drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); } Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; pagedownButtonImage.setBackgroundDrawable(drawable); pagedownButton.addView(pagedownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); pagedownButton.setContentDescription(LocaleController.getString("AccDescrPageDown", R.string.AccDescrPageDown)); pagedownButtonCounter = new CounterView(context, themeDelegate) { @Override public void invalidate() { if (isInOutAnimation()) { contentView.invalidate(); } super.invalidate(); } }; pagedownButtonCounter.setReverse(true); pagedownButton.addView(pagedownButtonCounter, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.TOP | Gravity.LEFT)); mentiondownButtonImage = new ImageView(context); mentiondownButtonImage.setImageResource(R.drawable.mentionbutton); mentiondownButtonImage.setScaleType(ImageView.ScaleType.CENTER); mentiondownButtonImage.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); mentiondownButtonImage.setPadding(0, AndroidUtilities.dp(2), 0, 0); if (Build.VERSION.SDK_INT >= 21) { pagedownButtonImage.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); } }); drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); } else { drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); } shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.MULTIPLY)); combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; mentiondownButtonImage.setBackgroundDrawable(drawable); mentiondownButton.addView(mentiondownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.LEFT | Gravity.BOTTOM)); mentiondownButtonCounter = new SimpleTextView(context); mentiondownButtonCounter.setVisibility(View.INVISIBLE); mentiondownButtonCounter.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); mentiondownButtonCounter.setTextSize(13); mentiondownButtonCounter.setTextColor(getThemedColor(Theme.key_chat_goDownButtonCounter)); mentiondownButtonCounter.setGravity(Gravity.CENTER); mentiondownButtonCounter.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(11.5f), getThemedColor(Theme.key_chat_goDownButtonCounterBackground))); mentiondownButtonCounter.setMinWidth(AndroidUtilities.dp(23)); mentiondownButtonCounter.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(1), AndroidUtilities.dp(8), 0); mentiondownButton.addView(mentiondownButtonCounter, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 23, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); mentiondownButton.setContentDescription(LocaleController.getString("AccDescrMentionDown", R.string.AccDescrMentionDown)); reactionsMentiondownButton.setOnClickListener(view -> { wasManualScroll = true; getMessagesController().getNextReactionMention(dialog_id, reactionsMentionCount, (messageId) -> { if (messageId == 0) { reactionsMentionCount = 0; updateReactionsMentionButton(true); getMessagesController().markReactionsAsRead(dialog_id); } else { updateReactionsMentionButton(true); scrollToMessageId(messageId, 0, false, 0, true, 0); } }); }); reactionsMentiondownButton.setOnLongClickListener(view -> { scrimPopupWindow = ReadAllMentionsMenu.show(ReadAllMentionsMenu.TYPE_REACTIONS, getParentActivity(), contentView, view, getResourceProvider(), () -> { for (int i = 0; i < messages.size(); i++) { messages.get(i).markReactionsAsRead(); } reactionsMentionCount = 0; updateReactionsMentionButton(true); getMessagesController().markReactionsAsRead(dialog_id); if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } }); dimBehindView(reactionsMentiondownButton, true); scrimPopupWindow.setOnDismissListener(() -> { scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); dimBehindView(false); if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } }); view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); return false; }); reactionsMentiondownButton.setVisibility(View.INVISIBLE); reactionsMentiondownButtonImage = new ImageView(context); reactionsMentiondownButtonImage.setImageResource(R.drawable.reactionbutton); reactionsMentiondownButtonImage.setScaleType(ImageView.ScaleType.CENTER); reactionsMentiondownButtonImage.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonIcon), PorterDuff.Mode.MULTIPLY)); if (Build.VERSION.SDK_INT >= 21) { reactionsMentiondownButtonImage.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); } }); drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton), getThemedColor(Theme.key_listSelector)); } else { drawable = Theme.createCircleDrawable(AndroidUtilities.dp(42), getThemedColor(Theme.key_chat_goDownButton)); } shadowDrawable = context.getResources().getDrawable(R.drawable.pagedown_shadow).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_goDownButtonShadow), PorterDuff.Mode.MULTIPLY)); combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); drawable = combinedDrawable; reactionsMentiondownButtonImage.setBackgroundDrawable(drawable); reactionsMentiondownButton.addView(reactionsMentiondownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.LEFT | Gravity.BOTTOM)); reactionsMentiondownButtonCounter = new CounterView(context, themeDelegate); reactionsMentiondownButton.addView(reactionsMentiondownButtonCounter, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.TOP | Gravity.LEFT)); reactionsMentiondownButton.setContentDescription(LocaleController.getString("AccDescrReactionMentionDown", R.string.AccDescrReactionMentionDown)); fragmentLocationContextView = new FragmentContextView(context, this, true, themeDelegate); fragmentContextView = new FragmentContextView(context, this, false, themeDelegate) { @Override protected void playbackSpeedChanged(float value) { if (Math.abs(value - 1.0f) < 0.001f || Math.abs(value - 1.8f) < 0.001f) { undoView.showWithAction(0, Math.abs(value - 1.0f) > 0.001f ? UndoView.ACTION_PLAYBACK_SPEED_ENABLED : UndoView.ACTION_PLAYBACK_SPEED_DISABLED, value, null, null); } } }; contentView.addView(fragmentLocationContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); contentView.addView(fragmentContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); fragmentContextView.setAdditionalContextView(fragmentLocationContextView); fragmentLocationContextView.setAdditionalContextView(fragmentContextView); fragmentContextView.setEnabled(!inPreviewMode); fragmentLocationContextView.setEnabled(!inPreviewMode); if (chatMode != 0) { fragmentContextView.setSupportsCalls(false); } messagesSearchListView = new RecyclerListView(context, themeDelegate); messagesSearchListView.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); LinearLayoutManager messagesSearchLayoutManager = new LinearLayoutManager(context); messagesSearchLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); messagesSearchListView.setLayoutManager(messagesSearchLayoutManager); messagesSearchListView.setVisibility(View.GONE); messagesSearchListView.setAlpha(0.0f); messagesSearchListView.setAdapter(messagesSearchAdapter = new MessagesSearchAdapter(context, themeDelegate)); contentView.addView(messagesSearchListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); messagesSearchListView.setOnItemClickListener((view, position) -> { getMediaDataController().jumpToSearchedMessage(classGuid, position); showMessagesSearchListView(false); }); messagesSearchListView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { int lastVisibleItem = messagesSearchLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; if (visibleItemCount > 0 && lastVisibleItem > messagesSearchLayoutManager.getItemCount() - 5) { getMediaDataController().loadMoreSearchMessages(); } } }); topUndoView = new UndoView(context, this, true, themeDelegate) { @Override public void didPressUrl(CharacterStyle span) { didPressMessageUrl(span, false, null, null); } @Override public void showWithAction(long did, int action, Object infoObject, Object infoObject2, Runnable actionRunnable, Runnable cancelRunnable) { setAdditionalTranslationY(fragmentContextView != null && fragmentContextView.isCallTypeVisible() ? AndroidUtilities.dp(fragmentContextView.getStyleHeight()) : 0); super.showWithAction(did, action, infoObject, infoObject2, actionRunnable, cancelRunnable); } }; contentView.addView(topUndoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 8, 8, 8, 0)); contentView.addView(actionBar); overlayView = new View(context); overlayView.setOnTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_DOWN) { checkRecordLocked(false); } overlayView.getParent().requestDisallowInterceptTouchEvent(true); return true; }); contentView.addView(overlayView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); overlayView.setVisibility(View.GONE); contentView.setClipChildren(false); instantCameraView = new InstantCameraView(context, this, themeDelegate); contentView.addView(instantCameraView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); bottomMessagesActionContainer = new BlurredFrameLayout(context, contentView) { @Override public void onDraw(Canvas canvas) { int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); Theme.chat_composeShadowDrawable.draw(canvas); AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight()); contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false); } }; bottomMessagesActionContainer.drawBlur = false; bottomMessagesActionContainer.isTopView = false; bottomMessagesActionContainer.setVisibility(View.INVISIBLE); bottomMessagesActionContainer.setWillNotDraw(false); bottomMessagesActionContainer.setPadding(0, AndroidUtilities.dp(2), 0, 0); contentView.addView(bottomMessagesActionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); bottomMessagesActionContainer.setOnTouchListener((v, event) -> true); chatActivityEnterView = new ChatActivityEnterView(getParentActivity(), contentView, this, true, themeDelegate) { int lastContentViewHeight; int messageEditTextPredrawHeigth; int messageEditTextPredrawScrollY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (getAlpha() != 1.0f) { return false; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { if (getAlpha() != 1.0f) { return false; } return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (getAlpha() != 1.0f) { return false; } return super.dispatchTouchEvent(ev); } @Override protected boolean pannelAnimationEnabled() { if (!openAnimationEnded) { return false; } return true; } @Override public void checkAnimation() { if (actionBar.isActionModeShowed() || reportType >= 0) { if (messageEditTextAnimator != null) { messageEditTextAnimator.cancel(); } if (changeBoundAnimator != null) { changeBoundAnimator.cancel(); } chatActivityEnterViewAnimateFromTop = 0; shouldAnimateEditTextWithBounds = false; } else { int t = getBackgroundTop(); if (chatActivityEnterViewAnimateFromTop != 0 && t != chatActivityEnterViewAnimateFromTop && lastContentViewHeight == contentView.getMeasuredHeight()) { int dy = animatedTop + chatActivityEnterViewAnimateFromTop - t; animatedTop = dy; if (changeBoundAnimator != null) { changeBoundAnimator.removeAllListeners(); changeBoundAnimator.cancel(); } chatListView.setTranslationY(dy); if (topView != null && topView.getVisibility() == View.VISIBLE) { topView.setTranslationY(animatedTop + (1f - topViewEnterProgress) * topView.getLayoutParams().height); if (topLineView != null) { topLineView.setTranslationY(animatedTop); } } if (mentionContainer != null) { mentionContainer.setTranslationY(dy); } changeBoundAnimator = ValueAnimator.ofFloat(dy, 0); changeBoundAnimator.addUpdateListener(a -> { float top = (float) a.getAnimatedValue(); animatedTop = (int) top; if (topView != null && topView.getVisibility() == View.VISIBLE) { topView.setTranslationY(top + (1f - topViewEnterProgress) * topView.getLayoutParams().height); if (topLineView != null) { topLineView.setTranslationY(top); } } else { if (mentionContainer != null) { mentionContainer.setTranslationY(top); } chatListView.setTranslationY(top); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } invalidate(); }); changeBoundAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animatedTop = 0; if (topView != null && topView.getVisibility() == View.VISIBLE) { topView.setTranslationY(animatedTop + (1f - topViewEnterProgress) * topView.getLayoutParams().height); if (topLineView != null) { topLineView.setTranslationY(animatedTop); } } else { chatListView.setTranslationY(0); if (mentionContainer != null) { mentionContainer.setTranslationY(0); } } changeBoundAnimator = null; } }); changeBoundAnimator.setDuration(ChatListItemAnimator.DEFAULT_DURATION); changeBoundAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); if (!waitingForSendingMessageLoad) { changeBoundAnimator.start(); } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); chatActivityEnterViewAnimateFromTop = 0; } else if (lastContentViewHeight != contentView.getMeasuredHeight()) { chatActivityEnterViewAnimateFromTop = 0; } if (shouldAnimateEditTextWithBounds) { float dy = (messageEditTextPredrawHeigth - messageEditText.getMeasuredHeight()) + (messageEditTextPredrawScrollY - messageEditText.getScrollY()); messageEditText.setOffsetY(messageEditText.getOffsetY() - dy); ValueAnimator a = ValueAnimator.ofFloat(messageEditText.getOffsetY(), 0); a.addUpdateListener(animation -> messageEditText.setOffsetY((float) animation.getAnimatedValue())); if (messageEditTextAnimator != null) { messageEditTextAnimator.cancel(); } messageEditTextAnimator = a; a.setDuration(ChatListItemAnimator.DEFAULT_DURATION); // a.setStartDelay(chatActivityEnterViewAnimateBeforeSending ? 20 : 0); a.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); a.start(); shouldAnimateEditTextWithBounds = false; } lastContentViewHeight = contentView.getMeasuredHeight(); chatActivityEnterViewAnimateBeforeSending = false; } } @Override protected void onLineCountChanged(int oldLineCount, int newLineCount) { if (chatActivityEnterView != null) { shouldAnimateEditTextWithBounds = true; messageEditTextPredrawHeigth = messageEditText.getMeasuredHeight(); messageEditTextPredrawScrollY = messageEditText.getScrollY(); contentView.invalidate(); chatActivityEnterViewAnimateFromTop = chatActivityEnterView.getBackgroundTop(); } } }; chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { int lastSize; boolean isEditTextItemVisibilitySuppressed; @Override public int getContentViewHeight() { return contentView.getHeight(); } @Override public int measureKeyboardHeight() { return contentView.measureKeyboardHeight(); } @Override public TLRPC.TL_channels_sendAsPeers getSendAsPeers() { return sendAsPeersObj; } @Override public void onMessageSend(CharSequence message, boolean notify, int scheduleDate) { if (chatListItemAnimator != null) { chatActivityEnterViewAnimateFromTop = chatActivityEnterView.getBackgroundTop(); if (chatActivityEnterViewAnimateFromTop != 0) { chatActivityEnterViewAnimateBeforeSending = true; } } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().addHashtagsFromMessage(message); } if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { scheduledMessagesCount = 0; } if (message != null) { scheduledMessagesCount++; } if (forwardingMessages != null && !forwardingMessages.messages.isEmpty()) { scheduledMessagesCount += forwardingMessages.messages.size(); } updateScheduledInterface(false); } hideFieldPanel(notify, scheduleDate, true); if (chatActivityEnterView != null && chatActivityEnterView.getEmojiView() != null) { chatActivityEnterView.getEmojiView().onMessageSend(); } } @Override public void onEditTextScroll() { if (suggestEmojiPanel != null) { suggestEmojiPanel.forceClose(); } } @Override public void onContextMenuOpen() { if (suggestEmojiPanel != null) { suggestEmojiPanel.forceClose(); } } @Override public void onContextMenuClose() { if (suggestEmojiPanel != null) { suggestEmojiPanel.fireUpdate(); } } @Override public void onSwitchRecordMode(boolean video) { showVoiceHint(false, video); } @Override public void onPreAudioVideoRecord() { showVoiceHint(true, false); } @Override public void onUpdateSlowModeButton(View button, boolean show, CharSequence time) { showSlowModeHint(button, show, time); if (headerItem != null && headerItem.getVisibility() != View.VISIBLE) { headerItem.setVisibility(View.VISIBLE); if (attachItem != null) { attachItem.setVisibility(View.GONE); } } } @Override public void onTextSelectionChanged(int start, int end) { if (editTextItem == null) { return; } if (suggestEmojiPanel != null) { suggestEmojiPanel.onTextSelectionChanged(start, end); } if (end - start > 0) { if (editTextItem.getTag() == null) { editTextItem.setTag(1); if (editTextItem.getVisibility() != View.VISIBLE) { if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0) { editTextItem.setVisibility(View.VISIBLE); headerItem.setVisibility(View.GONE); attachItem.setVisibility(View.GONE); } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(AndroidUtilities.dp(48), 0); valueAnimator.setDuration(220); valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { actionBar.setMenuOffsetSuppressed(true); editTextItem.setVisibility(View.VISIBLE); menu.translateXItems(AndroidUtilities.dp(48)); } @Override public void onAnimationEnd(Animator animation) { actionBar.setMenuOffsetSuppressed(false); } }); valueAnimator.addUpdateListener(animation -> menu.translateXItems((float) animation.getAnimatedValue())); valueAnimator.start(); } } } editTextStart = start; editTextEnd = end; } else { if (editTextItem.getTag() != null) { editTextItem.setTag(null); if (editTextItem.getVisibility() != View.GONE) { if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0) { editTextItem.setVisibility(View.GONE); if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { headerItem.setVisibility(View.GONE); attachItem.setVisibility(View.VISIBLE); } else { headerItem.setVisibility(View.VISIBLE); attachItem.setVisibility(View.GONE); } } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, AndroidUtilities.dp(48)); valueAnimator.setDuration(220); valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { actionBar.setMenuOffsetSuppressed(true); isEditTextItemVisibilitySuppressed = true; } @Override public void onAnimationEnd(Animator animation) { editTextItem.setVisibility(View.GONE); menu.translateXItems(0); actionBar.setMenuOffsetSuppressed(false); isEditTextItemVisibilitySuppressed = false; } }); valueAnimator.addUpdateListener(animation -> menu.translateXItems((float) animation.getAnimatedValue())); valueAnimator.start(); } } } } } @Override public void onTextChanged(final CharSequence text, boolean bigChange) { MediaController.getInstance().setInputFieldHasText(!TextUtils.isEmpty(text) || chatActivityEnterView.isEditingMessage()); if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().searchUsernameOrHashtag(text, chatActivityEnterView.getCursorPosition(), messages, false, false); } if (waitingForCharaterEnterRunnable != null) { AndroidUtilities.cancelRunOnUIThread(waitingForCharaterEnterRunnable); waitingForCharaterEnterRunnable = null; } if ((currentChat == null || ChatObject.canSendEmbed(currentChat)) && chatActivityEnterView.isMessageWebPageSearchEnabled() && (!chatActivityEnterView.isEditingMessage() || !chatActivityEnterView.isEditingCaption())) { if (bigChange) { searchLinks(text, true); } else { waitingForCharaterEnterRunnable = new Runnable() { @Override public void run() { if (this == waitingForCharaterEnterRunnable) { searchLinks(text, false); waitingForCharaterEnterRunnable = null; } } }; AndroidUtilities.runOnUIThread(waitingForCharaterEnterRunnable, AndroidUtilities.WEB_URL == null ? 3000 : 1000); } } } @Override public void onTextSpansChanged(CharSequence text) { searchLinks(text, true); } @Override public void needSendTyping() { getMessagesController().sendTyping(dialog_id, threadMessageId, 0, classGuid); } @Override public void onAttachButtonHidden() { if (actionBar.isSearchFieldVisible()) { return; } if (editTextItem != null && !isEditTextItemVisibilitySuppressed) { editTextItem.setVisibility(View.GONE); } if (TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { if (headerItem != null) { headerItem.setVisibility(View.GONE); } if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } } } @Override public void onAttachButtonShow() { if (actionBar.isSearchFieldVisible()) { return; } if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } if (editTextItem != null && !isEditTextItemVisibilitySuppressed) { editTextItem.setVisibility(View.GONE); } if (attachItem != null) { attachItem.setVisibility(View.GONE); } } @Override public void onMessageEditEnd(boolean loading) { if (chatListItemAnimator != null) { chatActivityEnterViewAnimateFromTop = chatActivityEnterView.getBackgroundTop(); if (chatActivityEnterViewAnimateFromTop != 0) { chatActivityEnterViewAnimateBeforeSending = true; } } if (!loading) { if (mentionContainer != null) { mentionContainer.getAdapter().setNeedBotContext(true); } if (editingMessageObject != null) { AndroidUtilities.runOnUIThread(() -> hideFieldPanel(true), 30); } boolean waitingForKeyboard = false; if (chatActivityEnterView.isPopupShowing()) { chatActivityEnterView.setFieldFocused(); waitingForKeyboard = true; } chatActivityEnterView.setAllowStickersAndGifs(true, true, true, waitingForKeyboard); if (editingMessageObjectReqId != 0) { getConnectionsManager().cancelRequest(editingMessageObjectReqId, true); editingMessageObjectReqId = 0; } updatePinnedMessageView(true); updateBottomOverlay(); updateVisibleRows(); } } @Override public void onWindowSizeChanged(int size) { if (size < AndroidUtilities.dp(72) + ActionBar.getCurrentActionBarHeight()) { allowStickersPanel = false; if (suggestEmojiPanel.getVisibility() == View.VISIBLE) { suggestEmojiPanel.setVisibility(View.INVISIBLE); } } else { allowStickersPanel = true; if (suggestEmojiPanel.getVisibility() == View.INVISIBLE) { suggestEmojiPanel.setVisibility(View.VISIBLE); } } allowContextBotPanel = !chatActivityEnterView.isPopupShowing(); // checkContextBotPanel(); int size2 = size + (chatActivityEnterView.isPopupShowing() ? 1 << 16 : 0); if (lastSize != size2) { chatActivityEnterViewAnimateFromTop = 0; chatActivityEnterViewAnimateBeforeSending = false; } lastSize = size2; } @Override public void onStickersTab(boolean opened) { if (emojiButtonRed != null) { emojiButtonRed.setVisibility(View.GONE); } allowContextBotPanelSecond = !opened; // checkContextBotPanel(); } @Override public void didPressAttachButton() { if (chatAttachAlert != null) { chatAttachAlert.setEditingMessageObject(null); } openAttachMenu(); } @Override public void needStartRecordVideo(int state, boolean notify, int scheduleDate) { if (instantCameraView != null) { if (state == 0) { instantCameraView.showCamera(); chatListView.stopScroll(); chatAdapter.updateRowsSafe(); } else if (state == 1 || state == 3 || state == 4) { instantCameraView.send(state, notify, scheduleDate); } else if (state == 2 || state == 5) { instantCameraView.cancel(state == 2); } } } @Override public void needChangeVideoPreviewState(int state, float seekProgress) { if (instantCameraView != null) { instantCameraView.changeVideoPreviewState(state, seekProgress); } } @Override public void needStartRecordAudio(int state) { int visibility = state == 0 ? View.GONE : View.VISIBLE; if (overlayView.getVisibility() != visibility) { overlayView.setVisibility(visibility); } } @Override public void needShowMediaBanHint() { showMediaBannedHint(); } @Override public void onStickersExpandedChange() { checkRaiseSensors(); if (chatActivityEnterView.isStickersExpanded()) { AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); if (Bulletin.getVisibleBulletin() != null && Bulletin.getVisibleBulletin().isShowing()) { Bulletin.getVisibleBulletin().hide(); } } else { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } if (mentionContainer != null) { mentionContainer.animate().alpha(chatActivityEnterView.isStickersExpanded() ? 0 : 1f).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } if (suggestEmojiPanel != null) { suggestEmojiPanel.setVisibility(View.VISIBLE); suggestEmojiPanel.animate().alpha(chatActivityEnterView.isStickersExpanded() ? 0 : 1f).setInterpolator(CubicBezierInterpolator.DEFAULT).withEndAction(() -> { if (suggestEmojiPanel != null && chatActivityEnterView.isStickersExpanded()) { suggestEmojiPanel.setVisibility(View.GONE); } }).start(); } } @Override public void scrollToSendingMessage() { int id = getSendMessagesHelper().getSendingMessageId(dialog_id); if (id != 0) { scrollToMessageId(id, 0, true, 0, true, 0); } } @Override public boolean hasScheduledMessages() { return scheduledMessagesCount > 0 && chatMode == 0; } @Override public void onSendLongClick() { if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } } @Override public void openScheduledMessages() { ChatActivity.this.openScheduledMessages(); } @Override public void onAudioVideoInterfaceUpdated() { updatePagedownButtonVisibility(true); } @Override public void bottomPanelTranslationYChanged(float translation) { if (translation != 0) { wasManualScroll = true; } bottomPanelTranslationY = chatActivityEnterView.panelAnimationInProgress() ? chatActivityEnterView.getEmojiPadding() - translation : 0; bottomPanelTranslationYReverse = chatActivityEnterView.panelAnimationInProgress() ? translation : 0; chatActivityEnterView.setTranslationY(translation); mentionContainer.setTranslationY(translation); contentView.setEmojiOffset(chatActivityEnterView.panelAnimationInProgress(), bottomPanelTranslationY); translation += chatActivityEnterView.getTopViewTranslation(); mentionContainer.setTranslationY(translation); chatListView.setTranslationY(translation); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); updateTextureViewPosition(false); contentView.invalidate(); updateBulletinLayout(); } @Override public void prepareMessageSending() { waitingForSendingMessageLoad = true; } @Override public void onTrendingStickersShowed(boolean show) { if (show) { AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); fragmentView.requestLayout(); } else { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } @Override public boolean hasForwardingMessages() { return forwardingMessages != null && !forwardingMessages.messages.isEmpty(); } }); chatActivityEnterView.setDialogId(dialog_id, currentAccount); if (chatInfo != null) { chatActivityEnterView.setChatInfo(chatInfo); } chatActivityEnterView.setId(id_chat_compose_panel); chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands, false); chatActivityEnterView.updateBotWebView(false); chatActivityEnterView.setMinimumHeight(AndroidUtilities.dp(51)); chatActivityEnterView.setAllowStickersAndGifs(true, true, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); if (inPreviewMode) { chatActivityEnterView.setVisibility(View.INVISIBLE); } if (!ChatObject.isChannel(currentChat) || currentChat.megagroup) { chatActivityEnterView.setBotInfo(botInfo, false); } contentView.addView(chatActivityEnterView, contentView.getChildCount() - 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); chatActivityEnterView.checkChannelRights(); chatActivityEnterTopView = new ChatActivityEnterTopView(context) { @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); if (chatActivityEnterView != null) { chatActivityEnterView.invalidate(); } if (getVisibility() != GONE) { hideHints(true); if (chatListView != null) { chatListView.setTranslationY(translationY); } if (progressView != null) { progressView.setTranslationY(translationY); } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); if (fragmentView != null) { fragmentView.invalidate(); } } } @Override public boolean hasOverlappingRendering() { return false; } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); if (visibility == GONE) { if (chatListView != null) { chatListView.setTranslationY(0); } if (progressView != null) { progressView.setTranslationY(0); } } } }; replyLineView = new View(context); replyLineView.setBackgroundColor(getThemedColor(Theme.key_chat_replyPanelLine)); chatActivityEnterView.addTopView(chatActivityEnterTopView, replyLineView, 48); final FrameLayout replyLayout = new FrameLayout(context); chatActivityEnterTopView.addReplyView(replyLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 52, 0)); replyLayout.setOnClickListener(v -> { if (forwardingMessages != null && !forwardingMessages.messages.isEmpty()) { SharedConfig.forwardingOptionsHintHintShowed(); openForwardingPreview(); } else if (replyingMessageObject != null && (!isThreadChat() || replyingMessageObject.getId() != threadMessageId)) { scrollToMessageId(replyingMessageObject.getId(), 0, true, 0, true, 0); } else if (editingMessageObject != null) { if (editingMessageObject.canEditMedia() && editingMessageObjectReqId == 0) { if (chatAttachAlert == null) { createChatAttachView(); } chatAttachAlert.setEditingMessageObject(editingMessageObject); openAttachMenu(); } else { scrollToMessageId(editingMessageObject.getId(), 0, true, 0, true, 0); } } }); replyIconImageView = new ImageView(context); replyIconImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_replyPanelIcons), PorterDuff.Mode.MULTIPLY)); replyIconImageView.setScaleType(ImageView.ScaleType.CENTER); replyLayout.addView(replyIconImageView, LayoutHelper.createFrame(52, 46, Gravity.TOP | Gravity.LEFT)); replyCloseImageView = new ImageView(context); replyCloseImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_replyPanelClose), PorterDuff.Mode.MULTIPLY)); replyCloseImageView.setImageResource(R.drawable.input_clear); replyCloseImageView.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { replyCloseImageView.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(18))); } chatActivityEnterTopView.addView(replyCloseImageView, LayoutHelper.createFrame(52, 46, Gravity.RIGHT | Gravity.TOP, 0, 0.5f, 0, 0)); replyCloseImageView.setOnClickListener(v -> { if (forwardingMessages == null || forwardingMessages.messages.isEmpty()) { showFieldPanel(false, null, null, null, foundWebPage, true, 0, true, true); } else { openAnotherForward(); } }); replyNameTextView = new SimpleTextView(context); replyNameTextView.setTextSize(14); replyNameTextView.setTextColor(getThemedColor(Theme.key_chat_replyPanelName)); replyNameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); replyLayout.addView(replyNameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 52, 6, 0, 0)); replyObjectTextView = new SimpleTextView(context); replyObjectTextView.setTextSize(14); replyObjectTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); replyLayout.addView(replyObjectTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 52, 24, 0, 0)); replyObjectHintTextView = new SimpleTextView(context); replyObjectHintTextView.setTextSize(14); replyObjectHintTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); replyObjectHintTextView.setText(LocaleController.getString("TapForForwardingOptions", R.string.TapForForwardingOptions)); replyObjectHintTextView.setAlpha(0f); replyLayout.addView(replyObjectHintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 52, 24, 0, 0)); replyImageView = new BackupImageView(context); replyImageView.setRoundRadius(AndroidUtilities.dp(2)); replyLayout.addView(replyImageView, LayoutHelper.createFrame(34, 34, Gravity.TOP | Gravity.LEFT, 52, 6, 0, 0)); suggestEmojiPanel = new SuggestEmojiView(context, currentAccount, chatActivityEnterView, themeDelegate); contentView.addView(suggestEmojiPanel, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 160, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 0)); final ChatActivityEnterTopView.EditView editView = new ChatActivityEnterTopView.EditView(context); editView.setMotionEventSplittingEnabled(false); editView.setOrientation(LinearLayout.HORIZONTAL); editView.setOnClickListener(v -> { if (editingMessageObject != null) { scrollToMessageId(editingMessageObject.getId(), 0, true, 0, true, 0); } }); chatActivityEnterTopView.addEditView(editView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 48, 0)); for (int i = 0; i < 2; i++) { final boolean firstButton = i == 0; final ChatActivityEnterTopView.EditViewButton button = new ChatActivityEnterTopView.EditViewButton(context) { @Override public void setEditButton(boolean editButton) { super.setEditButton(editButton); if (firstButton) { getTextView().setMaxWidth(editButton ? AndroidUtilities.dp(116) : Integer.MAX_VALUE); } } @Override public void updateColors() { final int leftInset = firstButton ? AndroidUtilities.dp(14) : 0; setBackground(Theme.createCircleSelectorDrawable(getThemedColor(Theme.key_chat_replyPanelName) & 0x19ffffff, leftInset, 0)); getImageView().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_replyPanelName), PorterDuff.Mode.MULTIPLY)); getTextView().setTextColor(getThemedColor(Theme.key_chat_replyPanelName)); } }; button.setOrientation(LinearLayout.HORIZONTAL); ViewHelper.setPadding(button, 10, 0, 10, 0); editView.addButton(button, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); final ImageView imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); imageView.setImageResource(firstButton ? R.drawable.msg_photoeditor : R.drawable.msg_replace); button.addImageView(imageView, LayoutHelper.createLinear(24, LayoutHelper.MATCH_PARENT)); button.addView(new Space(context), LayoutHelper.createLinear(10, LayoutHelper.MATCH_PARENT)); final TextView textView = new TextView(context); textView.setMaxLines(1); textView.setSingleLine(true); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); textView.setEllipsize(TextUtils.TruncateAt.END); button.addTextView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); button.updateColors(); button.setOnClickListener(v -> { if (editingMessageObject == null || !editingMessageObject.canEditMedia() || editingMessageObjectReqId != 0) { return; } if (button.isEditButton()) { openEditingMessageInPhotoEditor(); } else { replyLayout.callOnClick(); } }); } searchContainer = new BlurredFrameLayout(context, contentView) { @Override public void onDraw(Canvas canvas) { int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); if (chatActivityEnterView.getVisibility() != View.VISIBLE) { Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); Theme.chat_composeShadowDrawable.draw(canvas); } AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight()); contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false); } @Override protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { if (child == searchCountText) { int leftMargin = 14; if (searchCalendarButton != null && searchCalendarButton.getVisibility() != GONE) { leftMargin += 48; } if (searchUserButton != null && searchUserButton.getVisibility() != GONE) { leftMargin += 48; } ((MarginLayoutParams) child.getLayoutParams()).leftMargin = AndroidUtilities.dp(leftMargin); } super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } }; searchContainer.drawBlur = false; searchContainer.isTopView = false; searchContainer.setWillNotDraw(false); searchContainer.setVisibility(View.INVISIBLE); searchContainer.setPadding(0, AndroidUtilities.dp(3), 0, 0); searchContainer.setClipToPadding(false); searchAsListTogglerView = new View(context); searchAsListTogglerView.setOnTouchListener((v, event) -> getMediaDataController().getFoundMessageObjects().size() <= 1); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { searchAsListTogglerView.setBackground(Theme.getSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false)); } searchAsListTogglerView.setOnClickListener(v -> { if (getMediaDataController().getFoundMessageObjects().size() > 1) { if (searchAsListHint != null) { searchAsListHint.hide(); } toggleMesagesSearchListView(); if (!SharedConfig.searchMessagesAsListUsed) { SharedConfig.setSearchMessagesAsListUsed(true); } } }); final float paddingTop = Theme.chat_composeShadowDrawable.getIntrinsicHeight() / AndroidUtilities.density - 3f; searchContainer.addView(searchAsListTogglerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, paddingTop, 0, 0)); searchUpButton = new ImageView(context); searchUpButton.setScaleType(ImageView.ScaleType.CENTER); searchUpButton.setImageResource(R.drawable.msg_go_up); searchUpButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); searchUpButton.setOnClickListener(view -> { getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, threadMessageId, searchingUserMessages, searchingChatMessages); showMessagesSearchListView(false); if (!SharedConfig.searchMessagesAsListUsed && SharedConfig.searchMessagesAsListHintShows < 3 && !searchAsListHintShown && Math.random() <= 0.25) { showSearchAsListHint(); searchAsListHintShown = true; SharedConfig.increaseSearchAsListHintShows(); } }); searchUpButton.setContentDescription(LocaleController.getString("AccDescrSearchNext", R.string.AccDescrSearchNext)); searchDownButton = new ImageView(context); searchDownButton.setScaleType(ImageView.ScaleType.CENTER); searchDownButton.setImageResource(R.drawable.msg_go_down); searchDownButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); searchDownButton.setOnClickListener(view -> { getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, threadMessageId, searchingUserMessages, searchingChatMessages); showMessagesSearchListView(false); }); searchDownButton.setContentDescription(LocaleController.getString("AccDescrSearchPrev", R.string.AccDescrSearchPrev)); if (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) { searchUserButton = new ImageView(context); searchUserButton.setScaleType(ImageView.ScaleType.CENTER); searchUserButton.setImageResource(R.drawable.msg_usersearch); searchUserButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchUserButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUserButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 48, 0, 0, 0)); searchUserButton.setOnClickListener(view -> { if (mentionContainer != null) { mentionContainer.setReversed(true); mentionContainer.getAdapter().setSearchingMentions(true); } searchCalendarButton.setVisibility(View.GONE); searchUserButton.setVisibility(View.GONE); searchingForUser = true; searchingUserMessages = null; searchingChatMessages = null; searchItem.setSearchFieldHint(LocaleController.getString("SearchMembers", R.string.SearchMembers)); searchItem.setSearchFieldCaption(LocaleController.getString("SearchFrom", R.string.SearchFrom)); AndroidUtilities.showKeyboard(searchItem.getSearchField()); searchItem.clearSearchText(); }); searchUserButton.setContentDescription(LocaleController.getString("AccDescrSearchByUser", R.string.AccDescrSearchByUser)); } searchCalendarButton = new ImageView(context); searchCalendarButton.setScaleType(ImageView.ScaleType.CENTER); searchCalendarButton.setImageResource(R.drawable.msg_calendar); searchCalendarButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchCalendarButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); searchCalendarButton.setOnClickListener(view -> { if (getParentActivity() == null) { return; } AndroidUtilities.hideKeyboard(searchItem.getSearchField()); showDialog(AlertsCreator.createCalendarPickerDialog(getParentActivity(), 1375315200000L, new MessagesStorage.IntCallback() { @Override public void run(int param) { jumpToDate(param); } }, themeDelegate).create()); }); searchCalendarButton.setContentDescription(LocaleController.getString("JumpToDate", R.string.JumpToDate)); searchCountText = new SearchCounterView(context, themeDelegate); searchCountText.setGravity(Gravity.LEFT); searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 108, 0)); bottomOverlay = new FrameLayout(context) { @Override public void onDraw(Canvas canvas) { int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); Theme.chat_composeShadowDrawable.draw(canvas); canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground)); } }; bottomOverlay.setWillNotDraw(false); bottomOverlay.setVisibility(View.INVISIBLE); bottomOverlay.setFocusable(true); bottomOverlay.setFocusableInTouchMode(true); bottomOverlay.setClickable(true); bottomOverlay.setPadding(0, AndroidUtilities.dp(2), 0, 0); contentView.addView(bottomOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); bottomOverlayText = new TextView(context); bottomOverlayText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); bottomOverlayText.setGravity(Gravity.CENTER); bottomOverlayText.setMaxLines(2); bottomOverlayText.setEllipsize(TextUtils.TruncateAt.END); bottomOverlayText.setLineSpacing(AndroidUtilities.dp(2), 1); bottomOverlayText.setTextColor(getThemedColor(Theme.key_chat_secretChatStatusText)); bottomOverlay.addView(bottomOverlayText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 14, 0, 14, 0)); bottomOverlayChat = new BlurredFrameLayout(context, contentView) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int allWidth = MeasureSpec.getSize(widthMeasureSpec); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) bottomOverlayChatText.getLayoutParams(); layoutParams.width = allWidth; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void dispatchDraw(Canvas canvas) { int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); Theme.chat_composeShadowDrawable.draw(canvas); if (SharedConfig.chatBlurEnabled()) { if (backgroundPaint == null) { backgroundPaint = new Paint(); } backgroundPaint.setColor(getThemedColor(Theme.key_chat_messagePanelBackground)); AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight()); contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, backgroundPaint, false); } else { canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground)); } super.dispatchDraw(canvas); } }; bottomOverlayChat.isTopView = false; bottomOverlayChat.drawBlur = false; bottomOverlayChat.setWillNotDraw(false); bottomOverlayChat.setPadding(0, AndroidUtilities.dp(1.5f), 0, 0); bottomOverlayChat.setVisibility(View.INVISIBLE); bottomOverlayChat.setClipChildren(false); contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); bottomOverlayChatText = new UnreadCounterTextView(context); bottomOverlayChat.addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 1.5f, 0, 0)); bottomOverlayChatText.setOnClickListener(view -> { if (getParentActivity() == null || pullingDownOffset != 0) { return; } if (reportType >= 0) { showDialog(new ReportAlert(getParentActivity(), reportType) { @Override protected void onSend(int type, String message) { ArrayList ids = new ArrayList<>(); for (int b = 0; b < selectedMessagesIds[0].size(); b++) { ids.add(selectedMessagesIds[0].keyAt(b)); } TLRPC.InputPeer peer = currentUser != null ? MessagesController.getInputPeer(currentUser) : MessagesController.getInputPeer(currentChat); AlertsCreator.sendReport(peer, reportType, message, ids); finishFragment(); chatActivityDelegate.onReport(); } }); } else if (chatMode == MODE_PINNED) { finishFragment(); chatActivityDelegate.onUnpin(true, bottomOverlayChatText.getTag() == null); } else if (currentUser != null && userBlocked) { if (currentUser.bot) { String botUserLast = botUser; botUser = null; getMessagesController().unblockPeer(currentUser.id); if (botUserLast != null && botUserLast.length() != 0) { getMessagesController().sendBotStart(currentUser, botUserLast); } else { getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, null, false, null, null, null, true, 0, null); } } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setMessage(LocaleController.getString("AreYouSureUnblockContact", R.string.AreYouSureUnblockContact)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> getMessagesController().unblockPeer(currentUser.id)); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } } else if (UserObject.isReplyUser(currentUser)) { toggleMute(true); } else if (currentUser != null && currentUser.bot && botUser != null) { if (botUser.length() != 0) { getMessagesController().sendBotStart(currentUser, botUser); } else { getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, null, false, null, null, null, true, 0, null); } botUser = null; updateBottomOverlay(); } else { if (ChatObject.isChannel(currentChat) && !(currentChat instanceof TLRPC.TL_channelForbidden)) { if (ChatObject.isNotInChat(currentChat)) { if (currentChat.join_request) { // showDialog(new JoinGroupAlert(context, currentChat, null, this)); showBottomOverlayProgress(true, true); MessagesController.getInstance(currentAccount).addUserToChat( currentChat.id, UserConfig.getInstance(currentAccount).getCurrentUser(), 0, null, null, true, () -> { showBottomOverlayProgress(false, true); }, err -> { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putLong("dialog_join_requested_time_" + dialog_id, System.currentTimeMillis()).commit(); if (err != null && "INVITE_REQUEST_SENT".equals(err.text)) { JoinGroupAlert.showBulletin(context, this, ChatObject.isChannel(currentChat) && !currentChat.megagroup); } showBottomOverlayProgress(false, true); return false; } ); } else { if (chatInviteRunnable != null) { AndroidUtilities.cancelRunOnUIThread(chatInviteRunnable); chatInviteRunnable = null; } showBottomOverlayProgress(true, true); getMessagesController().addUserToChat(currentChat.id, getUserConfig().getCurrentUser(), 0, null, ChatActivity.this, null); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); if (hasReportSpam() && reportSpamButton.getTag(R.id.object_tag) != null) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putInt("dialog_bar_vis3" + dialog_id, 3).commit(); getNotificationCenter().postNotificationName(NotificationCenter.peerSettingsDidLoad, dialog_id); } } } else { toggleMute(true); } } else { boolean canDeleteHistory = chatInfo != null && chatInfo.can_delete_channel; AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, false, currentChat, currentUser, currentEncryptedChat != null, true, canDeleteHistory, (param) -> { getNotificationCenter().removeObserver(ChatActivity.this, NotificationCenter.closeChats); getNotificationCenter().postNotificationName(NotificationCenter.closeChats); finishFragment(); getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat, param); }, themeDelegate); } } }); bottomOverlayProgress = new RadialProgressView(context, themeDelegate); bottomOverlayProgress.setSize(AndroidUtilities.dp(22)); bottomOverlayProgress.setProgressColor(getThemedColor(Theme.key_chat_fieldOverlayText)); bottomOverlayProgress.setVisibility(View.INVISIBLE); bottomOverlayProgress.setScaleX(0.1f); bottomOverlayProgress.setScaleY(0.1f); bottomOverlayProgress.setAlpha(1.0f); bottomOverlayChat.addView(bottomOverlayProgress, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); bottomOverlayImage = new ImageView(context); int color = getThemedColor(Theme.key_chat_fieldOverlayText); bottomOverlayImage.setImageResource(R.drawable.msg_help); bottomOverlayImage.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); bottomOverlayImage.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { bottomOverlayImage.setBackgroundDrawable(Theme.createSelectorDrawable(Color.argb(24, Color.red(color), Color.green(color), Color.blue(color)), 1)); } bottomOverlayChat.addView(bottomOverlayImage, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 3, 1.5f, 0, 0)); bottomOverlayImage.setContentDescription(LocaleController.getString("SettingsHelp", R.string.SettingsHelp)); bottomOverlayImage.setOnClickListener(v -> undoView.showWithAction(dialog_id, UndoView.ACTION_TEXT_INFO, LocaleController.getString("BroadcastGroupInfo", R.string.BroadcastGroupInfo))); replyButton = new TextView(context); replyButton.setText(LocaleController.getString("Reply", R.string.Reply)); replyButton.setGravity(Gravity.CENTER_VERTICAL); replyButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); replyButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(21), 0); replyButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 3)); replyButton.setTextColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); replyButton.setCompoundDrawablePadding(AndroidUtilities.dp(7)); replyButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); Drawable image = context.getResources().getDrawable(R.drawable.input_reply).mutate(); image.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); replyButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); replyButton.setOnClickListener(v -> { MessageObject messageObject = null; for (int a = 1; a >= 0; a--) { if (messageObject == null && selectedMessagesIds[a].size() != 0) { messageObject = messagesDict[a].get(selectedMessagesIds[a].keyAt(0)); } selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } hideActionMode(); if (messageObject != null && (messageObject.messageOwner.id > 0 || messageObject.messageOwner.id < 0 && currentEncryptedChat != null)) { showFieldPanelForReply(messageObject); } updatePinnedMessageView(true); updateVisibleRows(); }); bottomMessagesActionContainer.addView(replyButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); forwardButton = new TextView(context); forwardButton.setText(LocaleController.getString("Forward", R.string.Forward)); forwardButton.setGravity(Gravity.CENTER_VERTICAL); forwardButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); forwardButton.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); forwardButton.setCompoundDrawablePadding(AndroidUtilities.dp(6)); forwardButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 3)); forwardButton.setTextColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); forwardButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); image = context.getResources().getDrawable(R.drawable.input_forward).mutate(); image.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); forwardButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); forwardButton.setOnClickListener(v -> openForward(false)); bottomMessagesActionContainer.addView(forwardButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP)); contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); contentView.addView(messageEnterTransitionContainer = new MessageEnterTransitionContainer(contentView, currentAccount)); undoView = new UndoView(context, this, false, themeDelegate); undoView.setAdditionalTranslationY(AndroidUtilities.dp(51)); contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); if (currentChat != null) { slowModeHint = new HintView(getParentActivity(), 2, themeDelegate); slowModeHint.setAlpha(0.0f); slowModeHint.setVisibility(View.INVISIBLE); contentView.addView(slowModeHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); } chatAdapter.updateRowsSafe(); if (loading && messages.isEmpty()) { showProgressView(chatAdapter.botInfoRow < 0); chatListView.setEmptyView(null); } else { showProgressView(false); chatListView.setEmptyView(emptyViewContainer); } checkBotKeyboard(); updateBottomOverlay(); updateSecretStatus(); updateTopPanel(false); updatePinnedMessageView(false); updateInfoTopView(false); chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager); chatScrollHelper.setScrollListener(this::invalidateMessagesVisiblePart); chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); if (currentEncryptedChat != null && (SharedConfig.passcodeHash.length() == 0 || SharedConfig.allowScreenCapture)) { unregisterFlagSecurePasscode = AndroidUtilities.registerFlagSecure(getParentActivity().getWindow()); } if (getMessagesController().isChatNoForwards(currentChat)) { unregisterFlagSecureNoforwards = AndroidUtilities.registerFlagSecure(getParentActivity().getWindow()); } if (oldMessage != null) { chatActivityEnterView.setFieldText(oldMessage); } fixLayoutInternal(); textSelectionHelper.setCallback(new TextSelectionHelper.Callback() { @Override public void onStateChanged(boolean isSelected) { swipeBackEnabled = !isSelected; if (isSelected) { if (slidingView != null) { slidingView.setSlidingOffset(0); slidingView = null; } maybeStartTrackingSlidingView = false; startedTrackingSlidingView = false; if (textSelectionHint != null) { textSelectionHint.hide(); } } updatePagedownButtonVisibility(true); } @Override public void onTextCopied() { if (actionBar != null && actionBar.isActionModeShowed()) { clearSelectionMode(); } undoView.showWithAction(0, UndoView.ACTION_TEXT_COPIED, null); } }); contentView.addView(textSelectionHelper.getOverlayView(context)); fireworksOverlay = new FireworksOverlay(context); contentView.addView(fireworksOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); textSelectionHelper.setParentView(chatListView); long searchFromUserId = getArguments().getInt("search_from_user_id", 0); long searchFromChatId = getArguments().getInt("search_from_chat_id", 0); if (searchFromUserId != 0) { TLRPC.User user = getMessagesController().getUser(searchFromUserId); if (user != null) { openSearchWithText(""); searchUserButton.callOnClick(); searchUserMessages(user, null); } } else if (searchFromChatId != 0) { TLRPC.Chat chat = getMessagesController().getChat(searchFromChatId); if (chat != null) { openSearchWithText(""); searchUserButton.callOnClick(); searchUserMessages(null, chat); } } if (replyingMessageObject != null) { chatActivityEnterView.setReplyingMessageObject(replyingMessageObject); } ViewGroup decorView; if (Build.VERSION.SDK_INT >= 21) { decorView = (ViewGroup) getParentActivity().getWindow().getDecorView(); } else { decorView = contentView; } pinchToZoomHelper = new PinchToZoomHelper(decorView, contentView) { @Override protected void drawOverlays(Canvas canvas, float alpha, float parentOffsetX, float parentOffsetY, float clipTop, float clipBottom) { if (alpha > 0) { View view = getChild(); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; int top = (int) Math.max(clipTop, parentOffsetY); int bottom = (int) Math.min(clipBottom, parentOffsetY + cell.getMeasuredHeight()); AndroidUtilities.rectTmp.set(parentOffsetX, top, parentOffsetX + cell.getMeasuredWidth(), bottom); canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (255 * alpha), Canvas.ALL_SAVE_FLAG); canvas.translate(parentOffsetX, parentOffsetY); cell.drawFromPinchToZoom = true; cell.drawOverlays(canvas); if (cell.shouldDrawTimeOnMedia() && cell.getCurrentMessagesGroup() == null) { cell.drawTime(canvas, 1f, false); } cell.drawFromPinchToZoom = false; canvas.restore(); } } } }; pinchToZoomHelper.setCallback(new PinchToZoomHelper.Callback() { @Override public TextureView getCurrentTextureView() { return videoTextureView; } @Override public void onZoomStarted(MessageObject messageObject) { chatListView.cancelClickRunnables(true); chatListView.stopScroll(); if (MediaController.getInstance().isPlayingMessage(messageObject)) { contentView.removeView(videoPlayerContainer); videoPlayerContainer = null; videoTextureView = null; aspectRatioFrameLayout = null; } for (int i = 0; i < chatListView.getChildCount(); i++) { if (chatListView.getChildAt(i) instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) chatListView.getChildAt(i); if (cell.getMessageObject().getId() == messageObject.getId()) { cell.getPhotoImage().setVisible(false, true); } } } } @Override public void onZoomFinished(MessageObject messageObject) { if (messageObject == null) { return; } if (MediaController.getInstance().isPlayingMessage(messageObject)) { for (int i = 0; i < chatListView.getChildCount(); i++) { if (chatListView.getChildAt(i) instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) chatListView.getChildAt(i); if (cell.getMessageObject().getId() == messageObject.getId()) { AnimatedFileDrawable animation = cell.getPhotoImage().getAnimation(); if (animation.isRunning()) { animation.stop(); } if (animation != null) { Bitmap bitmap = animation.getAnimatedBitmap(); if (bitmap != null) { try { Bitmap src = pinchToZoomHelper.getVideoBitmap(bitmap.getWidth(), bitmap.getHeight()); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(src, 0, 0, null); src.recycle(); } catch (Throwable e) { FileLog.e(e); } } } } } } createTextureView(true); MediaController.getInstance().setTextureView(videoTextureView, aspectRatioFrameLayout, videoPlayerContainer, true); } chatListView.invalidate(); } }); pinchToZoomHelper.setClipBoundsListener(topBottom -> { topBottom[1] = chatListView.getBottom() - blurredViewBottomOffset; topBottom[0] = chatListView.getTop() + chatListViewPaddingTop - AndroidUtilities.dp(4); }); emojiAnimationsOverlay = new EmojiAnimationsOverlay(ChatActivity.this, contentView, chatListView, currentAccount, dialog_id, threadMessageId) { @Override public void onAllEffectsEnd() { updateMessagesVisiblePart(false); } }; actionBar.setDrawBlurBackground(contentView); TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id); if (dialog != null) { reactionsMentionCount = dialog.unread_reactions_count; updateReactionsMentionButton(false); } return fragmentView; } public ActionBarMenuItem getHeaderItem() { return headerItem; } private void playReactionAnimation(Integer messageId) { if (fragmentView == null) { return; } ChatMessageCell cell = findMessageCell(messageId, false); if (cell != null) { TLRPC.TL_messagePeerReaction reaction = cell.getMessageObject().getRandomUnreadReaction(); if (reaction != null && cell.reactionsLayoutInBubble.hasUnreadReactions) { ReactionsEffectOverlay.show(ChatActivity.this, null, cell, 0, 0, reaction.reaction, currentAccount, reaction.big ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } cell.markReactionsAsRead(); } } private void dimBehindView(View view, boolean enable) { scrimView = view; dimBehindView(enable ? 0.2f : 0, view != reactionsMentiondownButton && view != mentiondownButton); } private void dimBehindView(View view, float value) { scrimView = view; dimBehindView(value, view != reactionsMentiondownButton && view != mentiondownButton); } public void dimBehindView(boolean enable) { dimBehindView(enable ? 0.2f : 0, true); } private void dimBehindView(float value, boolean hidePagedownButtons) { boolean enable = value > 0; if (scrimView instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) scrimView; cell.setInvalidatesParent(enable); if (enable) { restartSticker(cell); } } contentView.invalidate(); chatListView.invalidate(); if (scrimAnimatorSet != null) { scrimAnimatorSet.removeAllListeners(); scrimAnimatorSet.cancel(); } scrimAnimatorSet = new AnimatorSet(); ArrayList animators = new ArrayList<>(); ValueAnimator scrimPaintAlphaAnimator; if (enable) { scrimViewAlpha = 1f; if (scrimViewAlphaAnimator != null) { scrimViewAlphaAnimator.cancel(); } animators.add(scrimPaintAlphaAnimator = ValueAnimator.ofFloat(0, value)); } else { animators.add(scrimPaintAlphaAnimator = ValueAnimator.ofFloat(scrimPaintAlpha, 0)); } scrimPaintAlphaAnimator.addUpdateListener(a -> { scrimPaintAlpha = (float) a.getAnimatedValue(); if (fragmentView != null) { fragmentView.invalidate(); } }); if (!enable || hidePagedownButtons) { if (pagedownButton != null) { animators.add(ObjectAnimator.ofFloat(pagedownButton, View.ALPHA, enable ? 0 : 1)); } if (mentiondownButton != null) { animators.add(ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, enable ? 0 : 1)); } if (reactionsMentiondownButton != null) { animators.add(ObjectAnimator.ofFloat(reactionsMentiondownButton, View.ALPHA, enable ? 0 : 1)); } } scrimAnimatorSet.playTogether(animators); scrimAnimatorSet.setDuration(enable ? 150 : 220); scrimAnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (!enable) { scrimView = null; scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); } } }); if (scrimView != null && scrimViewAlpha <= 0f) { scrimView = null; } scrimAnimatorSet.start(); } private class PinnedMessageButton extends TextView { public PinnedMessageButton(Context context) { super(context); setSingleLine(true); setLines(1); setMaxLines(1); setEllipsize(TextUtils.TruncateAt.END); setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 16)); setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); setGravity(Gravity.CENTER); setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14), 0); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( View.MeasureSpec.makeMeasureSpec(Math.min(View.MeasureSpec.getSize(widthMeasureSpec), (int) (AndroidUtilities.displaySize.x * 0.45f)), View.MeasureSpec.AT_MOST), heightMeasureSpec ); } }; private void updatePagedownButtonsPosition() { float baseTranslationY = chatActivityEnterView.getAnimatedTop() + chatActivityEnterView.getTranslationY() + (chatActivityEnterTopView.getVisibility() == View.VISIBLE ? chatActivityEnterTopView.getTranslationY() : 0); if (pagedownButton != null) { pagedownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - pagedownButtonEnterProgress)); } if (mentiondownButton != null) { mentiondownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - mentionsButtonEnterProgress) - (AndroidUtilities.dp(72) * pagedownButtonEnterProgress) * mentionsButtonEnterProgress); } if (reactionsMentiondownButton != null) { reactionsMentiondownButton.setTranslationY(baseTranslationY + AndroidUtilities.dp(100) * (1f - reactionsMentionButtonEnterProgress) - ((AndroidUtilities.dp(50) + AndroidUtilities.dp(22) * pagedownButtonCounter.getEnterProgress()) * pagedownButtonEnterProgress + AndroidUtilities.dp(72) * mentionsButtonEnterProgress) * reactionsMentionButtonEnterProgress); } if (suggestEmojiPanel != null) { suggestEmojiPanel.setTranslationY(baseTranslationY); } } private void updateReactionsMentionButton(boolean animated) { if (reactionsMentiondownButtonCounter == null || getParentActivity() == null) { return; } boolean visible = reactionsMentionCount > 0 && chatMode == 0; reactionsMentiondownButtonCounter.setCount(reactionsMentionCount, animated); if (visible && reactionsMentiondownButton.getTag() == null) { reactionsMentiondownButton.setTag(1); if (reactionsMentionButtonAnimation != null) { reactionsMentionButtonAnimation.removeAllListeners(); reactionsMentionButtonAnimation.cancel(); reactionsMentionButtonAnimation = null; } if (animated) { reactionsMentiondownButton.setVisibility(View.VISIBLE); reactionsMentionButtonAnimation = ValueAnimator.ofFloat(reactionsMentionButtonEnterProgress, 1f); reactionsMentionButtonAnimation.addUpdateListener(valueAnimator -> { reactionsMentionButtonEnterProgress = (float) valueAnimator.getAnimatedValue(); contentView.invalidate(); }); reactionsMentionButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { reactionsMentionButtonEnterProgress = 1f; contentView.invalidate(); } }); reactionsMentionButtonAnimation.setDuration(200); reactionsMentionButtonAnimation.start(); } else { reactionsMentiondownButton.setVisibility(View.VISIBLE); reactionsMentionButtonEnterProgress = 1f; contentView.invalidate(); } } else if (!visible && reactionsMentiondownButton.getTag() != null) { reactionsMentiondownButton.setTag(null); if (reactionsMentionButtonAnimation != null) { reactionsMentionButtonAnimation.removeAllListeners(); reactionsMentionButtonAnimation.cancel(); reactionsMentionButtonAnimation = null; } if (animated) { reactionsMentiondownButton.setVisibility(View.VISIBLE); reactionsMentionButtonAnimation = ValueAnimator.ofFloat(reactionsMentionButtonEnterProgress, 0f); reactionsMentionButtonAnimation.addUpdateListener(valueAnimator -> { reactionsMentionButtonEnterProgress = (float) valueAnimator.getAnimatedValue(); contentView.invalidate(); }); reactionsMentionButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { reactionsMentiondownButton.setVisibility(View.INVISIBLE); reactionsMentionButtonEnterProgress = 0f; contentView.invalidate(); } }); reactionsMentionButtonAnimation.setDuration(200); reactionsMentionButtonAnimation.start(); } else { reactionsMentiondownButton.setVisibility(View.INVISIBLE); reactionsMentionButtonEnterProgress = 0f; contentView.invalidate(); } } } private void openForwardingPreview() { boolean keyboardVisible = chatActivityEnterView.isKeyboardVisible(); forwardingPreviewView = new ForwardingPreviewView(contentView.getContext(), forwardingMessages, currentUser, currentChat, currentAccount, themeDelegate) { @Override protected void onDismiss(boolean canShowKeyboard) { checkShowBlur(true); if (forwardingMessages != null) { ArrayList selectedMessage = new ArrayList<>(); forwardingMessages.getSelectedMessages(selectedMessage); showFieldPanelForForward(true, selectedMessage); } if (keyboardVisible && canShowKeyboard) { AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null) { chatActivityEnterView.openKeyboard(); } }, 50); } AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } @Override protected void selectAnotherChat() { super.selectAnotherChat(); dismiss(false); if (forwardingMessages != null) { int hasPoll = 0; boolean hasInvoice = false; for (int a = 0, N = forwardingMessages.messages.size(); a < N; a++) { MessageObject messageObject = forwardingMessages.messages.get(a); if (messageObject.isPoll()) { if (hasPoll != 2) { hasPoll = messageObject.isPublicPoll() ? 2 : 1; } } else if (messageObject.isInvoice()) { hasInvoice = true; } selectedMessagesIds[0].put(messageObject.getId(), messageObject); } Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 3); args.putInt("hasPoll", hasPoll); args.putBoolean("hasInvoice", hasInvoice); args.putInt("messagesCount", forwardingMessages.messages.size()); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } } @Override protected void didSendPressed() { super.didSendPressed(); dismiss(true); chatActivityEnterView.getSendButton().callOnClick(); } }; TLRPC.Peer defPeer = chatInfo != null ? chatInfo.default_send_as : null; if (defPeer == null && sendAsPeersObj != null && !sendAsPeersObj.peers.isEmpty()) { defPeer = sendAsPeersObj.peers.get(0); } forwardingPreviewView.setSendAsPeer(defPeer); checkShowBlur(true); contentView.addView(forwardingPreviewView); if (keyboardVisible) { chatActivityEnterView.showEmojiView(); openKeyboardOnAttachMenuClose = true; } AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); fragmentView.requestLayout(); } private void animateToNextChat() { if (pullingDownDrawable == null) { return; } // if (getParentLayout().fragmentsStack.size() > 1) { // BaseFragment previousFragment = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2); // if (previousFragment instanceof ChatActivity) { // getParentLayout().fragmentsStack.remove(getParentLayout().fragmentsStack.size() - 2); // } // } addToPulledDialogsMyself(); addToPulledDialogs(pullingDownDrawable.nextChat, pullingDownDrawable.nextDialogId, pullingDownDrawable.dialogFolderId, pullingDownDrawable.dialogFilterId); Bundle bundle = new Bundle(); bundle.putLong("chat_id", pullingDownDrawable.getChatId()); bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); bundle.putBoolean("pulled", true); SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); sharedPreferences.edit().remove("diditem" + pullingDownDrawable.nextDialogId).apply(); ChatActivity chatActivity = new ChatActivity(bundle); chatActivity.setPullingDownTransition(true); replacingChatActivity = true; presentFragment(chatActivity, true); } private void addToPulledDialogsMyself() { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().fragmentsStack.indexOf(this); BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, dialog_id, dialogFilterId, dialogFolderId); } private void addToPulledDialogs(TLRPC.Chat chat, long dialogId, int folderId, int filterId) { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().fragmentsStack.indexOf(this); BackButtonMenu.addToPulledDialogs(this, stackIndex, chat, null, dialogId, folderId, filterId); } private void setPullingDownTransition(boolean fromPullingDownTransition) { this.fromPullingDownTransition = fromPullingDownTransition; } private void updateBulletinLayout() { Bulletin bulletin = Bulletin.getVisibleBulletin(); if (bulletin != null && bulletinDelegate != null) { bulletin.updatePosition(); } } private void searchUserMessages(TLRPC.User user, TLRPC.Chat chat) { searchingUserMessages = user; searchingChatMessages = chat; if (searchItem == null || mentionContainer == null || searchingUserMessages == null && searchingChatMessages == null) { return; } String name; if (searchingUserMessages != null) { name = searchingUserMessages.first_name; if (TextUtils.isEmpty(name)) { name = searchingUserMessages.last_name; } } else { name = searchingChatMessages.title; } if (name == null) { return; } if (name.length() > 10) { name = name.substring(0, 10); } searchingForUser = false; String from = LocaleController.getString("SearchFrom", R.string.SearchFrom); Spannable spannable = new SpannableString(from + " " + name); spannable.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_actionBarDefaultSubtitle)), from.length() + 1, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); searchItem.setSearchFieldCaption(spannable); mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchItem.setSearchFieldHint(null); searchItem.clearSearchText(); getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); } private Animator infoTopViewAnimator; private void updateInfoTopView(boolean animated) { if (contentView == null) { return; } SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); distanceToPeer = preferences.getInt("dialog_bar_distance" + dialog_id, -1); CharSequence text = null; View.OnClickListener onClickListener = null; if (distanceToPeer >= 0 && currentUser != null) { text = LocaleController.formatString("ChatDistanceToPeer", R.string.ChatDistanceToPeer, currentUser.first_name, LocaleController.formatDistance(distanceToPeer, 0)); onClickListener = v -> presentFragment(new PeopleNearbyActivity()); } else if (currentChat != null && chatInviterId != 0) { boolean show = preferences.getInt("dialog_bar_vis3" + dialog_id, 0) == 2; boolean showReport = preferences.getBoolean("dialog_bar_report" + dialog_id, false); boolean showBlock = preferences.getBoolean("dialog_bar_block" + dialog_id, false); if (show && (showReport || showBlock)) { TLRPC.User user = getMessagesController().getUser(chatInviterId); if (user != null) { text = ChatObject.isChannel(currentChat) && !currentChat.megagroup ? LocaleController.getString("ActionUserInvitedToChannel", R.string.ActionUserInvitedToChannel) : LocaleController.getString("ActionUserInvitedToGroup", R.string.ActionUserInvitedToGroup); text = MessageObject.replaceWithLink(text, "un1", user); onClickListener = (v) -> { Bundle args = new Bundle(); args.putLong("user_id", chatInviterId); presentFragment(new ProfileActivity(args)); }; } } else { hideInfoView(); } } if (text != null) { if (infoTopViewAnimator != null) { infoTopViewAnimator.cancel(); } if (infoTopView == null) { infoTopView = new ChatActionCell(contentView.getContext(), false, themeDelegate); infoTopView.setCustomText(text); infoTopView.setInvalidateColors(true); infoTopView.setOnClickListener(onClickListener); contentView.addView(infoTopView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 0)); } if (animated) { if (infoTopView.getTag() == null) { ValueAnimator a = ValueAnimator.ofFloat(0, 1f); infoTopView.setTag(1); infoTopView.setAlpha(0f); View distanceTopViewFinal = infoTopView; a.addUpdateListener(animation -> { float alpha = (float) animation.getAnimatedValue(); topViewOffset = (alpha) * AndroidUtilities.dp(30); invalidateChatListViewTopPadding(); distanceTopViewFinal.setAlpha(alpha); }); a.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { topViewOffset = AndroidUtilities.dp(30); invalidateChatListViewTopPadding(); } }); a.setDuration(150); infoTopViewAnimator = a; a.start(); } } else { infoTopView.setTag(1); topViewOffset = AndroidUtilities.dp(30); invalidateChatListViewTopPadding(); } } } private void openAnotherForward() { if (forwardingMessages == null || forwardingMessages.messages == null) { return; } boolean fewSenders = false; long lastPeerId = 0; long dialogId = 0; for (int a = 0, N = forwardingMessages.messages.size(); a < N; a++) { MessageObject message = forwardingMessages.messages.get(a); if (lastPeerId == 0) { dialogId = message.getDialogId(); lastPeerId = message.getFromChatId(); } else if (lastPeerId != message.getFromChatId()) { fewSenders = true; break; } } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setButtonsVertical(true); String message; if (dialogId > 0) { TLRPC.User user = getMessagesController().getUser(dialogId); if (user == null) { return; } message = LocaleController.formatString("CancelForwardPrivate", R.string.CancelForwardPrivate, LocaleController.formatPluralString("MessagesBold", forwardingMessages.messages.size()), ContactsController.formatName(user.first_name, user.last_name)); } else { TLRPC.Chat chat = getMessagesController().getChat(-dialogId); if (chat == null) { return; } message = LocaleController.formatString("CancelForwardChat", R.string.CancelForwardChat, LocaleController.formatPluralString("MessagesBold", forwardingMessages.messages.size()), chat == null ? "" : chat.title); } builder.setMessage(AndroidUtilities.replaceTags(message)); builder.setTitle(LocaleController.formatPluralString("messages", forwardingMessages.messages.size())); builder.setPositiveButton(LocaleController.getString("CancelForwarding", R.string.CancelForwarding), (dialogInterface, i) -> { if (forwardingMessages != null) { forwardingMessages = null; } showFieldPanel(false, null, null, null, foundWebPage, true, 0, true, true); }); builder.setNegativeButton(LocaleController.getString("ShowForwardingOptions", R.string.ShowForwardingOptions), (dialogInterface, i) -> { openForwardingPreview(); }); AlertDialog dialog = builder.create(); showDialog(dialog); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(getThemedColor(Theme.key_dialogTextRed2)); } } private void openPinnedMessagesList(boolean preview) { if (getParentActivity() == null || parentLayout == null || parentLayout.getLastFragment() != this || pinnedMessageIds.isEmpty()) { return; } Bundle bundle = new Bundle(); if (currentChat != null) { bundle.putLong("chat_id", currentChat.id); } else { bundle.putLong("user_id", currentUser.id); } bundle.putInt("chatMode", MODE_PINNED); ChatActivity fragment = new ChatActivity(bundle); fragment.pinnedMessageIds = new ArrayList<>(pinnedMessageIds); fragment.pinnedMessageObjects = new HashMap<>(pinnedMessageObjects); for (int a = 0, N = pinnedMessageIds.size(); a < N; a++) { Integer id = pinnedMessageIds.get(a); MessageObject object = pinnedMessageObjects.get(id); MessageObject object2 = messagesDict[0].get(id); if (object == null) { object = object2; } else if (object2 != null) { object.mediaExists = object2.mediaExists; object.attachPathExists = object2.attachPathExists; } if (object != null) { fragment.pinnedMessageObjects.put(id, object); } } fragment.loadedPinnedMessagesCount = loadedPinnedMessagesCount; fragment.totalPinnedMessagesCount = totalPinnedMessagesCount; fragment.pinnedEndReached = pinnedEndReached; fragment.userInfo = userInfo; fragment.chatInfo = chatInfo; fragment.chatActivityDelegate = new ChatActivityDelegate() { @Override public void openReplyMessage(int mid) { scrollToMessageId(mid, 0, true, 0, true, 0); } @Override public void openSearch(String text) { openSearchWithText(text); } @Override public void onUnpin(boolean all, boolean hide) { if (all) { ArrayList ids = new ArrayList<>(pinnedMessageIds); ArrayList objects = new ArrayList<>(pinnedMessageObjects.values()); if (hide) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putInt("pin_" + dialog_id, pinnedMessageIds.get(0)).commit(); updatePinnedMessageView(true); } else { getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, false, null, null, 0, 0, true); } if (pinBulletin != null) { pinBulletin.hide(); } showPinBulletin = true; int tag = ++pinBullerinTag; int oldTotalPinnedCount = getPinnedMessagesCount(); pinBulletin = BulletinFactory.createUnpinAllMessagesBulletin(ChatActivity.this, oldTotalPinnedCount, hide, () -> { if (hide) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().remove("pin_" + dialog_id).commit(); updatePinnedMessageView(true); } else { getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, true, objects, null, 0, oldTotalPinnedCount, pinnedEndReached); } if (tag == pinBullerinTag) { pinBulletin = null; } }, () -> { if (!hide) { getMessagesController().unpinAllMessages(currentChat, currentUser); } if (tag == pinBullerinTag) { pinBulletin = null; } }, themeDelegate); } else { MessageObject messageObject = pinnedMessageObjects.get(currentPinnedMessageId); if (messageObject == null) { messageObject = messagesDict[0].get(currentPinnedMessageId); } unpinMessage(messageObject); } } }; if (preview) { presentFragmentAsPreview(fragment); checkShowBlur(true); } else { presentFragment(fragment, false); } } private void checkShowBlur(boolean animated) { boolean show = (parentLayout != null && parentLayout.isInPreviewMode() && !inPreviewMode) || (forwardingPreviewView != null && forwardingPreviewView.isShowing()); if (show && (blurredView == null || blurredView.getTag() == null)) { if (blurredView == null) { blurredView = new BluredView(fragmentView.getContext(), fragmentView, themeDelegate) { @Override public void setAlpha(float alpha) { super.setAlpha(alpha); fragmentView.invalidate(); } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); fragmentView.invalidate(); } }; contentView.addView(blurredView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } else { int idx = contentView.indexOfChild(blurredView); if (idx != contentView.getChildCount() - 1) { contentView.removeView(blurredView); contentView.addView(blurredView); } blurredView.update(); blurredView.setVisibility(View.VISIBLE); } blurredView.setAlpha(0.0f); blurredView.animate().setListener(null).cancel(); blurredView.animate().alpha(1f).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); chatListView.invalidate(); fragmentView.invalidate(); } }).start(); blurredView.setTag(1); } else if (!show && blurredView != null && blurredView.getTag() != null) { blurredView.animate().setListener(null).cancel(); blurredView.animate().setListener(new HideViewAfterAnimation(blurredView)).alpha(0).start(); blurredView.setTag(null); chatListView.invalidate(); fragmentView.invalidate(); } } @Override protected int getPreviewHeight() { if (chatMode == MODE_PINNED && messages.size() == 2) { return getHeightForMessage(messages.get(0)) + AndroidUtilities.dp(80) + ActionBar.getCurrentActionBarHeight(); } return super.getPreviewHeight(); } boolean animateTo; private void showProgressView(boolean show) { if (progressView == null) { return; } if (fragmentOpened) { if (show == animateTo) { return; } animateTo = show; if (show) { if (progressView.getVisibility() != View.VISIBLE) { progressView.setVisibility(View.VISIBLE); progressView.setAlpha(0f); progressView.setScaleX(0.3f); progressView.setScaleY(0.3f); } progressView.animate().setListener(null).cancel(); progressView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).start(); } else { progressView.animate().setListener(null).cancel(); progressView.animate().alpha(0).scaleX(0.3f).scaleY(0.3f).setDuration(150).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { progressView.setVisibility(View.INVISIBLE); } }).start(); } } else { animateTo = show; progressView.setVisibility(show ? View.VISIBLE : View.INVISIBLE); } } private void hideInfoView() { if (distanceToPeer >= 0) { distanceToPeer = -1; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putInt("dialog_bar_distance" + dialog_id, -2).commit(); } if (infoTopViewAnimator != null) { infoTopViewAnimator.cancel(); } if (infoTopView != null && infoTopView.getTag() != null) { infoTopView.setTag(null); View topViewFinal = infoTopView; ValueAnimator a = ValueAnimator.ofFloat(1f, 0); a.addUpdateListener(animation -> { float alpha = (float) animation.getAnimatedValue(); topViewOffset = (alpha) * AndroidUtilities.dp(30); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); topViewFinal.setAlpha(alpha); }); a.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { topViewOffset = 0; if (animation == infoTopViewAnimator) { ViewGroup parent = (ViewGroup) topViewFinal.getParent(); if (parent != null) { parent.removeView(topViewFinal); } infoTopView = null; infoTopViewAnimator = null; } } }); a.setDuration(150); infoTopViewAnimator = a; a.start(); } } private void updateChatListViewTopPadding() { if (!invalidateChatListViewTopPadding || chatListView == null || (fixedKeyboardHeight > 0 && searchExpandProgress == 0)) { return; } float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); float pinnedViewH = 0; if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } float pendingViewH = 0; View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null && pendingRequestsView.getVisibility() == View.VISIBLE) { pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset()); } float oldPadding = chatListViewPaddingTop; chatListViewPaddingTopOnlyTopViews = topPanelViewH + pinnedViewH; chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH; chatListViewPaddingTop += blurredViewTopOffset; chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; float searchExpandOffset = 0; if (searchExpandProgress != 0 && chatActivityEnterView.getVisibility() == View.VISIBLE) { chatListViewPaddingTop -= (searchExpandOffset = searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); } if (bottomPanelTranslationY == 0 && !chatActivityEnterView.panelAnimationInProgress() && (contentView.getLayoutParams().height < 0 || (contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing()))) { chatListViewPaddingTop += contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : contentView.getKeyboardHeight(); } if (!inPreviewMode && chatActivityEnterView != null) { if (chatActivityEnterView.getAnimatedTop() != 0) { chatListViewPaddingTop += chatActivityEnterView.getHeightWithTopView() - AndroidUtilities.dp(51) - chatActivityEnterView.getAnimatedTop(); } else if (!chatActivityEnterView.panelAnimationInProgress()) { chatListViewPaddingTop += chatActivityEnterView.getHeightWithTopView() - AndroidUtilities.dp(51); if (chatActivityEnterView.currentTopViewAnimation == null) { chatListViewPaddingTop -= chatListView.getTranslationY(); } } } if (infoTopView != null) { infoTopView.setTranslationY(chatListViewPaddingTop - AndroidUtilities.dp(30) + topViewOffset); chatListViewPaddingTop += topViewOffset; chatListViewPaddingVisibleOffset += topViewOffset; } if (floatingDateView != null) { floatingDateView.setTranslationY(chatListView.getTranslationY() - searchExpandOffset + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4)); } int p = chatListView.getMeasuredHeight() * 2 / 3; if (chatListView != null && chatLayoutManager != null && chatAdapter != null) { if (chatListView.getPaddingTop() != p) { int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition(); int lastVisPos = chatLayoutManager.findLastVisibleItemPosition(); int top = 0; MessageObject scrollToMessageObject = null; if (firstVisPos != RecyclerView.NO_POSITION) { for (int i = firstVisPos; i <= lastVisPos; i++) { View v = chatLayoutManager.findViewByPosition(i); if (v instanceof ChatMessageCell) { scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); break; } else if (v instanceof ChatActionCell) { scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); break; } } } chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset); if (firstVisPos != RecyclerView.NO_POSITION && scrollToMessageObject != null) { chatAdapter.updateRowsSafe(); int index = messages.indexOf(scrollToMessageObject); if (index >= 0) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + index, top); } } invalidateMessagesVisiblePart(); } chatListView.setTopGlowOffset((int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4))); if (oldPadding != chatListViewPaddingTop) { int n = chatListView.getChildCount(); for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); int adapterPosition = chatListView.getChildAdapterPosition(child); if (adapterPosition == chatAdapter.getItemCount() - 1) { float padding = chatListViewPaddingTop; if (isThreadChat() && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } if (child.getTop() > padding) { chatListView.scrollBy(0, (int) (child.getTop() - padding)); } break; } } } if (!isThreadChat() && !wasManualScroll && unreadMessageObject != null && chatListView != null) { chatListView.scrollBy(0, (int) (oldPadding - chatListViewPaddingTop)); } } invalidateChatListViewTopPadding = false; } private void invalidateChatListViewTopPadding() { if (!invalidateChatListViewTopPadding) { invalidateChatListViewTopPadding = true; if (contentView != null) { contentView.invalidate(); } if (chatListView != null) { chatListView.invalidate(); } } float translation = contentPanTranslation + contentPaddingTop + Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); if (pinnedMessageView != null) { translation += pinnedMessageEnterOffset; pinnedMessageView.setTranslationY(translation); translation += AndroidUtilities.dp(48); } View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null) { translation += pendingRequestsDelegate.getViewEnterOffset(); pendingRequestsView.setTranslationY(translation); } if (fragmentContextView != null) { float from = 0; if (fragmentLocationContextView != null && fragmentLocationContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(36); } fragmentContextView.setTranslationY(contentPanTranslation + from + fragmentContextView.getTopPadding()); } if (fragmentLocationContextView != null) { float from = 0; if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(fragmentContextView.getStyleHeight()) + fragmentContextView.getTopPadding(); } fragmentLocationContextView.setTranslationY(contentPanTranslation + from + fragmentLocationContextView.getTopPadding()); } if (topChatPanelView != null) { topChatPanelView.setTranslationY(contentPanTranslation + contentPaddingTop + topChatPanelViewOffset); } if (alertView != null && alertView.getVisibility() == View.VISIBLE) { alertView.setTranslationY(contentPanTranslation + contentPaddingTop - AndroidUtilities.dp(50) * (1f - alertViewEnterProgress)); } if (bottomOverlayChat != null) { bottomOverlayChat.setTranslationY(bottomPanelTranslationYReverse); } if (bottomMessagesActionContainer != null) { bottomMessagesActionContainer.setTranslationY(bottomPanelTranslationYReverse); } if (undoView != null) { undoView.setAdditionalTranslationY(chatActivityEnterView.getHeightWithTopView() - chatActivityEnterView.getAnimatedTop()); } } private TextureView createTextureView(boolean add) { if (parentLayout == null) { return null; } AndroidUtilities.cancelRunOnUIThread(destroyTextureViewRunnable); if (videoPlayerContainer == null) { if (Build.VERSION.SDK_INT >= 21) { videoPlayerContainer = new FrameLayout(getParentActivity()) { @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); contentView.invalidate(); } }; videoPlayerContainer.setOutlineProvider(new ViewOutlineProvider() { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void getOutline(View view, Outline outline) { ImageReceiver imageReceiver = (ImageReceiver) view.getTag(R.id.parent_tag); if (imageReceiver != null) { int[] rad = imageReceiver.getRoundRadius(); int maxRad = 0; for (int a = 0; a < 4; a++) { maxRad = Math.max(maxRad, rad[a]); } outline.setRoundRect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight(), maxRad); } else { outline.setOval(0, 0, AndroidUtilities.roundPlayingMessageSize, AndroidUtilities.roundPlayingMessageSize); } } }); videoPlayerContainer.setClipToOutline(true); } else { videoPlayerContainer = new FrameLayout(getParentActivity()) { RectF rect = new RectF(); @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); aspectPath.reset(); ImageReceiver imageReceiver = (ImageReceiver) getTag(R.id.parent_tag); if (imageReceiver != null) { int[] rad = imageReceiver.getRoundRadius(); int maxRad = 0; for (int a = 0; a < 4; a++) { maxRad = Math.max(maxRad, rad[a]); } rect.set(0, 0, w, h); aspectPath.addRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Path.Direction.CW); } else { aspectPath.addCircle(w / 2, h / 2, w / 2, Path.Direction.CW); } aspectPath.toggleInverseFillType(); } @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); contentView.invalidate(); } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); if (visibility == VISIBLE) { setLayerType(View.LAYER_TYPE_HARDWARE, null); } } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (getTag() == null) { canvas.drawPath(aspectPath, aspectPaint); } } }; aspectPath = new Path(); aspectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); aspectPaint.setColor(0xff000000); aspectPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } videoPlayerContainer.setWillNotDraw(false); aspectRatioFrameLayout = new AspectRatioFrameLayout(getParentActivity()); aspectRatioFrameLayout.setBackgroundColor(0); if (add) { videoPlayerContainer.addView(aspectRatioFrameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); } videoTextureView = new TextureView(getParentActivity()); videoTextureView.setOpaque(false); aspectRatioFrameLayout.addView(videoTextureView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } ViewGroup parent = (ViewGroup) videoPlayerContainer.getParent(); if (parent != null && parent != contentView) { parent.removeView(videoPlayerContainer); parent = null; } if (parent == null) { contentView.addView(videoPlayerContainer, 1, new FrameLayout.LayoutParams(AndroidUtilities.roundPlayingMessageSize, AndroidUtilities.roundPlayingMessageSize)); } videoPlayerContainer.setTag(null); aspectRatioFrameLayout.setDrawingReady(false); return videoTextureView; } private void destroyTextureView() { if (videoPlayerContainer == null || videoPlayerContainer.getParent() == null) { return; } chatListView.invalidateViews(); aspectRatioFrameLayout.setDrawingReady(false); videoPlayerContainer.setTag(null); if (Build.VERSION.SDK_INT < 21) { videoPlayerContainer.setLayerType(View.LAYER_TYPE_NONE, null); } contentView.removeView(videoPlayerContainer); } private boolean hasSelectedNoforwardsMessage() { try { for (int i = 0; i < selectedMessagesIds.length; ++i) { for (int j = 0; j < selectedMessagesIds[i].size(); ++j) { MessageObject msg = selectedMessagesIds[i].valueAt(j); if (msg != null && msg.messageOwner != null && msg.messageOwner.noforwards) { return true; } } } } catch (Exception ignore) {} return false; } private void openForward(boolean fromActionBar) { if (getMessagesController().isChatNoForwards(currentChat) || hasSelectedNoforwardsMessage()) { // We should update text if user changed locale without re-opening chat activity String str; if (getMessagesController().isChatNoForwards(currentChat)) { if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { str = LocaleController.getString("ForwardsRestrictedInfoChannel", R.string.ForwardsRestrictedInfoChannel); } else { str = LocaleController.getString("ForwardsRestrictedInfoGroup", R.string.ForwardsRestrictedInfoGroup); } } else { str = LocaleController.getString("ForwardsRestrictedInfoBot", R.string.ForwardsRestrictedInfoBot); } if (fromActionBar) { if (fwdRestrictedTopHint == null) { SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } fwdRestrictedTopHint = new HintView(getParentActivity(), 7, true); frameLayout.addView(fwdRestrictedTopHint, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 12, 0, 12, 0)); fwdRestrictedTopHint.setAlpha(0.0f); fwdRestrictedTopHint.setVisibility(View.INVISIBLE); } fwdRestrictedTopHint.setText(str); fwdRestrictedTopHint.showForView(actionBar.getActionMode().getItem(forward), true); } else { if (fwdRestrictedBottomHint == null) { SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } fwdRestrictedBottomHint = new HintView(getParentActivity(), 9); frameLayout.addView(fwdRestrictedBottomHint, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 12, 0, 12, 0)); fwdRestrictedBottomHint.setAlpha(0.0f); fwdRestrictedBottomHint.setVisibility(View.INVISIBLE); } fwdRestrictedBottomHint.setText(str); fwdRestrictedBottomHint.showForView(forwardButton, true); } return; } int hasPoll = 0; boolean hasInvoice = false; for (int a = 0; a < 2; a++) { for (int b = 0; b < selectedMessagesIds[a].size(); b++) { MessageObject messageObject = selectedMessagesIds[a].valueAt(b); if (messageObject.isPoll()) { hasPoll = messageObject.isPublicPoll() ? 2 : 1; if (hasPoll == 2) { break; } } else if (messageObject.isInvoice()) { hasInvoice = true; } } if (hasPoll == 2) { break; } } Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 3); args.putInt("messagesCount", canForwardMessagesCount); args.putInt("hasPoll", hasPoll); args.putBoolean("hasInvoice", hasInvoice); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } private void showBottomOverlayProgress(boolean show, boolean animated) { if (show && bottomOverlayProgress.getTag() != null || !show && bottomOverlayProgress.getTag() == null) { return; } if (bottomOverlayAnimation != null) { bottomOverlayAnimation.cancel(); bottomOverlayAnimation = null; } bottomOverlayProgress.setTag(show ? 1 : null); if (animated) { bottomOverlayAnimation = new AnimatorSet(); if (show) { bottomOverlayProgress.setVisibility(View.VISIBLE); bottomOverlayAnimation.playTogether( ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_X, 0.1f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_Y, 0.1f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.ALPHA, 0.0f), ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_X, 1.0f), ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_Y, 1.0f), ObjectAnimator.ofFloat(bottomOverlayProgress, View.ALPHA, 1.0f)); bottomOverlayAnimation.setStartDelay(200); } else { bottomOverlayChatText.setVisibility(View.VISIBLE); bottomOverlayAnimation.playTogether( ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_X, 0.1f), ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_Y, 0.1f), ObjectAnimator.ofFloat(bottomOverlayProgress, View.ALPHA, 0.0f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_X, 1.0f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_Y, 1.0f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.ALPHA, 1.0f)); } bottomOverlayAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (bottomOverlayAnimation != null && bottomOverlayAnimation.equals(animation)) { if (!show) { bottomOverlayProgress.setVisibility(View.INVISIBLE); } else { bottomOverlayChatText.setVisibility(View.INVISIBLE); } } } @Override public void onAnimationCancel(Animator animation) { if (bottomOverlayAnimation != null && bottomOverlayAnimation.equals(animation)) { bottomOverlayAnimation = null; } } }); bottomOverlayAnimation.setDuration(150); bottomOverlayAnimation.start(); } else { bottomOverlayProgress.setVisibility(show ? View.VISIBLE : View.INVISIBLE); bottomOverlayProgress.setScaleX(show ? 1.0f : 0.1f); bottomOverlayProgress.setScaleY(show ? 1.0f : 0.1f); bottomOverlayProgress.setAlpha(show ? 1.0f : 1.0f); bottomOverlayChatText.setVisibility(show ? View.INVISIBLE : View.VISIBLE); bottomOverlayChatText.setScaleX(show ? 0.1f : 1.0f); bottomOverlayChatText.setScaleY(show ? 0.1f : 1.0f); bottomOverlayChatText.setAlpha(show ? 0.0f : 1.0f); } } private void sendBotInlineResult(TLRPC.BotInlineResult result, boolean notify, int scheduleDate) { if (mentionContainer == null) { return; } long uid = mentionContainer.getAdapter().getContextBotId(); HashMap params = new HashMap<>(); params.put("id", result.id); params.put("query_id", "" + result.query_id); params.put("bot", "" + uid); params.put("bot_name", mentionContainer.getAdapter().getContextBotName()); SendMessagesHelper.prepareSendingBotContextResult(this, getAccountInstance(), result, params, dialog_id, replyingMessageObject, getThreadMessage(), notify, scheduleDate); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); getMediaDataController().increaseInlineRaiting(uid); } private void checkBotCommands() { URLSpanBotCommand.enabled = false; if (currentUser != null && currentUser.bot) { URLSpanBotCommand.enabled = !UserObject.isReplyUser(currentUser); } else if (chatInfo instanceof TLRPC.TL_chatFull) { for (int a = 0; a < chatInfo.participants.participants.size(); a++) { TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); TLRPC.User user = getMessagesController().getUser(participant.user_id); if (user != null && user.bot) { URLSpanBotCommand.enabled = true; break; } } } else if (chatInfo instanceof TLRPC.TL_channelFull) { URLSpanBotCommand.enabled = !chatInfo.bot_info.isEmpty() && currentChat != null && currentChat.megagroup; } } private MessageObject.GroupedMessages getValidGroupedMessage(MessageObject message) { MessageObject.GroupedMessages groupedMessages = null; if (message.getGroupId() != 0) { groupedMessages = groupedMessagesMap.get(message.getGroupId()); if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { groupedMessages = null; } } return groupedMessages; } public void jumpToDate(int date) { if (messages.isEmpty()) { return; } MessageObject firstMessage = messages.get(0); MessageObject lastMessage = messages.get(messages.size() - 1); if (firstMessage.messageOwner.date >= date && lastMessage.messageOwner.date <= date || lastMessage.messageOwner.date >= date && endReached[0]) { for (int a = messages.size() - 1; a >= 0; a--) { MessageObject message = messages.get(a); if (message.messageOwner.date >= date && message.getId() != 0) { scrollToMessageId(message.getId(), 0, false, message.getDialogId() == mergeDialogId ? 1 : 0, true, 0); break; } } } else if (!DialogObject.isEncryptedDialog(dialog_id)) { int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { TLRPC.Message message = messages.get(i - chatAdapter.messagesStartRow).messageOwner; if (message != null) { boolean scrollDown = message.date < date; if (isSecretChat()) { scrollDown = !scrollDown; } scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; break; } } } chatScrollHelper.setScrollDirection(scrollDirection); if (progressDialog != null) { progressDialog.dismiss(); } updatePinnedListButton(false); progressDialog = new AlertDialog(getParentActivity(), 3, themeDelegate); progressDialog.setOnCancelListener(postponedScrollCancelListener); progressDialog.showDelayed(1000); postponedScrollToLastMessageQueryIndex = lastLoadIndex; waitingForLoad.add(lastLoadIndex); postponedScrollMessageId = 0; postponedScrollIsCanceled = false; getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, date, true, 0, classGuid, 4, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); floatingDateView.setAlpha(0.0f); floatingDateView.setTag(null); } } public void processInlineBotContextPM(TLRPC.TL_inlineBotSwitchPM object) { if (object == null || mentionContainer == null) { return; } TLRPC.User user = mentionContainer.getAdapter().getContextBotUser(); if (user == null) { return; } chatActivityEnterView.setFieldText(""); if (dialog_id == user.id) { inlineReturn = dialog_id; getMessagesController().sendBotStart(currentUser, object.start_param); } else { Bundle args = new Bundle(); args.putLong("user_id", user.id); args.putString("inline_query", object.start_param); args.putLong("inline_return", dialog_id); if (!getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { return; } presentFragment(new ChatActivity(args)); } } private void createChatAttachView() { if (getParentActivity() == null) { return; } if (chatAttachAlert == null) { chatAttachAlert = new ChatAttachAlert(getParentActivity(), this, false, false, themeDelegate) { @Override public void dismissInternal() { if (chatAttachAlert != null && chatAttachAlert.isShowing()) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } super.dismissInternal(); onEditTextDialogClose(false, true); } @Override public void onDismissAnimationStart() { chatAttachAlert.setFocusable(false); chatActivityEnterView.getEditField().requestFocus(); if (chatAttachAlert != null && chatAttachAlert.isShowing()) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } onEditTextDialogClose(false, false); } }; chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() { @Override public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate, boolean forceDocument) { if (getParentActivity() == null || chatAttachAlert == null) { return; } editingMessageObject = chatAttachAlert.getEditingMessageObject(); if (button == 8 || button == 7 || button == 4 && !chatAttachAlert.getPhotoLayout().getSelectedPhotos().isEmpty()) { if (button != 8) { chatAttachAlert.dismiss(true); } HashMap selectedPhotos = chatAttachAlert.getPhotoLayout().getSelectedPhotos(); ArrayList selectedPhotosOrder = chatAttachAlert.getPhotoLayout().getSelectedPhotosOrder(); if (!selectedPhotos.isEmpty()) { for (int i = 0; i < Math.ceil(selectedPhotos.size() / 10f); ++i) { int count = Math.min(10, selectedPhotos.size() - (i * 10)); ArrayList photos = new ArrayList<>(); for (int a = 0; a < count; a++) { if (i * 10 + a >= selectedPhotosOrder.size()) { continue; } MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) selectedPhotos.get(selectedPhotosOrder.get(i * 10 + a)); SendMessagesHelper.SendingMediaInfo info = new SendMessagesHelper.SendingMediaInfo(); if (!photoEntry.isVideo && photoEntry.imagePath != null) { info.path = photoEntry.imagePath; } else if (photoEntry.path != null) { info.path = photoEntry.path; } info.thumbPath = photoEntry.thumbPath; info.isVideo = photoEntry.isVideo; info.caption = photoEntry.caption != null ? photoEntry.caption.toString() : null; info.entities = photoEntry.entities; info.masks = photoEntry.stickers; info.ttl = photoEntry.ttl; info.videoEditedInfo = photoEntry.editedInfo; info.canDeleteAfter = photoEntry.canDeleteAfter; photos.add(info); photoEntry.reset(); } if (i == 0) { fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); } SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate); } afterMessageSend(); chatActivityEnterView.setFieldText(""); } if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { scheduledMessagesCount = 0; } scheduledMessagesCount += selectedPhotos.size(); updateScheduledInterface(true); } return; } else if (chatAttachAlert != null) { chatAttachAlert.dismissWithButtonClick(button); } processSelectedAttach(button); } @Override public View getRevealView() { return chatActivityEnterView.getAttachButton(); } @Override public void didSelectBot(TLRPC.User user) { if (chatActivityEnterView == null || user == null || TextUtils.isEmpty(user.username)) { return; } chatActivityEnterView.setFieldText("@" + user.username + " "); chatActivityEnterView.openKeyboard(); } @Override public void onCameraOpened() { chatActivityEnterView.closeKeyboard(); } @Override public boolean needEnterComment() { return needEnterText(); } @Override public void doOnIdle(Runnable runnable) { ChatActivity.this.doOnIdle(runnable); } }); } } public boolean needEnterText() { boolean keyboardVisible = chatActivityEnterView.isKeyboardVisible(); if (keyboardVisible) { chatActivityEnterView.showEmojiView(); openKeyboardOnAttachMenuClose = true; } AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); fragmentView.requestLayout(); return keyboardVisible; } public void onEditTextDialogClose(boolean resetAdjust, boolean reset) { if (openKeyboardOnAttachMenuClose) { AndroidUtilities.runOnUIThread(() -> chatActivityEnterView.openKeyboard(), 50); if (reset) { openKeyboardOnAttachMenuClose = false; } } if (resetAdjust) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } public void doOnIdle(Runnable runnable) { NotificationCenter.getInstance(currentAccount).doOnIdle(runnable); } public void performHistoryClear(boolean revoke, boolean canDeleteHistory) { clearingHistory = true; undoView.showWithAction(dialog_id, UndoView.ACTION_CLEAR, () -> { if (!pinnedMessageIds.isEmpty()) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); preferences.edit().putInt("pin_" + dialog_id, pinnedMessageIds.get(0)).commit(); pinnedMessageIds.clear(); pinnedMessageObjects.clear(); currentPinnedMessageId = 0; loadedPinnedMessagesCount = 0; totalPinnedMessagesCount = 0; updatePinnedMessageView(true); } getMessagesController().deleteDialog(dialog_id, 1, revoke); clearingHistory = false; clearHistory(false, null); chatAdapter.notifyDataSetChanged(); }, () -> { clearingHistory = false; chatAdapter.notifyDataSetChanged(); }); chatAdapter.notifyDataSetChanged(); } public long getDialogId() { return dialog_id; } public int getDialogFolderId() { return dialogFolderId; } public int getDialogFilterId() { return dialogFilterId; } public boolean openedWithLivestream() { return livestream; } public UndoView getUndoView() { return undoView; } public long getMergeDialogId() { return mergeDialogId; } public boolean hasReportSpam() { return topChatPanelView != null && topChatPanelView.getTag() == null && reportSpamButton.getVisibility() != View.GONE; } public boolean isReport() { return reportType >= 0; } public void setChatInvite(TLRPC.ChatInvite invite) { chatInvite = invite; } public void setBotUser(String value) { if (inlineReturn != 0) { getMessagesController().sendBotStart(currentUser, value); } else { botUser = value; updateBottomOverlay(); } } private void afterMessageSend() { hideFieldPanel(false); if (chatMode == 0) { getMediaDataController().cleanDraft(dialog_id, threadMessageId, true); } } private void toggleMesagesSearchListView() { if (messagesSearchListView != null) { showMessagesSearchListView(messagesSearchListView.getTag() == null); } } private void showMessagesSearchListView(boolean show) { if (messagesSearchListView == null || show && messagesSearchListView.getTag() != null || !show && messagesSearchListView.getTag() == null) { return; } if (messagesSearchListViewAnimation != null) { messagesSearchListViewAnimation.cancel(); messagesSearchListViewAnimation = null; } if (show) { messagesSearchListView.setVisibility(View.VISIBLE); } messagesSearchListView.setTag(show ? 1 : null); messagesSearchListViewAnimation = new AnimatorSet(); messagesSearchListViewAnimation.playTogether(ObjectAnimator.ofFloat(messagesSearchListView, View.ALPHA, show ? 1.0f : 0.0f)); messagesSearchListViewAnimation.setInterpolator(CubicBezierInterpolator.EASE_IN); messagesSearchListViewAnimation.setDuration(180); messagesSearchListViewAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(messagesSearchListViewAnimation)) { messagesSearchListViewAnimation = null; if (!show) { messagesSearchListView.setVisibility(View.GONE); } } } @Override public void onAnimationCancel(Animator animation) { if (animation.equals(messagesSearchListViewAnimation)) { messagesSearchListViewAnimation = null; } } }); messagesSearchListViewAnimation.start(); } public boolean playFirstUnreadVoiceMessage() { if (chatActivityEnterView != null && chatActivityEnterView.isRecordingAudioVideo()) { return true; } for (int a = messages.size() - 1; a >= 0; a--) { MessageObject messageObject = messages.get(a); if ((messageObject.isVoice() || messageObject.isRoundVideo()) && messageObject.isContentUnread() && !messageObject.isOut()) { MediaController.getInstance().setVoiceMessagesPlaylist(MediaController.getInstance().playMessage(messageObject) ? createVoiceMessagesPlaylist(messageObject, true) : null, true); return true; } } if (Build.VERSION.SDK_INT >= 23 && getParentActivity() != null) { if (getParentActivity().checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 3); return true; } } return false; } private void openScheduledMessages() { if (parentLayout == null || parentLayout.getLastFragment() != this) { return; } Bundle bundle = new Bundle(); if (currentEncryptedChat != null) { bundle.putInt("enc_id", currentEncryptedChat.id); } else if (currentChat != null) { bundle.putLong("chat_id", currentChat.id); } else { bundle.putLong("user_id", currentUser.id); } bundle.putInt("chatMode", MODE_SCHEDULED); ChatActivity fragment = new ChatActivity(bundle); fragment.chatActivityDelegate = new ChatActivityDelegate() { @Override public void openReplyMessage(int mid) { scrollToMessageId(mid, 0, true, 0, true, 0); } @Override public void openSearch(String text) { openSearchWithText(text); } }; presentFragment(fragment, false); } public void shareMyContact(int type, MessageObject messageObject) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("ShareYouPhoneNumberTitle", R.string.ShareYouPhoneNumberTitle)); if (currentUser != null) { if (currentUser.bot) { builder.setMessage(LocaleController.getString("AreYouSureShareMyContactInfoBot", R.string.AreYouSureShareMyContactInfoBot)); } else { builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureShareMyContactInfoUser", R.string.AreYouSureShareMyContactInfoUser, PhoneFormat.getInstance().format("+" + getUserConfig().getCurrentUser().phone), ContactsController.formatName(currentUser.first_name, currentUser.last_name)))); } } else { builder.setMessage(LocaleController.getString("AreYouSureShareMyContactInfo", R.string.AreYouSureShareMyContactInfo)); } builder.setPositiveButton(LocaleController.getString("ShareContact", R.string.ShareContact), (dialogInterface, i) -> { if (type == 1) { TLRPC.TL_contacts_acceptContact req = new TLRPC.TL_contacts_acceptContact(); req.id = getMessagesController().getInputUser(currentUser); getConnectionsManager().sendRequest(req, (response, error) -> { if (error != null) { return; } getMessagesController().processUpdates((TLRPC.Updates) response, false); }); } else { SendMessagesHelper.getInstance(currentAccount).sendMessage(getUserConfig().getCurrentUser(), dialog_id, messageObject, getThreadMessage(), null, null, true, 0); if (chatMode == 0) { moveScrollToLastMessage(false); } hideFieldPanel(false); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } private void showVoiceHint(boolean hide, boolean video) { if (getParentActivity() == null || fragmentView == null || hide && voiceHintTextView == null || chatMode != 0 || chatActivityEnterView == null || chatActivityEnterView.getAudioVideoButtonContainer() == null || chatActivityEnterView.getAudioVideoButtonContainer().getVisibility() != View.VISIBLE) { return; } if (voiceHintTextView == null) { SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } voiceHintTextView = new HintView(getParentActivity(), 9, themeDelegate); frameLayout.addView(voiceHintTextView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); } if (hide) { voiceHintTextView.hide(); return; } if (chatActivityEnterView.hasRecordVideo()) { voiceHintTextView.setText(video ? LocaleController.getString("HoldToVideo", R.string.HoldToVideo) : LocaleController.getString("HoldToAudio", R.string.HoldToAudio)); } else { voiceHintTextView.setText(LocaleController.getString("HoldToAudioOnly", R.string.HoldToAudioOnly)); } voiceHintTextView.showForView(chatActivityEnterView.getAudioVideoButtonContainer(), true); } public boolean checkSlowMode(View view) { CharSequence time = chatActivityEnterView.getSlowModeTimer(); if (time != null) { showSlowModeHint(view, true, time); return true; } return false; } private void hideHints(boolean scroll) { if (!scroll) { if (slowModeHint != null) { slowModeHint.hide(); } if (searchAsListHint != null) { searchAsListHint.hide(); } if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } } if (fwdRestrictedBottomHint != null) { fwdRestrictedBottomHint.hide(); } if (fwdRestrictedTopHint != null) { fwdRestrictedTopHint.hide(); } if (noSoundHintView != null) { noSoundHintView.hide(); } if (forwardHintView != null) { forwardHintView.hide(); } if (pollHintView != null) { pollHintView.hide(); } if (timerHintView != null) { timerHintView.hide(); } if (checksHintView != null) { checksHintView.hide(); } } private void showSlowModeHint(View view, boolean show, CharSequence time) { if (getParentActivity() == null || fragmentView == null || !show && (slowModeHint == null || slowModeHint.getVisibility() != View.VISIBLE)) { return; } slowModeHint.setText(AndroidUtilities.replaceTags(LocaleController.formatString("SlowModeHint", R.string.SlowModeHint, time))); if (show) { slowModeHint.showForView(view, true); } } public void showTimerHint() { if (getParentActivity() == null || fragmentView == null || chatInfo == null) { return; } if (timerHintView == null) { timerHintView = new HintView(getParentActivity(), 7, true, themeDelegate); timerHintView.setAlpha(0.0f); timerHintView.setVisibility(View.INVISIBLE); timerHintView.setShowingDuration(4000); contentView.addView(timerHintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); } String time; if (chatInfo.ttl_period > 24 * 60 * 60) { time = LocaleController.formatPluralString("Days", chatInfo.ttl_period / (24 * 60 * 60)); } else if (chatInfo.ttl_period >= 60 * 60) { time = LocaleController.formatPluralString("Hours", chatInfo.ttl_period / (60 * 60)); } else if (chatInfo.ttl_period >= 60) { time = LocaleController.formatPluralString("Minutes", chatInfo.ttl_period / 60); } else { time = LocaleController.formatPluralString("Seconds", chatInfo.ttl_period); } timerHintView.setText(LocaleController.formatString("AutoDeleteSetInfo", R.string.AutoDeleteSetInfo, time)); timerHintView.showForView(avatarContainer.getTimeItem(), true); } private void showSearchAsListHint() { if (getParentActivity() == null || fragmentView == null || searchCountText == null) { return; } if (searchAsListHint == null) { searchAsListHint = new HintView(getParentActivity(), HintView.TYPE_SEARCH_AS_LIST, themeDelegate); searchAsListHint.setAlpha(0.0f); searchAsListHint.setVisibility(View.INVISIBLE); searchAsListHint.setText(LocaleController.getString("TapToViewAsList", R.string.TapToViewAsList)); contentView.addView(searchAsListHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); } searchAsListHint.showForView(searchCountText, true); } private void showScheduledOrNoSoundHint() { boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); if (SharedConfig.scheduledOrNoSoundHintShows >= 3 || System.currentTimeMillis() % 4 != 0 || disableNoSound) { return; } AndroidUtilities.cancelRunOnUIThread(showScheduledOrNoSoundRunnable); AndroidUtilities.runOnUIThread(showScheduledOrNoSoundRunnable, 200); } private void showMediaBannedHint() { if (getParentActivity() == null || currentChat == null && userInfo == null || fragmentView == null || mediaBanTooltip != null && mediaBanTooltip.getVisibility() == View.VISIBLE) { return; } SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } try { fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception e) { FileLog.e(e); } if (mediaBanTooltip == null) { mediaBanTooltip = new HintView(getParentActivity(), 9, themeDelegate); mediaBanTooltip.setVisibility(View.GONE); frameLayout.addView(mediaBanTooltip, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); } if (userInfo != null && userInfo.voice_messages_forbidden) { mediaBanTooltip.setText(AndroidUtilities.replaceTags(LocaleController.formatString(chatActivityEnterView.isInVideoMode() ? R.string.VideoMessagesRestrictedByPrivacy : R.string.VoiceMessagesRestrictedByPrivacy, currentUser.first_name))); } else if (ChatObject.isActionBannedByDefault(currentChat, ChatObject.ACTION_SEND_MEDIA)) { mediaBanTooltip.setText(LocaleController.getString("GlobalAttachMediaRestricted", R.string.GlobalAttachMediaRestricted)); } else { if (currentChat.banned_rights == null) { return; } if (AndroidUtilities.isBannedForever(currentChat.banned_rights)) { mediaBanTooltip.setText(LocaleController.getString("AttachMediaRestrictedForever", R.string.AttachMediaRestrictedForever)); } else { mediaBanTooltip.setText(LocaleController.formatString("AttachMediaRestricted", R.string.AttachMediaRestricted, LocaleController.formatDateForBan(currentChat.banned_rights.until_date))); } } View sendBtn = chatActivityEnterView.getSendButton(); View audioVideoBtn = chatActivityEnterView.getAudioVideoButtonContainer(); View viewForTooltip = sendBtn; if (sendBtn.getAlpha() < audioVideoBtn.getAlpha()) { viewForTooltip = audioVideoBtn; } mediaBanTooltip.showForView(viewForTooltip, true); } private void showNoSoundHint() { if (scrollingChatListView || SharedConfig.noSoundHintShowed || chatListView == null || getParentActivity() == null || fragmentView == null || noSoundHintView != null && noSoundHintView.getTag() != null) { return; } if (noSoundHintView == null) { SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } noSoundHintView = new HintView(getParentActivity(), 0, themeDelegate); noSoundHintView.setShowingDuration(10000); frameLayout.addView(noSoundHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); noSoundHintView.setAlpha(0.0f); noSoundHintView.setVisibility(View.INVISIBLE); } int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (!(child instanceof ChatMessageCell)) { continue; } ChatMessageCell messageCell = (ChatMessageCell) child; MessageObject messageObject = messageCell.getMessageObject(); if (messageObject == null || !messageObject.isVideo()) { continue; } ImageReceiver imageReceiver = messageCell.getPhotoImage(); AnimatedFileDrawable animation = imageReceiver.getAnimation(); if (animation == null || animation.getCurrentProgressMs() < 3000) { continue; } if (noSoundHintView.showForMessageCell(messageCell, true)) { SharedConfig.setNoSoundHintShowed(true); break; } } } private void checkChecksHint() { if (getMessagesController().pendingSuggestions.contains("NEWCOMER_TICKS")) { AndroidUtilities.runOnUIThread(this::showChecksHint, 1000); } } private void showChecksHint() { if (scrollingChatListView || chatListView == null || getParentActivity() == null || fragmentView == null || checksHintView != null && checksHintView.getTag() != null) { return; } if (checksHintView == null) { SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } checksHintView = new ChecksHintView(getParentActivity(), themeDelegate); frameLayout.addView(checksHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); checksHintView.setAlpha(0.0f); checksHintView.setVisibility(View.INVISIBLE); } int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (!(child instanceof ChatMessageCell)) { continue; } ChatMessageCell messageCell = (ChatMessageCell) child; MessageObject messageObject = messageCell.getMessageObject(); if (messageObject == null || !messageObject.isOutOwner() || !messageObject.isSent()) { continue; } if (checksHintView.showForMessageCell(messageCell, true)) { getMessagesController().removeSuggestion(0, "NEWCOMER_TICKS"); break; } } } private void showForwardHint(ChatMessageCell cell) { if (scrollingChatListView || chatListView == null || getParentActivity() == null || fragmentView == null) { return; } if (forwardHintView == null) { SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return; } forwardHintView = new HintView(getParentActivity(), 1, themeDelegate); frameLayout.addView(forwardHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); forwardHintView.setAlpha(0.0f); forwardHintView.setVisibility(View.INVISIBLE); } forwardHintView.showForMessageCell(cell, true); } private void showTextSelectionHint(MessageObject messageObject) { if (getParentActivity() == null || getMessagesController().isChatNoForwards(messageObject.getChatId()) || (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.noforwards)) { return; } CharSequence text; boolean canShowText = false; if (messageObject.textLayoutBlocks != null && !messageObject.textLayoutBlocks.isEmpty()) { text = messageObject.messageText; if (messageObject.textLayoutBlocks.size() > 1) { canShowText = true; } } else { text = messageObject.caption; } if (!canShowText && text != null) { canShowText = text.length() > 200; } if (!canShowText || SharedConfig.textSelectionHintShows > 2 || textSelectionHintWasShowed || lastTouchY > chatActivityEnterView.getTop() - AndroidUtilities.dp(60)) { return; } textSelectionHintWasShowed = true; SharedConfig.increaseTextSelectionHintShowed(); if (textSelectionHint == null) { textSelectionHint = new TextSelectionHint(getParentActivity(), themeDelegate) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); updatePosition(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); updatePosition(); } public void updatePosition() { int start = -(getMeasuredHeight() + AndroidUtilities.dp(16)); int end = chatActivityEnterView.getTop() - contentView.getMeasuredHeight(); setTranslationY(end - (end + start) * (1f - getPrepareProgress())); } }; contentView.addView(textSelectionHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 56, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); } textSelectionHint.show(); } private boolean showGifHint() { if (chatActivityEnterView == null || chatActivityEnterView.getVisibility() != View.VISIBLE) { return false; } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (preferences.getBoolean("gifhint", false)) { return false; } preferences.edit().putBoolean("gifhint", true).commit(); if (getParentActivity() == null || fragmentView == null || gifHintTextView != null) { return false; } if (!allowContextBotPanelSecond) { if (chatActivityEnterView != null) { chatActivityEnterView.setOpenGifsTabFirst(); } return false; } SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; int index = frameLayout.indexOfChild(chatActivityEnterView); if (index == -1) { return false; } chatActivityEnterView.setOpenGifsTabFirst(); emojiButtonRed = new View(getParentActivity()); emojiButtonRed.setBackgroundResource(R.drawable.redcircle); frameLayout.addView(emojiButtonRed, index + 1, LayoutHelper.createFrame(10, 10, Gravity.BOTTOM | Gravity.LEFT, 30, 0, 0, 27)); gifHintTextView = new HintView(getParentActivity(), 9, themeDelegate); gifHintTextView.setText(LocaleController.getString("TapHereGifs", R.string.TapHereGifs)); frameLayout.addView(gifHintTextView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 5, 0, 5, 3)); AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( ObjectAnimator.ofFloat(gifHintTextView, View.ALPHA, 0.0f, 1.0f), ObjectAnimator.ofFloat(emojiButtonRed, View.ALPHA, 0.0f, 1.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { AndroidUtilities.runOnUIThread(() -> { if (gifHintTextView == null) { return; } AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( ObjectAnimator.ofFloat(gifHintTextView, View.ALPHA, 0.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (gifHintTextView != null) { gifHintTextView.setVisibility(View.GONE); } } }); AnimatorSet.setDuration(300); AnimatorSet.start(); }, 2000); } }); AnimatorSet.setDuration(300); AnimatorSet.start(); View emojiButton = chatActivityEnterView.getEmojiButton(); if (emojiButton != null) { gifHintTextView.showForView(emojiButton, true); } return true; } private void openAttachMenu() { if (getParentActivity() == null || chatActivityEnterView != null && !TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { return; } createChatAttachView(); chatAttachAlert.getPhotoLayout().loadGalleryPhotos(); if (Build.VERSION.SDK_INT == 21 || Build.VERSION.SDK_INT == 22) { chatActivityEnterView.closeKeyboard(); } if (currentChat != null && !ChatObject.hasAdminRights(currentChat) && currentChat.slowmode_enabled) { chatAttachAlert.setMaxSelectedPhotos(10, true); } else { chatAttachAlert.setMaxSelectedPhotos(-1, true); } chatAttachAlert.init(); chatAttachAlert.getCommentTextView().setText(chatActivityEnterView.getFieldText()); chatAttachAlert.parentThemeDelegate = themeDelegate; showDialog(chatAttachAlert); } private void checkAutoDownloadMessages(boolean scrollUp) { if (chatListView == null) { return; } showNoSoundHint(); } private void checkAutoDownloadMessage(MessageObject object) { if (object.mediaExists) { return; } TLRPC.Message message = object.messageOwner; int canDownload = getDownloadController().canDownloadMedia(message); if (canDownload == 0) { return; } TLRPC.Document document = object.getDocument(); TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, AndroidUtilities.getPhotoSize()) : null; if (document == null && photo == null) { return; } if (canDownload == 2 || canDownload == 1 && object.isVideo()) { if (document != null && currentEncryptedChat == null && !object.shouldEncryptPhotoOrVideo() && object.canStreamVideo()) { getFileLoader().loadFile(document, object, 0, 10); } } else { if (document != null) { getFileLoader().loadFile(document, object, 0, MessageObject.isVideoDocument(document) && object.shouldEncryptPhotoOrVideo() ? 2 : 0); } else { getFileLoader().loadFile(ImageLocation.getForObject(photo, object.photoThumbsObject), object, null, 0, object.shouldEncryptPhotoOrVideo() ? 2 : 0); } } } private void showFloatingDateView(boolean scroll) { if (floatingDateView == null) { return; } if (floatingDateView.getTag() == null) { if (floatingDateAnimation != null) { floatingDateAnimation.cancel(); } floatingDateView.setTag(1); floatingDateAnimation = new AnimatorSet(); floatingDateAnimation.setDuration(150); floatingDateAnimation.playTogether(ObjectAnimator.ofFloat(floatingDateView, View.ALPHA, 1.0f)); floatingDateAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(floatingDateAnimation)) { floatingDateAnimation = null; } } }); floatingDateAnimation.start(); } if (!scroll) { invalidateMessagesVisiblePart(); hideDateDelay = 1000; } } private void hideFloatingDateView(boolean animated) { if (floatingDateView.getTag() != null && !currentFloatingDateOnScreen && (!scrollingFloatingDate || currentFloatingTopIsNotMessage)) { floatingDateView.setTag(null); if (animated) { floatingDateAnimation = new AnimatorSet(); floatingDateAnimation.setDuration(150); floatingDateAnimation.playTogether(ObjectAnimator.ofFloat(floatingDateView, View.ALPHA, 0.0f)); floatingDateAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(floatingDateAnimation)) { floatingDateAnimation = null; } } }); floatingDateAnimation.setStartDelay(hideDateDelay); floatingDateAnimation.start(); } else { if (floatingDateAnimation != null) { floatingDateAnimation.cancel(); floatingDateAnimation = null; } floatingDateView.setAlpha(0.0f); } hideDateDelay = 500; } } @Override protected void onRemoveFromParent() { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null && messageObject.isVideo()) { MediaController.getInstance().cleanupPlayer(true, true); } else { MediaController.getInstance().setTextureView(videoTextureView, null, null, false); } } protected void setIgnoreAttachOnPause(boolean value) { ignoreAttachOnPause = value; } public ChatActivityEnterView getChatActivityEnterViewForStickers() { return bottomOverlayChat.getVisibility() != View.VISIBLE && (currentChat == null || ChatObject.canSendStickers(currentChat)) ? chatActivityEnterView : null; } public ChatActivityEnterView getChatActivityEnterView() { return chatActivityEnterView; } public boolean isKeyboardVisible() { return contentView.getKeyboardHeight() > AndroidUtilities.dp(20); } private void checkScrollForLoad(boolean scroll) { if (chatLayoutManager == null || paused || chatAdapter.isFrozen) { return; } int firstVisibleItem = chatLayoutManager.findFirstVisibleItemPosition(); int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(chatLayoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; int totalItemCount = chatAdapter.getItemCount(); int checkLoadCount; if (scroll) { checkLoadCount = 25; } else { checkLoadCount = 5; } if (totalItemCount - firstVisibleItem - visibleItemCount <= checkLoadCount && !loading) { if (!endReached[0]) { loading = true; waitingForLoad.add(lastLoadIndex); if (messagesByDays.size() != 0) { getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, maxMessageId[0], 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else { getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } else if (mergeDialogId != 0 && !endReached[1]) { loading = true; waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(mergeDialogId, 0, false, 50, maxMessageId[1], 0, !cacheEndReached[1], minDate[1], classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } if (visibleItemCount > 0 && !loadingForward && firstVisibleItem <= 10) { if (mergeDialogId != 0 && !forwardEndReached[1]) { waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(mergeDialogId, 0, false, 50, minMessageId[1], 0, true, maxDate[1], classGuid, 1, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loadingForward = true; } else if (!forwardEndReached[0]) { waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, minMessageId[0], 0, true, maxDate[0], classGuid, 1, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loadingForward = true; } } } private void processSelectedAttach(int which) { if (which == attach_photo) { if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.CAMERA}, 19); return; } try { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File image = AndroidUtilities.generatePicturePath(); if (image != null) { if (Build.VERSION.SDK_INT >= 24) { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(getParentActivity(), ApplicationLoader.getApplicationId() + ".provider", image)); takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else { takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image)); } currentPicturePath = image.getAbsolutePath(); } startActivityForResult(takePictureIntent, 0); } catch (Exception e) { FileLog.e(e); } } else if (which == attach_gallery) { if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { try { getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE); } catch (Throwable ignore) { } return; } boolean allowGifs; if (ChatObject.isChannel(currentChat) && currentChat.banned_rights != null && currentChat.banned_rights.send_gifs) { allowGifs = false; } else { allowGifs = true; } PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(PhotoAlbumPickerActivity.SELECT_TYPE_ALL, allowGifs, true, ChatActivity.this); if (currentChat != null && !ChatObject.hasAdminRights(currentChat) && currentChat.slowmode_enabled) { fragment.setMaxSelectedPhotos(10, true); } else { fragment.setMaxSelectedPhotos(editingMessageObject != null ? 1 : 0, editingMessageObject == null); } fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { } @Override public void startPhotoSelectActivity() { try { Intent videoPickerIntent = new Intent(); videoPickerIntent.setType("video/*"); videoPickerIntent.setAction(Intent.ACTION_GET_CONTENT); videoPickerIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.DEFAULT_MAX_FILE_SIZE); Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); Intent chooserIntent = Intent.createChooser(photoPickerIntent, null); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{videoPickerIntent}); startActivityForResult(chooserIntent, 1); } catch (Exception e) { FileLog.e(e); } } }); presentFragment(fragment); } else if (which == attach_video) { if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { try { getParentActivity().requestPermissions(new String[]{Manifest.permission.CAMERA}, BasePermissionsActivity.REQUEST_CODE_OPEN_CAMERA); } catch (Throwable ignore) { } return; } try { Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); File video = AndroidUtilities.generateVideoPath(); if (video != null) { if (Build.VERSION.SDK_INT >= 24) { takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(getParentActivity(), ApplicationLoader.getApplicationId() + ".provider", video)); takeVideoIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); takeVideoIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else if (Build.VERSION.SDK_INT >= 18) { takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(video)); } takeVideoIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.DEFAULT_MAX_FILE_SIZE); currentPicturePath = video.getAbsolutePath(); } startActivityForResult(takeVideoIntent, 2); } catch (Exception e) { FileLog.e(e); } } } public boolean allowSendGifs() { if (ChatObject.isChannel(currentChat) && currentChat.banned_rights != null && currentChat.banned_rights.send_gifs) { return false; } else { return true; } } public void openPollCreate(Boolean quiz) { PollCreateActivity pollCreateActivity = new PollCreateActivity(ChatActivity.this, quiz); pollCreateActivity.setDelegate((poll, params, notify, scheduleDate) -> { getSendMessagesHelper().sendMessage(poll, dialog_id, replyingMessageObject, getThreadMessage(), null, params, notify, scheduleDate); afterMessageSend(); }); presentFragment(pollCreateActivity); } @Override public void didSelectFiles(ArrayList files, String caption, ArrayList fmessages, boolean notify, int scheduleDate) { fillEditingMediaWithCaption(caption, null); if (!fmessages.isEmpty() && !TextUtils.isEmpty(caption)) { SendMessagesHelper.getInstance(currentAccount).sendMessage(caption, dialog_id, null, null, null, true, null, null, null, true, 0, null); caption = null; } getSendMessagesHelper().sendMessage(fmessages, dialog_id, false, false,true, 0); SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, caption, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, notify, scheduleDate); afterMessageSend(); } @Override public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, true, false, editingMessageObject, notify, scheduleDate); afterMessageSend(); if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { scheduledMessagesCount = 0; } scheduledMessagesCount += photos.size(); updateScheduledInterface(true); } } public void didSelectSearchPhotos(ArrayList photos, boolean notify, int scheduleDate) { if (photos.isEmpty()) { return; } boolean hasNoGifs = false; for (int a = 0; a < photos.size(); a++) { SendMessagesHelper.SendingMediaInfo info = photos.get(a); if (info.inlineResult == null && info.videoEditedInfo == null) { hasNoGifs = true; break; } } if (!hasNoGifs && !TextUtils.isEmpty(photos.get(0).caption)) { SendMessagesHelper.getInstance(currentAccount).sendMessage(photos.get(0).caption, dialog_id, replyingMessageObject, getThreadMessage(), null, false, photos.get(0).entities, null, null, notify, scheduleDate, null); } for (int a = 0; a < photos.size(); a++) { SendMessagesHelper.SendingMediaInfo info = photos.get(a); if (info.inlineResult != null && info.videoEditedInfo == null) { SendMessagesHelper.prepareSendingBotContextResult(this, getAccountInstance(), info.inlineResult, info.params, dialog_id, replyingMessageObject, getThreadMessage(), notify, scheduleDate); photos.remove(a); a--; } } if (photos.isEmpty()) { return; } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, false, true, editingMessageObject, notify, scheduleDate); afterMessageSend(); if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { scheduledMessagesCount = 0; } scheduledMessagesCount += photos.size(); updateScheduledInterface(true); } } @Override public void startDocumentSelectActivity() { try { Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT); if (Build.VERSION.SDK_INT >= 18) { photoPickerIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); } photoPickerIntent.setType("*/*"); startActivityForResult(photoPickerIntent, 21); } catch (Exception e) { FileLog.e(e); } } @Override public boolean dismissDialogOnPause(Dialog dialog) { return dialog != chatAttachAlert && super.dismissDialogOnPause(dialog); } private void searchLinks(final CharSequence charSequence, final boolean force) { if (currentEncryptedChat != null && getMessagesController().secretWebpagePreview == 0 || editingMessageObject != null && !editingMessageObject.isWebpage()) { return; } if (force && foundWebPage != null) { if (foundWebPage.url != null) { int index = TextUtils.indexOf(charSequence, foundWebPage.url); char lastChar = 0; boolean lenEqual = false; if (index == -1) { if (foundWebPage.display_url != null) { index = TextUtils.indexOf(charSequence, foundWebPage.display_url); lenEqual = index != -1 && index + foundWebPage.display_url.length() == charSequence.length(); lastChar = index != -1 && !lenEqual ? charSequence.charAt(index + foundWebPage.display_url.length()) : 0; } } else { lenEqual = index + foundWebPage.url.length() == charSequence.length(); lastChar = !lenEqual ? charSequence.charAt(index + foundWebPage.url.length()) : 0; } if (index != -1 && (lenEqual || lastChar == ' ' || lastChar == ',' || lastChar == '.' || lastChar == '!' || lastChar == '/')) { return; } } pendingLinkSearchString = null; foundUrls = null; showFieldPanelForWebPage(false, foundWebPage, false); } final MessagesController messagesController = getMessagesController(); Utilities.searchQueue.postRunnable(() -> { if (linkSearchRequestId != 0) { getConnectionsManager().cancelRequest(linkSearchRequestId, true); linkSearchRequestId = 0; } ArrayList urls = null; CharSequence textToCheck; try { Matcher m = AndroidUtilities.WEB_URL.matcher(charSequence); while (m.find()) { if (m.start() > 0) { if (charSequence.charAt(m.start() - 1) == '@') { continue; } } if (urls == null) { urls = new ArrayList<>(); } urls.add(charSequence.subSequence(m.start(), m.end())); } if (charSequence instanceof Spannable) { URLSpanReplacement[] spans = ((Spannable) charSequence).getSpans(0, charSequence.length(), URLSpanReplacement.class); if (spans != null && spans.length > 0) { if (urls == null) { urls = new ArrayList<>(); } for (int a = 0; a < spans.length; a++) { urls.add(spans[a].getURL()); } } } if (urls != null && foundUrls != null && urls.size() == foundUrls.size()) { boolean clear = true; for (int a = 0; a < urls.size(); a++) { if (!TextUtils.equals(urls.get(a), foundUrls.get(a))) { clear = false; } } if (clear) { return; } } foundUrls = urls; if (urls == null) { AndroidUtilities.runOnUIThread(() -> { if (foundWebPage != null) { showFieldPanelForWebPage(false, foundWebPage, false); foundWebPage = null; } }); return; } textToCheck = TextUtils.join(" ", urls); } catch (Exception e) { FileLog.e(e); String text = charSequence.toString().toLowerCase(); if (charSequence.length() < 13 || !text.contains("http://") && !text.contains("https://")) { AndroidUtilities.runOnUIThread(() -> { if (foundWebPage != null) { showFieldPanelForWebPage(false, foundWebPage, false); foundWebPage = null; } }); return; } textToCheck = charSequence; } if (currentEncryptedChat != null && messagesController.secretWebpagePreview == 2) { AndroidUtilities.runOnUIThread(() -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { messagesController.secretWebpagePreview = 1; MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", getMessagesController().secretWebpagePreview).commit(); foundUrls = null; searchLinks(charSequence, force); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); builder.setMessage(LocaleController.getString("SecretLinkPreviewAlert", R.string.SecretLinkPreviewAlert)); showDialog(builder.create()); messagesController.secretWebpagePreview = 0; MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", messagesController.secretWebpagePreview).commit(); }); return; } final TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview(); if (textToCheck instanceof String) { req.message = (String) textToCheck; } else { req.message = textToCheck.toString(); } linkSearchRequestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { linkSearchRequestId = 0; if (error == null) { if (response instanceof TLRPC.TL_messageMediaWebPage) { foundWebPage = ((TLRPC.TL_messageMediaWebPage) response).webpage; if (foundWebPage instanceof TLRPC.TL_webPage || foundWebPage instanceof TLRPC.TL_webPagePending) { if (foundWebPage instanceof TLRPC.TL_webPagePending) { pendingLinkSearchString = req.message; } if (currentEncryptedChat != null && foundWebPage instanceof TLRPC.TL_webPagePending) { foundWebPage.url = req.message; } showFieldPanelForWebPage(true, foundWebPage, false); } else { if (foundWebPage != null) { showFieldPanelForWebPage(false, foundWebPage, false); foundWebPage = null; } } } else { if (foundWebPage != null) { showFieldPanelForWebPage(false, foundWebPage, false); foundWebPage = null; } } } })); getConnectionsManager().bindRequestToGuid(linkSearchRequestId, classGuid); }); } private void forwardMessages(ArrayList arrayList, boolean fromMyName, boolean hideCaption, boolean notify, int scheduleDate) { if (arrayList == null || arrayList.isEmpty()) { return; } if ((scheduleDate != 0) == (chatMode == MODE_SCHEDULED)) { waitingForSendingMessageLoad = true; } int result = getSendMessagesHelper().sendMessage(arrayList, dialog_id, fromMyName, hideCaption, notify, scheduleDate); AlertsCreator.showSendMediaAlert(result, this, themeDelegate); if (result != 0) { AndroidUtilities.runOnUIThread(() -> { waitingForSendingMessageLoad = false; hideFieldPanel(true); }); } } public boolean shouldShowImport() { return openImport; } public void setOpenImport() { openImport = true; } private void checkBotKeyboard() { if (chatActivityEnterView == null || botButtons == null || userBlocked) { return; } if (botButtons.messageOwner.reply_markup instanceof TLRPC.TL_replyKeyboardForceReply) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); if (preferences.getInt("answered_" + dialog_id, 0) != botButtons.getId() && (replyingMessageObject == null || chatActivityEnterView.getFieldText() == null)) { botReplyButtons = botButtons; chatActivityEnterView.setButtons(botButtons); showFieldPanelForReply(botButtons); } } else { if (replyingMessageObject != null && botReplyButtons == replyingMessageObject) { botReplyButtons = null; hideFieldPanel(true); } chatActivityEnterView.setButtons(botButtons); } } public void hideFieldPanel(boolean animated) { showFieldPanel(false, null, null, null, null, true, 0, false, animated); } public void hideFieldPanel(boolean notify, int scheduleDate, boolean animated) { showFieldPanel(false, null, null, null, null, notify, scheduleDate, false, animated); } public void showFieldPanelForWebPage(boolean show, TLRPC.WebPage webPage, boolean cancel) { showFieldPanel(show, null, null, null, webPage, true, 0, cancel, true); } public void showFieldPanelForForward(boolean show, ArrayList messageObjectsToForward) { showFieldPanel(show, null, null, messageObjectsToForward, null, true, 0, false, true); } public void showFieldPanelForReply(MessageObject messageObjectToReply) { showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, false, true); } public void showFieldPanelForEdit(boolean show, MessageObject messageObjectToEdit) { showFieldPanel(show, null, messageObjectToEdit, null, null, true, 0, false, true); } public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean notify, int scheduleDate, boolean cancel, boolean animated) { if (chatActivityEnterView == null) { return; } boolean showHint = false; if (show) { if (messageObjectToReply == null && messageObjectsToForward == null && messageObjectToEdit == null && webPage == null) { return; } hideHints(false); if (searchItem != null && actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(false); chatActivityEnterView.setFieldFocused(); AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null) { chatActivityEnterView.openKeyboard(); } }, 100); } boolean openKeyboard = false; if (messageObjectToReply != null && messageObjectToReply.getDialogId() != dialog_id) { messageObjectsToForward = new ArrayList<>(); messageObjectsToForward.add(messageObjectToReply); messageObjectToReply = null; openKeyboard = true; } chatActivityEnterTopView.setEditMode(false); if (messageObjectToEdit != null) { forwardingMessages = null; if (threadMessageId == 0) { replyingMessageObject = null; chatActivityEnterView.setReplyingMessageObject(null); } editingMessageObject = messageObjectToEdit; final boolean mediaEmpty = messageObjectToEdit.isMediaEmpty(); chatActivityEnterView.setEditingMessageObject(messageObjectToEdit, !mediaEmpty); if (foundWebPage != null) { return; } chatActivityEnterView.setForceShowSendButton(false, false); final boolean canEditMedia = messageObjectToEdit.canEditMedia(); replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelEdit", R.string.AccDescrCancelEdit)); if (!mediaEmpty && canEditMedia) { String editButtonText = null; String replaceButtonText; if (messageObjectToEdit.isPhoto()) { editButtonText = LocaleController.getString("EditMessageEditPhoto", R.string.EditMessageEditPhoto); replaceButtonText = LocaleController.getString("EditMessageReplacePhoto", R.string.EditMessageReplacePhoto); } else if (messageObjectToEdit.isVideo()) { editButtonText = LocaleController.getString("EditMessageEditVideo", R.string.EditMessageEditVideo); replaceButtonText = LocaleController.getString("EditMessageReplaceVideo", R.string.EditMessageReplaceVideo); } else if (messageObjectToEdit.isGif()) { replaceButtonText = LocaleController.getString("EditMessageReplaceGif", R.string.EditMessageReplaceGif); } else if (messageObjectToEdit.isMusic()) { replaceButtonText = LocaleController.getString("EditMessageReplaceAudio", R.string.EditMessageReplaceAudio); } else { replaceButtonText = LocaleController.getString("EditMessageReplaceFile", R.string.EditMessageReplaceFile); } final ChatActivityEnterTopView.EditViewButton[] buttons = chatActivityEnterTopView.getEditView().getButtons(); buttons[0].setEditButton(editButtonText != null); buttons[0].getTextView().setText(editButtonText != null ? editButtonText : replaceButtonText); buttons[0].getImageView().setImageResource(editButtonText != null ? R.drawable.msg_photoeditor : R.drawable.msg_replace); buttons[1].setVisibility(editButtonText != null ? View.VISIBLE : View.GONE); if (editButtonText != null) { buttons[1].getTextView().setText(replaceButtonText); } chatActivityEnterTopView.setEditMode(true); } else { replyIconImageView.setImageResource(R.drawable.group_edit); replyIconImageView.setContentDescription(LocaleController.getString("AccDescrEditing", R.string.AccDescrEditing)); if (mediaEmpty) { replyNameTextView.setText(LocaleController.getString("EditMessage", R.string.EditMessage)); } else { replyNameTextView.setText(LocaleController.getString("EditCaption", R.string.EditCaption)); } if (canEditMedia) { replyObjectTextView.setText(LocaleController.getString("EditMessageMedia", R.string.EditMessageMedia)); } else if (messageObjectToEdit.messageText != null || messageObjectToEdit.caption != null) { String mess = messageObjectToEdit.caption != null ? messageObjectToEdit.caption.toString() : messageObjectToEdit.messageText.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); Spannable cs = new SpannableStringBuilder(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); MediaDataController.addTextStyleRuns(messageObjectToEdit, cs); if (messageObjectToEdit.messageOwner != null) { cs = MessageObject.replaceAnimatedEmoji(cs, messageObjectToEdit.messageOwner.entities, replyObjectTextView.getPaint().getFontMetricsInt()); } replyObjectTextView.setText(AnimatedEmojiSpan.cloneSpans(cs)); } } } else if (messageObjectToReply != null) { forwardingMessages = null; editingMessageObject = null; replyingMessageObject = messageObjectToReply; chatActivityEnterView.setReplyingMessageObject(messageObjectToReply); chatActivityEnterView.setEditingMessageObject(null, false); if (foundWebPage != null) { return; } String restrictionReason = MessagesController.getRestrictionReason(messageObjectToReply.messageOwner.restriction_reason); chatActivityEnterView.setForceShowSendButton(false, false); String name; if (messageObjectToReply.isFromUser()) { if (messageObjectToReply.messageOwner.from_id.channel_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(messageObjectToReply.messageOwner.from_id.channel_id); if (chat == null) { return; } name = chat.title; } else { TLRPC.User user = getMessagesController().getUser(messageObjectToReply.messageOwner.from_id.user_id); if (user == null) { return; } name = UserObject.getUserName(user); } } else { TLRPC.Chat chat; if (ChatObject.isChannel(currentChat) && currentChat.megagroup && messageObjectToReply.isForwardedChannelPost()) { chat = getMessagesController().getChat(messageObjectToReply.messageOwner.fwd_from.from_id.channel_id); } else { chat = getMessagesController().getChat(-messageObjectToReply.getSenderId()); } if (chat == null) { return; } name = chat.title; } replyIconImageView.setImageResource(R.drawable.msg_panel_reply); replyNameTextView.setText(name); replyIconImageView.setContentDescription(LocaleController.getString("AccDescrReplying", R.string.AccDescrReplying)); replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelReply", R.string.AccDescrCancelReply)); CharSequence replyObjectText = null; CharSequence sourceText = null; if (!TextUtils.isEmpty(restrictionReason)) { replyObjectText = restrictionReason; sourceText = restrictionReason; } else if (messageObjectToReply.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { replyObjectText = Emoji.replaceEmoji(messageObjectToReply.messageOwner.media.game.title, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); sourceText = messageObjectToReply.messageOwner.media.game.title; } else if (messageObjectToReply.messageText != null || messageObjectToReply.caption != null) { CharSequence mess = messageObjectToReply.caption != null ? messageObjectToReply.caption.toString() : messageObjectToReply.messageText.toString(); sourceText = mess; if (mess.length() > 150) { mess = mess.subSequence(0, 150); } mess = AndroidUtilities.replaceNewLines(mess); if (messageObjectToReply.messageOwner != null && messageObjectToReply.messageOwner.entities != null) { mess = MessageObject.replaceAnimatedEmoji(mess, messageObjectToReply.messageOwner.entities, replyObjectTextView.getPaint().getFontMetricsInt()); } replyObjectText = Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); } if (replyObjectText != null) { if (replyObjectText instanceof Spannable && sourceText != null) { MediaDataController.addTextStyleRuns(messageObjectToReply.messageOwner.entities, sourceText, (Spannable) replyObjectText); } replyObjectTextView.setText(AnimatedEmojiSpan.cloneSpans(replyObjectText)); } } else if (messageObjectsToForward != null) { if (messageObjectsToForward.isEmpty()) { return; } if (threadMessageId == 0) { replyingMessageObject = null; chatActivityEnterView.setReplyingMessageObject(null); } editingMessageObject = null; chatActivityEnterView.setEditingMessageObject(null, false); if (forwardingMessages == null) { forwardingMessages = new ForwardingMessagesParams(messageObjectsToForward, dialog_id); } if (foundWebPage != null) { return; } chatActivityEnterView.setForceShowSendButton(true, false); ArrayList uids = new ArrayList<>(); replyIconImageView.setImageResource(R.drawable.msg_panel_forward); replyIconImageView.setContentDescription(LocaleController.getString("AccDescrForwarding", R.string.AccDescrForwarding)); replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelForward", R.string.AccDescrCancelForward)); MessageObject object = messageObjectsToForward.get(0); if (object.isFromUser()) { uids.add(object.messageOwner.from_id.user_id); } else { TLRPC.Chat chat = getMessagesController().getChat(object.messageOwner.peer_id.channel_id); if (ChatObject.isChannel(chat) && chat.megagroup && object.isForwardedChannelPost()) { uids.add(-object.messageOwner.fwd_from.from_id.channel_id); } else { uids.add(-object.messageOwner.peer_id.channel_id); } } int type = object.isAnimatedEmoji() || object.isDice() ? 0 : object.type; for (int a = 1; a < messageObjectsToForward.size(); a++) { object = messageObjectsToForward.get(a); long uid; if (object.isFromUser()) { uid = object.messageOwner.from_id.user_id; } else { TLRPC.Chat chat = getMessagesController().getChat(object.messageOwner.peer_id.channel_id); if (ChatObject.isChannel(chat) && chat.megagroup && object.isForwardedChannelPost()) { uid = -object.messageOwner.fwd_from.from_id.channel_id; } else { uid = -object.messageOwner.peer_id.channel_id; } } if (!uids.contains(uid)) { uids.add(uid); } if (messageObjectsToForward.get(a).type != type) { type = -1; } } StringBuilder userNames = new StringBuilder(); for (int a = 0; a < uids.size(); a++) { Long uid = uids.get(a); TLRPC.Chat chat = null; TLRPC.User user = null; if (uid > 0) { user = getMessagesController().getUser(uid); } else { chat = getMessagesController().getChat(-uid); } if (user == null && chat == null) { continue; } if (uids.size() == 1) { if (user != null) { userNames.append(UserObject.getUserName(user)); } else { userNames.append(chat.title); } } else if (uids.size() == 2 || userNames.length() == 0) { if (userNames.length() > 0) { userNames.append(", "); } if (user != null) { if (!TextUtils.isEmpty(user.first_name)) { userNames.append(user.first_name); } else if (!TextUtils.isEmpty(user.last_name)) { userNames.append(user.last_name); } else { userNames.append(" "); } } else { userNames.append(chat.title); } } else { userNames.append(" "); userNames.append(LocaleController.formatPluralString("AndOther", uids.size() - 1)); break; } } formwardingNameText = userNames; if (type == -1 || type == 0 || type == 10 || type == 11 || type == MessageObject.TYPE_EMOJIS) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardMessagesCount", messageObjectsToForward.size())); } else if (type == 1) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardPhoto", messageObjectsToForward.size())); if (messageObjectsToForward.size() == 1) { messageObjectToReply = messageObjectsToForward.get(0); } } else if (type == 4) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardLocation", messageObjectsToForward.size())); } else if (type == 3) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardVideo", messageObjectsToForward.size())); if (messageObjectsToForward.size() == 1) { messageObjectToReply = messageObjectsToForward.get(0); } } else if (type == 12) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardContact", messageObjectsToForward.size())); } else if (type == 2) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardAudio", messageObjectsToForward.size())); } else if (type == MessageObject.TYPE_ROUND_VIDEO) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardRound", messageObjectsToForward.size())); } else if (type == 14) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardMusic", messageObjectsToForward.size())); } else if (type == MessageObject.TYPE_STICKER || type == MessageObject.TYPE_ANIMATED_STICKER) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardSticker", messageObjectsToForward.size())); } else if (type == 17) { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardPoll", messageObjectsToForward.size())); } else if (type == 8 || type == 9) { if (messageObjectsToForward.size() == 1 & type == 9) { messageObjectToReply = messageObjectsToForward.get(0); } if (messageObjectsToForward.size() == 1 && type == 8) { replyNameTextView.setText(LocaleController.getString("AttachGif", R.string.AttachGif)); } else { replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardFile", messageObjectsToForward.size())); } } if (forwardingMessages.hideForwardSendersName) { replyObjectTextView.setText(LocaleController.getString("HiddenSendersNameDescription", R.string.HiddenSendersNameDescription)); } else { if ((type == -1 || type == 0 || type == 10 || type == 11 || type == MessageObject.TYPE_EMOJIS) && (messageObjectsToForward.size() == 1 && messageObjectsToForward.get(0).messageText != null)) { MessageObject messageObject = messageObjectsToForward.get(0); CharSequence mess = new SpannableStringBuilder(messageObject.messageText.toString()); if (mess.length() > 150) { mess = mess.subSequence(0, 150); } mess = Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); if (mess instanceof Spannable) { MediaDataController.addTextStyleRuns(messageObject.messageOwner.entities, messageObject.messageText, (Spannable) mess); if (messageObject.messageOwner != null) { mess = MessageObject.replaceAnimatedEmoji(mess, messageObject.messageOwner.entities, replyObjectTextView.getPaint().getFontMetricsInt()); } } replyObjectTextView.setText(mess); } else { replyObjectTextView.setText(LocaleController.formatString("ForwardingFromNames", R.string.ForwardingFromNames, userNames)); } } if (!SharedConfig.forwardingOptionsHintShown) { showHint = true; } } else { replyIconImageView.setImageResource(R.drawable.msg_link); if (webPage instanceof TLRPC.TL_webPagePending) { replyNameTextView.setText(LocaleController.getString("GettingLinkInfo", R.string.GettingLinkInfo)); replyObjectTextView.setText(pendingLinkSearchString); } else { if (webPage.site_name != null) { replyNameTextView.setText(webPage.site_name); } else if (webPage.title != null) { replyNameTextView.setText(webPage.title); } else { replyNameTextView.setText(LocaleController.getString("LinkPreview", R.string.LinkPreview)); } if (webPage.title != null) { replyObjectTextView.setText(webPage.title); } else if (webPage.description != null) { replyObjectTextView.setText(webPage.description); } else if (webPage.author != null) { replyObjectTextView.setText(webPage.author); } else { replyObjectTextView.setText(webPage.display_url); } chatActivityEnterView.setWebPage(webPage, true); } } MessageObject thumbMediaMessageObject; if (messageObjectToReply != null) { thumbMediaMessageObject = messageObjectToReply; } else if (messageObjectToEdit != null) { if (!chatActivityEnterTopView.isEditMode()) { thumbMediaMessageObject = messageObjectToEdit; } else { thumbMediaMessageObject = null; } } else { thumbMediaMessageObject = null; } FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) replyNameTextView.getLayoutParams(); FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) replyObjectTextView.getLayoutParams(); FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) replyObjectHintTextView.getLayoutParams(); int cacheType = 1; int size = 0; TLRPC.PhotoSize photoSize = null; TLRPC.PhotoSize thumbPhotoSize = null; TLObject photoSizeObject = null; if (thumbMediaMessageObject != null && TextUtils.isEmpty(MessagesController.getRestrictionReason(thumbMediaMessageObject.messageOwner.restriction_reason))) { photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs2, 320); thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs2, AndroidUtilities.dp(40)); photoSizeObject = thumbMediaMessageObject.photoThumbsObject2; if (photoSize == null) { if (thumbMediaMessageObject.mediaExists) { photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); if (photoSize != null) { size = photoSize.size; } cacheType = 0; } else { photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, 320); } thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, AndroidUtilities.dp(40)); photoSizeObject = thumbMediaMessageObject.photoThumbsObject; } } if (photoSize == thumbPhotoSize) { thumbPhotoSize = null; } if (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || thumbMediaMessageObject.isAnyKindOfSticker() || thumbMediaMessageObject.isSecretMedia() || thumbMediaMessageObject.isWebpageDocument()) { replyImageView.setImageBitmap(null); replyImageLocation = null; replyImageLocationObject = null; replyImageView.setVisibility(View.INVISIBLE); layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = AndroidUtilities.dp(52); } else { if (thumbMediaMessageObject.isRoundVideo()) { replyImageView.setRoundRadius(AndroidUtilities.dp(17)); } else { replyImageView.setRoundRadius(AndroidUtilities.dp(2)); } replyImageSize = size; replyImageCacheType = cacheType; replyImageLocation = photoSize; replyImageThumbLocation = thumbPhotoSize; replyImageLocationObject = photoSizeObject; replyImageView.setImage(ImageLocation.getForObject(replyImageLocation, photoSizeObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), "50_50_b", null, size, cacheType, thumbMediaMessageObject); replyImageView.setVisibility(View.VISIBLE); layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = AndroidUtilities.dp(96); } replyNameTextView.setLayoutParams(layoutParams1); replyObjectTextView.setLayoutParams(layoutParams2); replyObjectTextView.setLayoutParams(layoutParams3); chatActivityEnterView.showTopView(true, openKeyboard); } else { if (replyingMessageObject == null && forwardingMessages == null && foundWebPage == null && editingMessageObject == null && !chatActivityEnterView.isTopViewVisible()) { return; } if (replyingMessageObject != null && replyingMessageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyKeyboardForceReply) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); preferences.edit().putInt("answered_" + dialog_id, replyingMessageObject.getId()).commit(); } if (foundWebPage != null) { foundWebPage = null; chatActivityEnterView.setWebPage(null, !cancel); if (webPage != null && (replyingMessageObject != null || forwardingMessages != null || editingMessageObject != null)) { showFieldPanel(true, replyingMessageObject, editingMessageObject, forwardingMessages != null ? forwardingMessages.messages : null, null, notify, scheduleDate, false, true); return; } } if (forwardingMessages != null) { ArrayList messagesToForward = new ArrayList<>(); forwardingMessages.getSelectedMessages(messagesToForward); forwardMessages(messagesToForward, forwardingMessages.hideForwardSendersName, forwardingMessages.hideCaption, notify, scheduleDate != 0 && scheduleDate != 0x7ffffffe ? scheduleDate + 1 : scheduleDate); forwardingMessages = null; } chatActivityEnterView.setForceShowSendButton(false, animated); if (!waitingForSendingMessageLoad) { chatActivityEnterView.hideTopView(animated); } chatActivityEnterView.setReplyingMessageObject(threadMessageObject); chatActivityEnterView.setEditingMessageObject(null, false); topViewWasVisible = 0; replyingMessageObject = threadMessageObject; editingMessageObject = null; replyImageLocation = null; replyImageLocationObject = null; } if (showHint) { if (tapForForwardingOptionsHitRunnable == null) { AndroidUtilities.runOnUIThread(tapForForwardingOptionsHitRunnable = () -> { showTapForForwardingOptionsHit = !showTapForForwardingOptionsHit; replyObjectTextView.setPivotX(0); replyObjectHintTextView.setPivotX(0); if (showTapForForwardingOptionsHit) { replyObjectTextView.animate().alpha(0f).scaleX(0.98f).scaleY(0.98f).setDuration(150).start(); replyObjectHintTextView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).start(); } else { replyObjectTextView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).start(); replyObjectHintTextView.animate().alpha(0f).scaleX(0.98f).scaleY(0.98f).setDuration(150).start(); } AndroidUtilities.runOnUIThread(tapForForwardingOptionsHitRunnable, 6000); }, 6000); } } else { if (tapForForwardingOptionsHitRunnable != null) { AndroidUtilities.cancelRunOnUIThread(tapForForwardingOptionsHitRunnable); tapForForwardingOptionsHitRunnable = null; } replyObjectTextView.setAlpha(1f); replyObjectHintTextView.setAlpha(0); } } private void moveScrollToLastMessage(boolean skipSponsored) { if (chatListView != null && !messages.isEmpty() && !pinchToZoomHelper.isInOverlayMode()) { int position = 0; if (skipSponsored) { position += getSponsoredMessagesCount(); } chatLayoutManager.scrollToPositionWithOffset(position, 0); chatListView.stopScroll(); } } private Runnable sendSecretMessageRead(MessageObject messageObject, boolean readNow) { if (messageObject == null || messageObject.isOut() || !messageObject.isSecretMedia() || messageObject.messageOwner.destroyTime != 0 || messageObject.messageOwner.ttl <= 0) { return null; } messageObject.messageOwner.destroyTime = messageObject.messageOwner.ttl + getConnectionsManager().getCurrentTime(); if (readNow) { if (currentEncryptedChat != null) { getMessagesController().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id, messageObject.messageOwner.ttl); } else { getMessagesController().markMessageAsRead2(dialog_id, messageObject.getId(), null, messageObject.messageOwner.ttl, 0); } return null; } else { return () -> { if (currentEncryptedChat != null) { getMessagesController().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id, messageObject.messageOwner.ttl); } else { getMessagesController().markMessageAsRead2(dialog_id, messageObject.getId(), null, messageObject.messageOwner.ttl, 0); } }; } } private void clearChatData() { messages.clear(); messagesByDays.clear(); waitingForLoad.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; if (chatAdapter != null) { showProgressView(chatAdapter.botInfoRow < 0); } if (chatListView != null) { chatListView.setEmptyView(null); } for (int a = 0; a < 2; a++) { messagesDict[a].clear(); if (currentEncryptedChat == null) { maxMessageId[a] = Integer.MAX_VALUE; minMessageId[a] = Integer.MIN_VALUE; } else { maxMessageId[a] = Integer.MIN_VALUE; minMessageId[a] = Integer.MAX_VALUE; } maxDate[a] = Integer.MIN_VALUE; minDate[a] = 0; endReached[a] = false; cacheEndReached[a] = false; forwardEndReached[a] = true; } first = true; firstLoading = true; loading = true; loadingForward = false; waitingForReplyMessageLoad = false; startLoadFromMessageId = 0; showScrollToMessageError = false; last_message_id = 0; unreadMessageObject = null; createUnreadMessageAfterId = 0; createUnreadMessageAfterIdLoading = false; needSelectFromMessageId = false; if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(false); } } public void scrollToLastMessage(boolean skipSponsored) { if (chatListView.isFastScrollAnimationRunning()) { return; } forceNextPinnedMessageId = 0; nextScrollToMessageId = 0; forceScrollToFirst = false; chatScrollHelper.setScrollDirection(RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN); if (forwardEndReached[0] && first_unread_id == 0 && startLoadFromMessageId == 0) { if (chatLayoutManager.findFirstCompletelyVisibleItemPosition() == 0) { canShowPagedownButton = false; updatePagedownButtonVisibility(true); removeSelectedMessageHighlight(); updateVisibleRows(); } else { chatAdapter.updateRowsSafe(); chatScrollHelperCallback.scrollTo = null; int position = 0; if (skipSponsored) { while (position < messages.size()) { if (!messages.get(position).isSponsored()) { break; } position++; } } chatScrollHelper.scrollToPosition(position, 0, true, true); } } else { if (progressDialog != null) { progressDialog.dismiss(); } updatePinnedListButton(false); progressDialog = new AlertDialog(getParentActivity(), 3, themeDelegate); progressDialog.setOnCancelListener(postponedScrollCancelListener); progressDialog.showDelayed(1000); postponedScrollToLastMessageQueryIndex = lastLoadIndex; postponedScrollMessageId = 0; postponedScrollIsCanceled = false; waitingForLoad.clear(); waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, true, 0, classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } } public void updateTextureViewPosition(boolean needScroll) { if (fragmentView == null || paused) { return; } boolean foundTextureViewMessage = false; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell messageCell = (ChatMessageCell) view; MessageObject messageObject = messageCell.getMessageObject(); if (videoPlayerContainer != null && (messageObject.isRoundVideo() || messageObject.isVideo()) && MediaController.getInstance().isPlayingMessage(messageObject)) { ImageReceiver imageReceiver = messageCell.getPhotoImage(); videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); float translationY = messageCell.getY() + imageReceiver.getImageY() + chatListView.getY() - videoPlayerContainer.getTop(); videoPlayerContainer.setTranslationY(translationY); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) videoPlayerContainer.getLayoutParams(); if (messageObject.isRoundVideo()) { videoPlayerContainer.setTag(R.id.parent_tag, null); if (layoutParams.width != AndroidUtilities.roundPlayingMessageSize || layoutParams.height != AndroidUtilities.roundPlayingMessageSize) { layoutParams.width = layoutParams.height = AndroidUtilities.roundPlayingMessageSize; aspectRatioFrameLayout.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT); videoPlayerContainer.setLayoutParams(layoutParams); } float scale = (AndroidUtilities.roundPlayingMessageSize + AndroidUtilities.roundMessageInset * 2) / (float) AndroidUtilities.roundPlayingMessageSize; float transitionScale = messageCell.getPhotoImage().getImageWidth() / AndroidUtilities.roundPlayingMessageSize; if (videoPlayerContainer.getScaleX() != transitionScale) { videoPlayerContainer.invalidate(); fragmentView.invalidate(); } videoPlayerContainer.setPivotX(0); videoPlayerContainer.setPivotY(0); videoPlayerContainer.setScaleX(transitionScale); videoPlayerContainer.setScaleY(transitionScale); videoTextureView.setScaleX(scale); videoTextureView.setScaleY(scale); } else { videoPlayerContainer.setTag(R.id.parent_tag, imageReceiver); if (layoutParams.width != imageReceiver.getImageWidth() || layoutParams.height != imageReceiver.getImageHeight()) { aspectRatioFrameLayout.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL); layoutParams.width = (int) imageReceiver.getImageWidth(); layoutParams.height = (int) imageReceiver.getImageHeight(); videoPlayerContainer.setLayoutParams(layoutParams); } videoTextureView.setScaleX(1f); videoTextureView.setScaleY(1f); } fragmentView.invalidate(); videoPlayerContainer.invalidate(); foundTextureViewMessage = true; break; } } } if (needScroll && videoPlayerContainer != null) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null && messageObject.eventId == 0) { if (!foundTextureViewMessage) { if (checkTextureViewPosition && messageObject.isVideo()) { MediaController.getInstance().cleanupPlayer(true, true); } else { videoPlayerContainer.setTranslationY(-AndroidUtilities.roundPlayingMessageSize - 100); fragmentView.invalidate(); if (messageObject.isRoundVideo() || messageObject.isVideo()) { if (checkTextureViewPosition || PipRoundVideoView.getInstance() != null) { MediaController.getInstance().setCurrentVideoVisible(false); } else { scrollToMessageId(messageObject.getId(), 0, false, 0, true, 0); } } } } else { MediaController.getInstance().setCurrentVideoVisible(true); if (messageObject.isRoundVideo() || scrollToVideo) { // scrollToMessageId(messageObject.getId(), 0, false, 0, true, 0); } else { chatListView.invalidate(); } } } } } public void invalidateMessagesVisiblePart() { invalidateMessagesVisiblePart = true; if (fragmentView != null) { fragmentView.invalidate(); } } private Integer findClosest(ArrayList arrayList, int target, int[] index) { if (arrayList.isEmpty()) { return 0; } Integer val = arrayList.get(0); if (target >= val) { index[0] = 0; return val; } int n = arrayList.size(); val = arrayList.get(n - 1); if (target <= val) { index[0] = n - 1; return val; } int i = 0, j = n, mid = 0; while (i < j) { mid = (i + j) / 2; val = arrayList.get(mid); if (val == target) { index[0] = mid; return val; } if (target < val) { if (mid > 0) { Integer val2 = arrayList.get(mid - 1); if (target > val2) { index[0] = mid - 1; return val2; } } i = mid + 1; } else { if (mid > 0) { Integer val2 = arrayList.get(mid - 1); if (target < val2) { index[0] = mid; return val; } } j = mid; } } index[0] = mid; return arrayList.get(mid); } public void updateMessagesVisiblePart(boolean inLayout) { if (chatListView == null) { return; } int count = chatListView.getChildCount(); int height = chatListView.getMeasuredHeight(); int minPositionHolder = Integer.MAX_VALUE; int minPositionDateHolder = Integer.MAX_VALUE; View minDateChild = null; View minChild = null; View minMessageChild = null; boolean foundTextureViewMessage = false; boolean previousThreadMessageVisible = threadMessageVisible; int previousPinnedMessageId = currentPinnedMessageId; int maxVisibleId = Integer.MIN_VALUE; MessageObject maxVisibleMessageObject = null; threadMessageVisible = firstLoading; Integer currentReadMaxId = null; int threadId = threadMessageId; if (threadId != 0 && currentChat != null) { currentReadMaxId = replyMaxReadId; } else { currentReadMaxId = getMessagesController().dialogs_read_inbox_max.get(dialog_id_Long); } if (currentReadMaxId == null) { currentReadMaxId = 0; } int maxPositiveUnreadId = Integer.MIN_VALUE; int maxNegativeUnreadId = Integer.MAX_VALUE; int maxUnreadDate = Integer.MIN_VALUE; int recyclerChatViewHeight = (contentView.getHeightWithKeyboard() - (inPreviewMode ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop()); pollsToCheck.clear(); float clipTop = chatListViewPaddingTop; long currentTime = System.currentTimeMillis(); int maxAdapterPosition = -1; int minAdapterPosition = -1; boolean blurEnabled = SharedConfig.chatBlurEnabled() && Color.alpha(Theme.getColor(Theme.key_chat_BlurAlpha)) != 255; for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); MessageObject messageObject = null; int adapterPosition = chatListView.getChildAdapterPosition(view); if (adapterPosition >= 0) { if (adapterPosition > maxAdapterPosition || maxAdapterPosition == -1) { maxAdapterPosition = adapterPosition; } if (adapterPosition < minAdapterPosition || minAdapterPosition == -1) { minAdapterPosition = adapterPosition; } } int top = (int) view.getY(); int bottom = top + view.getMeasuredHeight(); ChatMessageCell messageCell = null; if (view instanceof ChatMessageCell) { messageCell = (ChatMessageCell) view; } if (messageCell != null) { messageCell.isBlurred = (top < clipTop && bottom > clipTop) || (bottom > chatListView.getMeasuredHeight() - blurredViewBottomOffset && top < chatListView.getMeasuredHeight() - blurredViewBottomOffset); } if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight() - blurredViewBottomOffset) { if (messageCell != null) { if (!blurEnabled) { messageCell.setVisibleOnScreen(false); } else { messageCell.setVisibleOnScreen(true); } } continue; } if (messageCell != null) { messageCell.setVisibleOnScreen(true); } int viewTop = top >= 0 ? 0 : -top; int viewBottom = view.getMeasuredHeight(); if (viewBottom > height) { viewBottom = viewTop + height; } int keyboardOffset = contentView.getKeyboardHeight(); if (keyboardOffset < AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing() || chatActivityEnterView.panelAnimationInProgress()) { keyboardOffset = chatActivityEnterView.getEmojiPadding(); } if (messageCell != null) { messageObject = messageCell.getMessageObject(); if (messageObject.getDialogId() == dialog_id && messageObject.getId() > maxVisibleId) { maxVisibleId = messageObject.getId(); maxVisibleMessageObject = messageObject; } messageCell.setParentBounds(chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4), chatListView.getMeasuredHeight() - blurredViewBottomOffset); messageCell.setVisiblePart(viewTop, viewBottom - viewTop, recyclerChatViewHeight, keyboardOffset, view.getY() + (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), blurredViewTopOffset, blurredViewBottomOffset); markSponsoredAsRead(messageObject); if (!threadMessageVisible && threadMessageObject != null && messageObject == threadMessageObject && messageCell.getBottom() > chatListViewPaddingTop) { threadMessageVisible = true; } if (videoPlayerContainer != null && (messageObject.isVideo() || messageObject.isRoundVideo()) && MediaController.getInstance().isPlayingMessage(messageObject)) { ImageReceiver imageReceiver = messageCell.getPhotoImage(); if (top + imageReceiver.getImageY2() < 0) { foundTextureViewMessage = false; } else { videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); float translationY = messageCell.getY() + imageReceiver.getImageY() + chatListView.getY() - videoPlayerContainer.getTop(); videoPlayerContainer.setTranslationY(translationY); fragmentView.invalidate(); videoPlayerContainer.invalidate(); foundTextureViewMessage = true; } } if (startFromVideoTimestamp >= 0 && fragmentOpened && !chatListView.isFastScrollAnimationRunning() && startFromVideoMessageId == messageObject.getId() && (messageObject.isVideo() || messageObject.isRoundVideo() || messageObject.isVoice() || messageObject.isMusic())) { messageObject.forceSeekTo = startFromVideoTimestamp / (float) messageObject.getDuration(); MessageObject finalMessage = messageObject; AndroidUtilities.runOnUIThread(() -> { if (finalMessage.isVideo()) { openPhotoViewerForMessage(null, finalMessage); } else { MediaController.getInstance().playMessage(finalMessage); } }, 40); startFromVideoTimestamp = -1; } if (fragmentOpened && openAnimationEnded && (chatListItemAnimator == null || !chatListItemAnimator.isRunning()) && messageCell.checkUnreadReactions(clipTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { reactionsMentionCount--; getMessagesStorage().markMessageReactionsAsRead(getDialogId(), messageCell.getMessageObject().getId(), true); if (reactionsMentionCount <= 0) { getMessagesController().markReactionsAsRead(dialog_id); } if (reactionsMentionCount >= 0) { TLRPC.TL_messagePeerReaction reaction = messageCell.getMessageObject().getRandomUnreadReaction(); if (reaction != null) { ReactionsEffectOverlay.show(ChatActivity.this, null, messageCell, 0, 0, reaction.reaction, currentAccount, reaction.big ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } messageCell.markReactionsAsRead(); } else { reactionsMentionCount = 0; } updateReactionsMentionButton(true); } getDownloadController().checkUnviewedDownloads(messageCell.getId(), dialog_id); boolean allowPlayEffect = ((messageObject.messageOwner.media != null && !messageObject.messageOwner.media.nopremium) || (messageObject.isAnimatedEmojiStickerSingle() && dialog_id > 0)); if ((chatListItemAnimator == null || !chatListItemAnimator.isRunning()) && (!messageObject.isOutOwner() || messageObject.forcePlayEffect) && allowPlayEffect && !messageObject.messageOwner.premiumEffectWasPlayed && (messageObject.isPremiumSticker() || messageObject.isAnimatedEmojiStickerSingle()) && emojiAnimationsOverlay.isIdle() && emojiAnimationsOverlay.checkPosition(messageCell, chatListViewPaddingTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { emojiAnimationsOverlay.onTapItem(messageCell, ChatActivity.this, false); } else if (messageObject.isAnimatedAnimatedEmoji()) { emojiAnimationsOverlay.preloadAnimation(messageCell); } } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) view; messageObject = cell.getMessageObject(); if (messageObject != null && messageObject.getDialogId() == dialog_id && messageObject.getId() > maxVisibleId) { maxVisibleId = Math.max(maxVisibleId, messageObject.getId()); } cell.setVisiblePart(view.getY() + (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY(), contentView.getBackgroundSizeY()); } else if (view instanceof BotHelpCell) { view.invalidate(); } if (chatMode != MODE_SCHEDULED && messageObject != null) { int id = messageObject.getId(); if (!isThreadChat() && (!messageObject.isOut() && messageObject.isUnread() || messageObject.messageOwner.from_scheduled && id > currentReadMaxId) || id > 0 && isThreadChat() && id > currentReadMaxId && id > replyMaxReadId) { if (id > 0) { maxPositiveUnreadId = Math.max(maxPositiveUnreadId, messageObject.getId()); } if (id < 0 && !isThreadChat()) { maxNegativeUnreadId = Math.min(maxNegativeUnreadId, messageObject.getId()); } maxUnreadDate = Math.max(maxUnreadDate, messageObject.messageOwner.date); } if (messageObject.type == MessageObject.TYPE_POLL && messageObject.getId() > 0) { pollsToCheck.add(messageObject); } } if (bottom <= clipTop) { if (view instanceof ChatActionCell && messageObject.isDateObject) { view.setAlpha(0); } continue; } int position = view.getBottom(); if (position < minPositionHolder) { minPositionHolder = position; if (view instanceof ChatMessageCell || view instanceof ChatActionCell) { minMessageChild = view; } minChild = view; } if (chatListItemAnimator == null || (!chatListItemAnimator.willRemoved(view) && !chatListItemAnimator.willAddedFromAlpha(view))) { if (view instanceof ChatActionCell && messageObject.isDateObject) { if (view.getAlpha() != 1.0f) { view.setAlpha(1.0f); } if (position < minPositionDateHolder) { minPositionDateHolder = position; minDateChild = view; } } } } currentPinnedMessageId = 0; if (!pinnedMessageIds.isEmpty()) { if (maxVisibleId == Integer.MIN_VALUE) { if (startLoadFromMessageId != 0) { maxVisibleId = startLoadFromMessageId; } else if (!pinnedMessageIds.isEmpty()) { maxVisibleId = pinnedMessageIds.get(0) + 1; } } else if (maxVisibleId < 0) { int idx = messages.indexOf(maxVisibleMessageObject); if (idx >= 0) { for (int a = idx - 1; a >= 0; a--) { MessageObject object = messages.get(a); if (object.getId() > 0) { maxVisibleId = object.getId(); break; } } if (maxVisibleId < 0) { for (int a = idx + 1, N = messages.size(); a < N; a++) { MessageObject object = messages.get(a); if (object.getId() > 0) { maxVisibleId = object.getId(); break; } } } } } currentPinnedMessageId = findClosest(pinnedMessageIds, forceNextPinnedMessageId != 0 ? forceNextPinnedMessageId : maxVisibleId, currentPinnedMessageIndex); if (!inMenuMode && !loadingPinnedMessagesList && !pinnedEndReached && !pinnedMessageIds.isEmpty() && currentPinnedMessageIndex[0] > pinnedMessageIds.size() - 2) { getMediaDataController().loadPinnedMessages(dialog_id, pinnedMessageIds.get(pinnedMessageIds.size() - 1), 0); loadingPinnedMessagesList = true; } } getMessagesController().addToPollsQueue(dialog_id, pollsToCheck); if (maxAdapterPosition >= 0 && minAdapterPosition >= 0) { int from = minAdapterPosition - chatAdapter.messagesStartRow - 10; int to = maxAdapterPosition - chatAdapter.messagesStartRow + 10; if (from < 0) { from = 0; } if (to > messages.size()) { to = messages.size(); } reactionsToCheck.clear(); for (int i = from; i < to; i++) { MessageObject messageObject = messages.get(i); if (threadMessageObject != messageObject && messageObject.getId() > 0 && messageObject.messageOwner.action == null && (currentTime - messageObject.reactionsLastCheckTime) > 15000L) { messageObject.reactionsLastCheckTime = currentTime; reactionsToCheck.add(messageObject); } } getMessagesController().loadReactionsForMessages(dialog_id, reactionsToCheck); } if (videoPlayerContainer != null) { if (!foundTextureViewMessage) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null) { if (checkTextureViewPosition && messageObject.isVideo()) { MediaController.getInstance().cleanupPlayer(true, true); } else { videoPlayerContainer.setTranslationY(-AndroidUtilities.roundPlayingMessageSize - 100); fragmentView.invalidate(); if ((messageObject.isRoundVideo() || messageObject.isVideo()) && messageObject.eventId == 0 && checkTextureViewPosition && !chatListView.isFastScrollAnimationRunning()) { MediaController.getInstance().setCurrentVideoVisible(false); } } } } else { MediaController.getInstance().setCurrentVideoVisible(true); } } if (minMessageChild != null) { MessageObject messageObject; if (minMessageChild instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) minMessageChild).getMessageObject(); } else { messageObject = ((ChatActionCell) minMessageChild).getMessageObject(); } floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); } currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); if (minDateChild != null) { boolean showFloatingView = false; if (minDateChild.getY() > clipTop || currentFloatingTopIsNotMessage) { if (minDateChild.getAlpha() != 1.0f) { minDateChild.setAlpha(1.0f); } if (chatListView.getChildAdapterPosition(minDateChild) == chatAdapter.messagesStartRow + messages.size() - 1) { if (minDateChild.getAlpha() != 1.0f) { minDateChild.setAlpha(1.0f); } if (floatingDateAnimation != null) { floatingDateAnimation.cancel(); floatingDateAnimation = null; } floatingDateView.setTag(null); floatingDateView.setAlpha(0); currentFloatingDateOnScreen = false; } else { hideFloatingDateView(!currentFloatingTopIsNotMessage); } } else { if (minDateChild.getAlpha() != 0.0f) { minDateChild.setAlpha(0.0f); } showFloatingView = true; } float offset = minDateChild.getY() + minDateChild.getMeasuredHeight() - clipTop; if (offset > floatingDateView.getMeasuredHeight() && offset < floatingDateView.getMeasuredHeight() * 2) { if (chatListView.getChildAdapterPosition(minDateChild) == chatAdapter.messagesStartRow + messages.size() - 1) { showFloatingView = false; if (minDateChild.getAlpha() != 1.0f) { minDateChild.setAlpha(1.0f); } if (floatingDateAnimation != null) { floatingDateAnimation.cancel(); floatingDateAnimation = null; } floatingDateView.setTag(null); floatingDateView.setAlpha(0); } else { floatingDateViewOffset = -floatingDateView.getMeasuredHeight() * 2 + offset; } } else { floatingDateViewOffset = 0; } if (showFloatingView) { if (floatingDateAnimation != null) { floatingDateAnimation.cancel(); floatingDateAnimation = null; } if (floatingDateView.getTag() == null) { floatingDateView.setTag(1); } if (floatingDateView.getAlpha() != 1.0f) { floatingDateView.setAlpha(1.0f); } currentFloatingDateOnScreen = true; } } else { hideFloatingDateView(true); floatingDateViewOffset = 0; } if (isThreadChat()) { if (previousThreadMessageVisible != threadMessageVisible) { updatePinnedMessageView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); } } else { if (currentPinnedMessageId != 0) { MessageObject object = pinnedMessageObjects.get(currentPinnedMessageId); if (object == null) { object = messagesDict[0].get(currentPinnedMessageId); } if (object == null) { if (loadingPinnedMessages.indexOfKey(currentPinnedMessageId) < 0) { loadingPinnedMessages.put(currentPinnedMessageId, true); ArrayList ids = new ArrayList<>(); ids.add(currentPinnedMessageId); getMediaDataController().loadPinnedMessages(dialog_id, ChatObject.isChannel(currentChat) ? currentChat.id : 0, ids, true); } currentPinnedMessageId = previousPinnedMessageId; } } else if (previousPinnedMessageId != 0 && !pinnedMessageIds.isEmpty()) { currentPinnedMessageId = previousPinnedMessageId; } boolean animated = (fromPullingDownTransition && fragmentView.getVisibility() == View.VISIBLE) || (openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); if (previousPinnedMessageId != currentPinnedMessageId) { int animateToNext; if (previousPinnedMessageId == 0) { animateToNext = 0; } else if (previousPinnedMessageId > currentPinnedMessageId) { animateToNext = 1; } else { animateToNext = 2; } updatePinnedMessageView(animated, animateToNext); } else { updatePinnedListButton(animated); } } if (floatingDateView != null) { floatingDateView.setTranslationY(chatListView.getTranslationY() + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4)); } invalidateChatListViewTopPadding(); if (!firstLoading && !paused && !inPreviewMode && chatMode == 0 && !getMessagesController().ignoreSetOnline) { int scheduledRead = 0; if ((maxPositiveUnreadId != Integer.MIN_VALUE || maxNegativeUnreadId != Integer.MAX_VALUE)) { int counterDecrement = 0; for (int a = 0; a < messages.size(); a++) { MessageObject messageObject = messages.get(a); int id = messageObject.getId(); if (maxPositiveUnreadId != Integer.MIN_VALUE) { if (id > 0 && id <= maxPositiveUnreadId && (messageObject.messageOwner.from_scheduled && id > currentReadMaxId || messageObject.isUnread() && !messageObject.isOut())) { if (messageObject.messageOwner.from_scheduled) { scheduledRead++; } else { messageObject.setIsRead(); } counterDecrement++; } } if (maxNegativeUnreadId != Integer.MAX_VALUE) { if (id < 0 && id >= maxNegativeUnreadId && messageObject.isUnread()) { messageObject.setIsRead(); counterDecrement++; } } } if (forwardEndReached[0] && maxPositiveUnreadId == minMessageId[0] || maxNegativeUnreadId == minMessageId[0]) { newUnreadMessageCount = 0; } else { newUnreadMessageCount -= counterDecrement; if (newUnreadMessageCount < 0) { newUnreadMessageCount = 0; } } if (inLayout) { AndroidUtilities.runOnUIThread(this::inlineUpdate1); } else { inlineUpdate1(); } getMessagesController().markDialogAsRead(dialog_id, maxPositiveUnreadId, maxNegativeUnreadId, maxUnreadDate, false, threadId, counterDecrement, maxPositiveUnreadId == minMessageId[0] || maxNegativeUnreadId == minMessageId[0], scheduledRead); firstUnreadSent = true; } else if (!firstUnreadSent && currentEncryptedChat == null) { if (chatLayoutManager.findFirstVisibleItemPosition() == 0) { newUnreadMessageCount = 0; if (inLayout) { AndroidUtilities.runOnUIThread(this::inlineUpdate2); } else { inlineUpdate2(); } getMessagesController().markDialogAsRead(dialog_id, minMessageId[0], minMessageId[0], maxDate[0], false, threadId, 0, true, scheduledRead); firstUnreadSent = true; } } if (threadId != 0 && maxPositiveUnreadId > 0 && replyMaxReadId != maxPositiveUnreadId) { replyMaxReadId = maxPositiveUnreadId; getMessagesStorage().updateRepliesMaxReadId(replyOriginalChat.id, replyOriginalMessageId, replyMaxReadId, true); getNotificationCenter().postNotificationName(NotificationCenter.commentsRead, replyOriginalChat.id, replyOriginalMessageId, replyMaxReadId); } } } private void inlineUpdate1() { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; pagedownButtonCounter.setCount(newUnreadMessageCount, openAnimationEnded); } } private void inlineUpdate2() { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; pagedownButtonCounter.setCount(newUnreadMessageCount, true); } } private void toggleMute(boolean instant) { boolean muted = getMessagesController().isDialogMuted(dialog_id); if (!muted) { if (instant) { getNotificationsController().muteDialog(dialog_id, true); } else { BottomSheet alert = AlertsCreator.createMuteAlert(this, dialog_id, themeDelegate); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } } else { getNotificationsController().muteDialog(dialog_id, false); if (!instant) { BulletinFactory.createMuteBulletin(this, false, themeDelegate).show(); } } } private int getScrollOffsetForMessage(MessageObject object) { return getScrollOffsetForMessage(getHeightForMessage(object)); } private int getScrollOffsetForMessage(int messageHeight) { return (int) Math.max(-AndroidUtilities.dp(2), (chatListView.getMeasuredHeight() - blurredViewBottomOffset - chatListViewPaddingTop - messageHeight) / 2); } private int getHeightForMessage(MessageObject object) { if (dummyMessageCell == null) { dummyMessageCell = new ChatMessageCell(getParentActivity(), true, themeDelegate); } dummyMessageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser); dummyMessageCell.isBot = currentUser != null && currentUser.bot; dummyMessageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; return dummyMessageCell.computeHeight(object, groupedMessagesMap.get(object.getGroupId())); } private void startMessageUnselect() { if (unselectRunnable != null) { AndroidUtilities.cancelRunOnUIThread(unselectRunnable); } unselectRunnable = () -> { highlightMessageId = Integer.MAX_VALUE; updateVisibleRows(); unselectRunnable = null; }; AndroidUtilities.runOnUIThread(unselectRunnable, 1000); } private void removeSelectedMessageHighlight() { if (unselectRunnable != null) { AndroidUtilities.cancelRunOnUIThread(unselectRunnable); unselectRunnable = null; } highlightMessageId = Integer.MAX_VALUE; } private AlertDialog progressDialog; private int nextScrollToMessageId; private int nextScrollFromMessageId; private boolean nextScrollSelect; private int nextScrollLoadIndex; private boolean nextScrollForce; private int nextScrollForcePinnedMessageId; private boolean pinnedProgressIsShowing; Runnable updatePinnedProgressRunnable; public void scrollToMessageId(int id, int fromMessageId, boolean select, int loadIndex, boolean forceScroll, int forcePinnedMessageId) { if (id == 0 || NotificationCenter.getInstance(currentAccount).isAnimationInProgress() || getParentActivity() == null) { if (NotificationCenter.getInstance(currentAccount).isAnimationInProgress()) { nextScrollToMessageId = id; nextScrollFromMessageId = fromMessageId; nextScrollSelect = select; nextScrollLoadIndex = loadIndex; nextScrollForce = forceScroll; nextScrollForcePinnedMessageId = forcePinnedMessageId; NotificationCenter.getInstance(currentAccount).doOnIdle(() -> { if (nextScrollToMessageId != 0) { scrollToMessageId(nextScrollToMessageId, nextScrollFromMessageId, nextScrollSelect, nextScrollLoadIndex, nextScrollForce, nextScrollForcePinnedMessageId); nextScrollToMessageId = 0; } }); } return; } forceNextPinnedMessageId = Math.abs(forcePinnedMessageId); forceScrollToFirst = forcePinnedMessageId > 0; wasManualScroll = true; MessageObject object = messagesDict[loadIndex].get(id); boolean query = false; int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; int scrollFromIndex = 0; if (fromMessageId != 0) { boolean scrollDown = fromMessageId < id; if (isSecretChat()) { scrollDown = !scrollDown; } scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else if (messages.size() > 0) { if (isThreadChat() && id == threadMessageId) { scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else { int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { MessageObject messageObject = messages.get(i - chatAdapter.messagesStartRow); if (messageObject.getId() == 0) { continue; } scrollFromIndex = i - chatAdapter.messagesStartRow; boolean scrollDown = messageObject.getId() < id; if (isSecretChat()) { scrollDown = !scrollDown; } scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; break; } } } } chatScrollHelper.setScrollDirection(scrollDirection); if (object != null) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(object.getGroupId()); if (object.getGroupId() != 0 && groupedMessages != null) { MessageObject primary = groupedMessages.findPrimaryMessageObject(); if (primary != null) { object = primary; } } int index = messages.indexOf(object); if (index != -1) { if (scrollFromIndex > 0) { scrollDirection = scrollFromIndex > index ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; chatScrollHelper.setScrollDirection(scrollDirection); } removeSelectedMessageHighlight(); if (select) { highlightMessageId = id; } chatAdapter.updateRowsSafe(); int position = chatAdapter.messagesStartRow + messages.indexOf(object); updateVisibleRows(); boolean found = false; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject messageObject = cell.getMessageObject(); if (messageObject != null && messageObject.getId() == object.getId()) { found = true; view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) view; MessageObject messageObject = cell.getMessageObject(); if (messageObject != null && messageObject.getId() == object.getId()) { found = true; view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } } if (found) { int yOffset = getScrollOffsetForMessage(view.getHeight()); int scrollY = (int) (view.getTop() - chatListViewPaddingTop - yOffset); int maxScrollOffset = chatListView.computeVerticalScrollRange() - chatListView.computeVerticalScrollOffset() - chatListView.computeVerticalScrollExtent(); if (maxScrollOffset < 0) { maxScrollOffset = 0; } if (scrollY > maxScrollOffset) { scrollY = maxScrollOffset; } if (scrollY != 0) { scrollByTouch = false; chatListView.smoothScrollBy(0, scrollY); chatListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); } break; } } if (!found) { int yOffset = getScrollOffsetForMessage(object); chatScrollHelperCallback.scrollTo = object; chatScrollHelperCallback.lastBottom = false; chatScrollHelperCallback.lastItemOffset = yOffset; chatScrollHelperCallback.lastPadding = (int) chatListViewPaddingTop; chatScrollHelper.setScrollDirection(scrollDirection); chatScrollHelper.scrollToPosition(position, yOffset, false, true); canShowPagedownButton = true; updatePagedownButtonVisibility(true); } } else { query = true; } } else { query = true; } if (query) { if (isThreadChat() && id == threadMessageId) { scrollToThreadMessage = true; id = 1; } if (progressDialog != null) { progressDialog.dismiss(); } showPinnedProgress(forceNextPinnedMessageId != 0); progressDialog = new AlertDialog(getParentActivity(), 3, themeDelegate); progressDialog.setOnShowListener(dialogInterface -> showPinnedProgress(false)); progressDialog.setOnCancelListener(postponedScrollCancelListener); progressDialog.showDelayed(400); waitingForLoad.clear(); removeSelectedMessageHighlight(); scrollToMessagePosition = -10000; startLoadFromMessageId = id; showScrollToMessageError = !forceScroll; if (id == createUnreadMessageAfterId) { createUnreadMessageAfterIdLoading = true; } postponedScrollIsCanceled = false; waitingForLoad.add(lastLoadIndex); postponedScrollToLastMessageQueryIndex = lastLoadIndex; postponedScrollMinMessageId = minMessageId[0]; postponedScrollMessageId = id; getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, isThreadChat() || AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } else { View child = chatListView.getChildAt(0); if (child != null && child.getTop() <= 0) { showFloatingDateView(false); } } returnToMessageId = fromMessageId; returnToLoadIndex = loadIndex; needSelectFromMessageId = select; } private void showPinnedProgress(boolean show) { if (show) { if (updatePinnedProgressRunnable == null) { updatePinnedProgressRunnable = () -> { pinnedProgressIsShowing = true; updatePinnedListButton(true); }; AndroidUtilities.runOnUIThread(updatePinnedProgressRunnable, 100); } } else { if (updatePinnedProgressRunnable != null) { AndroidUtilities.cancelRunOnUIThread(updatePinnedProgressRunnable); } updatePinnedProgressRunnable = null; pinnedProgressIsShowing = false; updatePinnedListButton(true); } } private void updatePagedownButtonVisibility(boolean animated) { if (pagedownButton == null) { return; } boolean show = canShowPagedownButton && !textSelectionHelper.isSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo(); if (show) { if (animated && (openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150)) { animated = false; } pagedownButtonShowedByScroll = false; if (pagedownButton.getTag() == null) { if (pagedownButtonAnimation != null) { pagedownButtonAnimation.removeAllListeners(); pagedownButtonAnimation.cancel(); pagedownButtonAnimation = null; } pagedownButton.setTag(1); if (animated) { pagedownButton.setVisibility(View.VISIBLE); pagedownButtonAnimation = ValueAnimator.ofFloat(pagedownButtonEnterProgress, 1f); pagedownButtonAnimation.addUpdateListener(valueAnimator -> { pagedownButtonEnterProgress = (float) valueAnimator.getAnimatedValue(); contentView.invalidate(); }); pagedownButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { pagedownButtonEnterProgress = 1f; contentView.invalidate(); } }); pagedownButtonAnimation.setDuration(200); pagedownButtonAnimation.start(); } else { pagedownButtonEnterProgress = 1f; contentView.invalidate(); pagedownButton.setVisibility(View.VISIBLE); } } } else { returnToMessageId = 0; newUnreadMessageCount = 0; if (pagedownButton.getTag() != null) { pagedownButton.setTag(null); if (pagedownButtonAnimation != null) { pagedownButtonAnimation.removeAllListeners(); pagedownButtonAnimation.cancel(); pagedownButtonAnimation = null; } if (animated) { pagedownButton.setVisibility(View.VISIBLE); pagedownButtonAnimation = ValueAnimator.ofFloat(pagedownButtonEnterProgress, 0); pagedownButtonAnimation.addUpdateListener(valueAnimator -> { pagedownButtonEnterProgress = (float) valueAnimator.getAnimatedValue(); contentView.invalidate(); }); pagedownButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { pagedownButtonEnterProgress = 0; pagedownButton.setVisibility(View.INVISIBLE); contentView.invalidate(); } }); pagedownButtonAnimation.setDuration(200); pagedownButtonAnimation.start(); } else { pagedownButtonEnterProgress = 0; pagedownButton.setVisibility(View.INVISIBLE); } } } } private void showMentionDownButton(boolean show, boolean animated) { if (mentiondownButton == null) { return; } if (show) { if (mentiondownButton.getTag() == null) { if (mentiondownButtonAnimation != null) { mentiondownButtonAnimation.removeAllListeners(); mentiondownButtonAnimation.cancel(); mentiondownButtonAnimation = null; } if (animated) { mentiondownButton.setVisibility(View.VISIBLE); mentiondownButton.setTag(1); mentiondownButtonAnimation = ValueAnimator.ofFloat(mentionsButtonEnterProgress, 1f); mentiondownButtonAnimation.addUpdateListener(valueAnimator -> { mentionsButtonEnterProgress = (float) valueAnimator.getAnimatedValue(); contentView.invalidate(); }); mentiondownButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mentionsButtonEnterProgress = 1f; contentView.invalidate(); } }); mentiondownButtonAnimation.setDuration(200); mentiondownButtonAnimation.start(); } else { mentionsButtonEnterProgress = 1f; contentView.invalidate(); } } } else { returnToMessageId = 0; if (mentiondownButton.getTag() != null) { mentiondownButton.setTag(null); if (mentiondownButtonAnimation != null) { mentiondownButtonAnimation.removeAllListeners(); mentiondownButtonAnimation.cancel(); mentiondownButtonAnimation = null; } if (animated) { mentiondownButtonAnimation = ValueAnimator.ofFloat(mentionsButtonEnterProgress, 0f); mentiondownButtonAnimation.addUpdateListener(valueAnimator -> { mentionsButtonEnterProgress = (float) valueAnimator.getAnimatedValue(); contentView.invalidate(); }); mentiondownButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mentionsButtonEnterProgress = 0f; mentiondownButton.setVisibility(View.INVISIBLE); contentView.invalidate(); } }); mentiondownButtonAnimation.setDuration(200); mentiondownButtonAnimation.start(); } else { mentionsButtonEnterProgress = 0f; mentiondownButton.setVisibility(View.INVISIBLE); } } } } private void updateSecretStatus() { if (bottomOverlay == null) { return; } boolean hideKeyboard = false; if (currentChat != null && !ChatObject.canSendMessages(currentChat) && !currentChat.gigagroup && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) { if (currentChat.default_banned_rights != null && currentChat.default_banned_rights.send_messages) { bottomOverlayText.setText(LocaleController.getString("GlobalSendMessageRestricted", R.string.GlobalSendMessageRestricted)); } else if (AndroidUtilities.isBannedForever(currentChat.banned_rights)) { bottomOverlayText.setText(LocaleController.getString("SendMessageRestrictedForever", R.string.SendMessageRestrictedForever)); } else { bottomOverlayText.setText(LocaleController.formatString("SendMessageRestricted", R.string.SendMessageRestricted, LocaleController.formatDateForBan(currentChat.banned_rights.until_date))); } bottomOverlay.setVisibility(View.VISIBLE); if (mentionListAnimation != null) { mentionListAnimation.cancel(); mentionListAnimation = null; } mentionContainer.setVisibility(View.GONE); mentionContainer.setTag(null); updateMessageListAccessibilityVisibility(); hideKeyboard = true; if (suggestEmojiPanel != null) { suggestEmojiPanel.forceClose(); } } else { if (currentEncryptedChat == null || bigEmptyView == null) { bottomOverlay.setVisibility(View.INVISIBLE); if (suggestEmojiPanel != null && chatActivityEnterView != null && chatActivityEnterView.hasText()) { suggestEmojiPanel.fireUpdate(); } return; } if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatRequested) { bottomOverlayText.setText(LocaleController.getString("EncryptionProcessing", R.string.EncryptionProcessing)); bottomOverlay.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); hideKeyboard = true; } else if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatWaiting) { bottomOverlayText.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AwaitingEncryption", R.string.AwaitingEncryption, "" + currentUser.first_name + ""))); bottomOverlay.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); hideKeyboard = true; } else if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatDiscarded) { bottomOverlayText.setText(LocaleController.getString("EncryptionRejected", R.string.EncryptionRejected)); bottomOverlay.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); chatActivityEnterView.setFieldText(""); getMediaDataController().cleanDraft(dialog_id, threadMessageId, false); hideKeyboard = true; } else if (currentEncryptedChat instanceof TLRPC.TL_encryptedChat) { bottomOverlay.setVisibility(View.INVISIBLE); if (!inPreviewMode) { chatActivityEnterView.setVisibility(View.VISIBLE); } } checkRaiseSensors(); checkActionBarMenu(false); } if (inPreviewMode) { bottomOverlay.setVisibility(View.INVISIBLE); } if (hideKeyboard) { chatActivityEnterView.hidePopup(false); if (getParentActivity() != null) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } } } @Override public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { if (chatActivityEnterView != null) { chatActivityEnterView.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } if (requestCode == BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE && chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().checkStorage(); } else if ((requestCode == BasePermissionsActivity.REQUEST_CODE_ATTACH_CONTACT || requestCode == 30) && chatAttachAlert != null) { chatAttachAlert.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } else if ((requestCode == 17 || requestCode == 18) && chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().checkCamera(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED); chatAttachAlert.getPhotoLayout().checkStorage(); } else if (requestCode == 21) { if (getParentActivity() == null) { return; } if (grantResults != null && grantResults.length != 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("PermissionNoAudioVideoWithHint", R.string.PermissionNoAudioVideoWithHint)); builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), (dialog, which) -> { try { Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + ApplicationLoader.applicationContext.getPackageName())); getParentActivity().startActivity(intent); } catch (Exception e) { FileLog.e(e); } }); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.show(); } } else if (requestCode == 19 && grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { processSelectedAttach(attach_photo); } else if (requestCode == BasePermissionsActivity.REQUEST_CODE_OPEN_CAMERA && grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { processSelectedAttach(attach_video); } else if ((requestCode == 101 || requestCode == 102) && currentUser != null || requestCode == 103 && currentChat != null) { boolean allGranted = true; for (int a = 0; a < grantResults.length; a++) { if (grantResults[a] != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (grantResults.length > 0 && allGranted) { if (requestCode == 103) { VoIPHelper.startCall(currentChat, null, null, createGroupCall, getParentActivity(), ChatActivity.this, getAccountInstance()); } else { VoIPHelper.startCall(currentUser, requestCode == 102, userInfo != null && userInfo.video_calls_available, getParentActivity(), getMessagesController().getUserFull(currentUser.id), getAccountInstance()); } } else { VoIPHelper.permissionDenied(getParentActivity(), null, requestCode); } } } private void checkActionBarMenu(boolean animated) { if (currentEncryptedChat != null && !(currentEncryptedChat instanceof TLRPC.TL_encryptedChat) || currentChat != null && (chatMode != 0 || threadMessageId != 0 || chatInfo == null || chatInfo.ttl_period == 0) || currentUser != null && (UserObject.isDeleted(currentUser) || currentEncryptedChat == null && (userInfo == null || userInfo.ttl_period == 0))) { if (timeItem2 != null) { timeItem2.setVisibility(View.GONE); } if (avatarContainer != null) { avatarContainer.hideTimeItem(animated); } } else { if (timeItem2 != null) { timeItem2.setVisibility(View.VISIBLE); } if (avatarContainer != null) { avatarContainer.showTimeItem(animated); } } if (avatarContainer != null) { if (currentEncryptedChat != null) { avatarContainer.setTime(currentEncryptedChat.ttl, animated); } else if (userInfo != null) { avatarContainer.setTime(userInfo.ttl_period, animated); } else if (chatInfo != null) { avatarContainer.setTime(chatInfo.ttl_period, animated); } } if (clearHistoryItem != null && chatInfo != null) { boolean visible = chatInfo.can_delete_channel || !ChatObject.isChannel(currentChat) || currentChat.megagroup && TextUtils.isEmpty(currentChat.username); clearHistoryItem.setVisibility(visible ? View.VISIBLE : View.GONE); } checkAndUpdateAvatar(); } private int getMessageType(MessageObject messageObject) { if (messageObject == null) { return -1; } if (currentEncryptedChat == null) { if (messageObject.isEditing()) { return -1; } else if (messageObject.getId() <= 0 && messageObject.isOut()) { if (messageObject.isSendError()) { if (!messageObject.isMediaEmpty()) { return 0; } else { return 20; } } else { return -1; } } else { if (messageObject.isAnimatedEmoji()) { return 2; } else if (messageObject.type == 6) { return -1; } else if (messageObject.type == 10 || messageObject.type == 11) { if (messageObject.getId() == 0) { return -1; } return 1; } else { if (messageObject.isVoice()) { return 2; } else if (messageObject.isSticker() || messageObject.isAnimatedSticker()) { TLRPC.InputStickerSet inputStickerSet = messageObject.getInputStickerSet(); if (inputStickerSet instanceof TLRPC.TL_inputStickerSetID) { if (!getMediaDataController().isStickerPackInstalled(inputStickerSet.id)) { return 7; } } else if (inputStickerSet instanceof TLRPC.TL_inputStickerSetShortName) { if (!getMediaDataController().isStickerPackInstalled(inputStickerSet.short_name)) { return 7; } } return 9; } else if (!messageObject.isRoundVideo() && (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto || messageObject.getDocument() != null || messageObject.isMusic() || messageObject.isVideo())) { boolean canSave = false; if (!TextUtils.isEmpty(messageObject.messageOwner.attachPath)) { File f = new File(messageObject.messageOwner.attachPath); if (f.exists()) { canSave = true; } } if (!canSave) { if (messageObject.mediaExists) { canSave = true; } } if (canSave) { if (messageObject.getDocument() != null && !messageObject.isMusic()) { String mime = messageObject.getDocument().mime_type; if (mime != null) { if (messageObject.getDocumentName().toLowerCase().endsWith("attheme")) { return 10; } else if (mime.endsWith("/xml")) { return 5; } else if (!messageObject.isNewGif() && mime.endsWith("/mp4") || mime.endsWith("/png") || mime.endsWith("/jpg") || mime.endsWith("/jpeg")) { return 6; } } } return 4; } } else if (messageObject.type == 12) { return 8; } else if (messageObject.isMediaEmpty()) { return 3; } return 2; } } } else { if (messageObject.isSending()) { return -1; } if (messageObject.isAnimatedEmoji()) { return 2; } else if (messageObject.type == 6) { return -1; } else if (messageObject.isSendError()) { if (!messageObject.isMediaEmpty()) { return 0; } else { return 20; } } else if (messageObject.type == 10 || messageObject.type == 11) { if (messageObject.getId() == 0 || messageObject.isSending()) { return -1; } else { return 1; } } else { if (messageObject.isVoice()) { return 2; } else if (!messageObject.isAnimatedEmoji() && (messageObject.isSticker() || messageObject.isAnimatedSticker())) { TLRPC.InputStickerSet inputStickerSet = messageObject.getInputStickerSet(); if (inputStickerSet instanceof TLRPC.TL_inputStickerSetShortName) { if (!getMediaDataController().isStickerPackInstalled(inputStickerSet.short_name)) { return 7; } } } else if (!messageObject.isRoundVideo() && (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto || messageObject.getDocument() != null || messageObject.isMusic() || messageObject.isVideo())) { boolean canSave = false; if (!TextUtils.isEmpty(messageObject.messageOwner.attachPath)) { File f = new File(messageObject.messageOwner.attachPath); if (f.exists()) { canSave = true; } } if (!canSave) { File f = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner); if (f.exists()) { canSave = true; } } if (canSave) { if (messageObject.getDocument() != null) { String mime = messageObject.getDocument().mime_type; if (mime != null && mime.endsWith("text/xml")) { return 5; } } if (messageObject.messageOwner.ttl <= 0) { return 4; } } } else if (messageObject.type == 12) { return 8; } else if (messageObject.isMediaEmpty()) { return 3; } return 2; } } } private void addToSelectedMessages(MessageObject messageObject, boolean outside) { addToSelectedMessages(messageObject, outside, true); } private void addToSelectedMessages(MessageObject messageObject, boolean outside, boolean last) { int prevCantForwardCount = cantForwardMessagesCount; if (messageObject != null) { if (threadMessageObjects != null && threadMessageObjects.contains(messageObject)) { return; } int index = messageObject.getDialogId() == dialog_id ? 0 : 1; if (outside && messageObject.getGroupId() != 0) { boolean hasUnselected = false; MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); if (groupedMessages != null) { int lastNum = 0; for (int a = 0; a < groupedMessages.messages.size(); a++) { MessageObject message = groupedMessages.messages.get(a); if (selectedMessagesIds[index].indexOfKey(message.getId()) < 0) { hasUnselected = true; lastNum = a; } } for (int a = 0; a < groupedMessages.messages.size(); a++) { MessageObject message = groupedMessages.messages.get(a); if (hasUnselected) { if (selectedMessagesIds[index].indexOfKey(message.getId()) < 0) { addToSelectedMessages(message, false, a == lastNum); } } else { addToSelectedMessages(message, false, a == groupedMessages.messages.size() - 1); } if (!TextUtils.isEmpty(message.caption)) { showTextSelectionHint(messageObject); } } } return; } if (selectedMessagesIds[index].indexOfKey(messageObject.getId()) >= 0) { selectedMessagesIds[index].remove(messageObject.getId()); if (reportType < 0) { if ((messageObject.type == 0 || messageObject.isAnimatedEmoji() || messageObject.caption != null) && !(messageObject.messageOwner != null && messageObject.messageOwner.noforwards)) { selectedMessagesCanCopyIds[index].remove(messageObject.getId()); } if (!messageObject.isAnimatedEmoji() && (messageObject.isSticker() || messageObject.isAnimatedSticker()) && MessageObject.isStickerHasSet(messageObject.getDocument())) { selectedMessagesCanStarIds[index].remove(messageObject.getId()); } if (messageObject.canEditMessage(currentChat)) { canEditMessagesCount--; } if (!messageObject.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat)) { cantDeleteMessagesCount--; } boolean noforwards = getMessagesController().isChatNoForwards(currentChat); if (chatMode == MODE_SCHEDULED || !messageObject.canForwardMessage() || noforwards) { cantForwardMessagesCount--; } else { canForwardMessagesCount--; } if (messageObject.isMusic() && !noforwards) { canSaveMusicCount--; } else if (messageObject.isDocument() && !noforwards) { canSaveDocumentsCount--; } else { cantSaveMessagesCount--; } } } else { if (selectedMessagesIds[0].size() + selectedMessagesIds[1].size() >= 100) { AndroidUtilities.shakeView(selectedMessagesCountTextView, 2, 0); Vibrator vibrator = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null) { vibrator.vibrate(200); } return; } selectedMessagesIds[index].put(messageObject.getId(), messageObject); if (reportType < 0) { if ((messageObject.type == 0 || messageObject.isAnimatedEmoji() || messageObject.caption != null) && !(messageObject.messageOwner != null && messageObject.messageOwner.noforwards)) { selectedMessagesCanCopyIds[index].put(messageObject.getId(), messageObject); } if (!messageObject.isAnimatedEmoji() && (messageObject.isSticker() || messageObject.isAnimatedSticker()) && MessageObject.isStickerHasSet(messageObject.getDocument())) { selectedMessagesCanStarIds[index].put(messageObject.getId(), messageObject); } if (messageObject.canEditMessage(currentChat)) { canEditMessagesCount++; } if (!messageObject.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat)) { cantDeleteMessagesCount++; } boolean noforwards = getMessagesController().isChatNoForwards(currentChat); if (chatMode == MODE_SCHEDULED || !messageObject.canForwardMessage() || noforwards) { cantForwardMessagesCount++; } else { canForwardMessagesCount++; } if (messageObject.isMusic() && !noforwards) { canSaveMusicCount++; } else if (messageObject.isDocument() && !noforwards) { canSaveDocumentsCount++; } else { cantSaveMessagesCount++; } if (outside) { showTextSelectionHint(messageObject); } } } } if (forwardButtonAnimation != null) { forwardButtonAnimation.cancel(); forwardButtonAnimation = null; } if (last && actionBar.isActionModeShowed() && reportType < 0) { int selectedCount = selectedMessagesIds[0].size() + selectedMessagesIds[1].size(); if (selectedCount == 0) { hideActionMode(); updatePinnedMessageView(true); } else { ActionBarMenuItem saveItem = actionBar.createActionMode().getItem(save_to); ActionBarMenuItem copyItem = actionBar.createActionMode().getItem(copy); ActionBarMenuItem starItem = actionBar.createActionMode().getItem(star); ActionBarMenuItem editItem = actionBar.createActionMode().getItem(edit); ActionBarMenuItem forwardItem = actionBar.createActionMode().getItem(forward); boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || hasSelectedNoforwardsMessage(); if (prevCantForwardCount == 0 && cantForwardMessagesCount != 0 || prevCantForwardCount != 0 && cantForwardMessagesCount == 0) { forwardButtonAnimation = new AnimatorSet(); ArrayList animators = new ArrayList<>(); if (forwardItem != null) { forwardItem.setEnabled(cantForwardMessagesCount == 0 || noforwards); animators.add(ObjectAnimator.ofFloat(forwardItem, View.ALPHA, cantForwardMessagesCount == 0 ? 1.0f : 0.5f)); if (noforwards && forwardItem.getBackground() != null) { forwardItem.setBackground(null); } else if (forwardItem.getBackground() == null) { forwardItem.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 5)); } } if (forwardButton != null) { forwardButton.setEnabled(cantForwardMessagesCount == 0 || noforwards); if (noforwards && forwardButton.getBackground() != null) { forwardButton.setBackground(null); } else if (forwardButton.getBackground() == null) { forwardButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 3)); } animators.add(ObjectAnimator.ofFloat(forwardButton, View.ALPHA, cantForwardMessagesCount == 0 ? 1.0f : 0.5f)); } forwardButtonAnimation.playTogether(animators); forwardButtonAnimation.setDuration(100); forwardButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { forwardButtonAnimation = null; } }); forwardButtonAnimation.start(); } else { if (forwardItem != null) { forwardItem.setEnabled(cantForwardMessagesCount == 0 || noforwards); forwardItem.setAlpha(cantForwardMessagesCount == 0 ? 1.0f : 0.5f); if (noforwards) { if (forwardItem.getBackground() != null) forwardButton.setBackground(null); } else if (forwardItem.getBackground() == null) { forwardItem.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 3)); } } if (forwardButton != null) { forwardButton.setEnabled(cantForwardMessagesCount == 0 || noforwards); if (noforwards) { if (forwardButton.getBackground() != null) forwardButton.setBackground(null); } else if (forwardButton.getBackground() == null) { forwardButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 3)); } forwardButton.setAlpha(cantForwardMessagesCount == 0 ? 1.0f : 0.5f); } } if (saveItem != null) { saveItem.setVisibility(((canSaveMusicCount > 0 && canSaveDocumentsCount == 0) || (canSaveMusicCount == 0 && canSaveDocumentsCount > 0)) && cantSaveMessagesCount == 0 ? View.VISIBLE : View.GONE); saveItem.setContentDescription(canSaveMusicCount > 0 ? LocaleController.getString("SaveToMusic", R.string.SaveToMusic) : LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); } int copyVisible = copyItem.getVisibility(); int starVisible = starItem.getVisibility(); copyItem.setVisibility(!noforwards && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); starItem.setVisibility(getMediaDataController().canAddStickerToFavorites() && (selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size()) == selectedCount ? View.VISIBLE : View.GONE); int newCopyVisible = copyItem.getVisibility(); int newStarVisible = starItem.getVisibility(); actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); hasUnfavedSelected = false; for (int a = 0; a < 2; a++) { for (int b = 0; b < selectedMessagesCanStarIds[a].size(); b++) { MessageObject msg = selectedMessagesCanStarIds[a].valueAt(b); if (!getMediaDataController().isStickerInFavorites(msg.getDocument())) { hasUnfavedSelected = true; break; } } if (hasUnfavedSelected) { break; } } starItem.setIcon(hasUnfavedSelected ? R.drawable.msg_fave : R.drawable.msg_unfave); final int newEditVisibility = canEditMessagesCount == 1 && selectedCount == 1 ? View.VISIBLE : View.GONE; if (replyButton != null) { boolean allowChatActions = true; if (bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { allowChatActions = false; } int newVisibility; if (chatMode == MODE_SCHEDULED || !allowChatActions || selectedMessagesIds[0].size() != 0 && selectedMessagesIds[1].size() != 0) { newVisibility = View.GONE; } else if (selectedCount == 1) { newVisibility = View.VISIBLE; } else { newVisibility = View.VISIBLE; long lastGroupId = 0; for (int a = 0; a < 2; a++) { for (int b = 0, N = selectedMessagesIds[a].size(); b < N; b++) { MessageObject message = selectedMessagesIds[a].valueAt(b); long groupId = message.getGroupId(); if (groupId == 0 || lastGroupId != 0 && lastGroupId != groupId) { newVisibility = View.GONE; break; } lastGroupId = groupId; } if (newVisibility == View.GONE) { break; } } } if (threadMessageObjects != null && newVisibility == View.VISIBLE) { for (int b = 0, N = selectedMessagesIds[0].size(); b < N; b++) { MessageObject message = selectedMessagesIds[0].valueAt(b); if (threadMessageObjects.contains(message)) { newVisibility = View.GONE; } } } if (replyButton.getVisibility() != newVisibility) { if (replyButtonAnimation != null) { replyButtonAnimation.cancel(); } replyButtonAnimation = new AnimatorSet(); if (newVisibility == View.VISIBLE) { replyButton.setVisibility(newVisibility); replyButtonAnimation.playTogether( ObjectAnimator.ofFloat(replyButton, View.ALPHA, 1.0f), ObjectAnimator.ofFloat(replyButton, View.SCALE_Y, 1.0f) ); } else { replyButtonAnimation.playTogether( ObjectAnimator.ofFloat(replyButton, View.ALPHA, 0.0f), ObjectAnimator.ofFloat(replyButton, View.SCALE_Y, 0.0f) ); } replyButtonAnimation.setDuration(100); int newVisibilityFinal = newVisibility; replyButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (replyButtonAnimation != null && replyButtonAnimation.equals(animation)) { if (newVisibilityFinal == View.GONE) { replyButton.setVisibility(View.GONE); } } } @Override public void onAnimationCancel(Animator animation) { if (replyButtonAnimation != null && replyButtonAnimation.equals(animation)) { replyButtonAnimation = null; } } }); replyButtonAnimation.start(); } } if (editItem != null) { if (copyVisible != newCopyVisible || starVisible != newStarVisible) { if (newEditVisibility == View.VISIBLE) { editItem.setAlpha(1.0f); editItem.setScaleX(1.0f); } else { editItem.setAlpha(0.0f); editItem.setScaleX(0.0f); } editItem.setVisibility(newEditVisibility); } else if (editItem.getVisibility() != newEditVisibility) { if (editButtonAnimation != null) { editButtonAnimation.cancel(); } editButtonAnimation = new AnimatorSet(); editItem.setPivotX(AndroidUtilities.dp(54)); editItem.setPivotX(AndroidUtilities.dp(54)); if (newEditVisibility == View.VISIBLE) { editItem.setVisibility(newEditVisibility); editButtonAnimation.playTogether( ObjectAnimator.ofFloat(editItem, View.ALPHA, 1.0f), ObjectAnimator.ofFloat(editItem, View.SCALE_X, 1.0f) ); } else { editButtonAnimation.playTogether( ObjectAnimator.ofFloat(editItem, View.ALPHA, 0.0f), ObjectAnimator.ofFloat(editItem, View.SCALE_X, 0.0f) ); } editButtonAnimation.setDuration(100); editButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (editButtonAnimation != null && editButtonAnimation.equals(animation)) { if (newEditVisibility == View.GONE) { editItem.setVisibility(View.GONE); } } } @Override public void onAnimationCancel(Animator animation) { if (editButtonAnimation != null && editButtonAnimation.equals(animation)) { editButtonAnimation = null; } } }); editButtonAnimation.start(); } } } } } private void processRowSelect(View view, boolean outside, float touchX, float touchY) { MessageObject message = null; if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; message = cell.getMessageObject(); cell.setLastTouchCoords(touchX, touchY); } else if (view instanceof ChatActionCell) { message = ((ChatActionCell) view).getMessageObject(); } int type = getMessageType(message); if (type < 2 || type == 20) { return; } addToSelectedMessages(message, outside); updateActionModeTitle(); updateVisibleRows(); } private void updateActionModeTitle() { if (reportType < 0) { if (!actionBar.isActionModeShowed()) { return; } if (selectedMessagesIds[0].size() != 0 || selectedMessagesIds[1].size() != 0) { selectedMessagesCountTextView.setNumber(selectedMessagesIds[0].size() + selectedMessagesIds[1].size(), true); } } else { int size = selectedMessagesIds[0].size() + selectedMessagesIds[1].size(); if (size == 0) { bottomOverlayChatText.setText(LocaleController.getString("ReportMessages", R.string.ReportMessages)); bottomOverlayChatText.setAlpha(0.5f); bottomOverlayChatText.setEnabled(false); } else { bottomOverlayChatText.setText(LocaleController.formatString("ReportMessagesCount", R.string.ReportMessagesCount, LocaleController.formatPluralString("messages", size)).toUpperCase()); bottomOverlayChatText.setAlpha(1.0f); bottomOverlayChatText.setEnabled(true); } } } private void updateTitle() { if (avatarContainer == null) { return; } if (isThreadChat()) { if (isComments) { if (threadMessageObject.hasReplies()) { avatarContainer.setTitle(LocaleController.formatPluralString("Comments", threadMessageObject.getRepliesCount())); } else { avatarContainer.setTitle(LocaleController.getString("CommentsTitle", R.string.CommentsTitle)); } } else { avatarContainer.setTitle(LocaleController.formatPluralString("Replies", threadMessageObject.getRepliesCount())); } } else if (UserObject.isReplyUser(currentUser)) { avatarContainer.setTitle(LocaleController.getString("RepliesTitle", R.string.RepliesTitle)); } else if (chatMode == MODE_SCHEDULED) { if (UserObject.isUserSelf(currentUser)) { avatarContainer.setTitle(LocaleController.getString("Reminders", R.string.Reminders)); } else { avatarContainer.setTitle(LocaleController.getString("ScheduledMessages", R.string.ScheduledMessages)); } } else if (chatMode == MODE_PINNED) { avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } else if (currentChat != null) { avatarContainer.setTitle(currentChat.title, currentChat.scam, currentChat.fake, currentChat.verified, false); } else if (currentUser != null) { if (currentUser.self) { avatarContainer.setTitle(LocaleController.getString("SavedMessages", R.string.SavedMessages)); } else if (!MessagesController.isSupportUser(currentUser) && getContactsController().contactsDict.get(currentUser.id) == null && (getContactsController().contactsDict.size() != 0 || !getContactsController().isLoadingContacts())) { if (!TextUtils.isEmpty(currentUser.phone)) { avatarContainer.setTitle(PhoneFormat.getInstance().format("+" + currentUser.phone)); } else { avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser)); } } else { avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser)); } } setParentActivityTitle(avatarContainer.getTitleTextView().getText()); } private int getPinnedMessagesCount() { return Math.max(loadedPinnedMessagesCount, totalPinnedMessagesCount); } private void updateBotButtons() { if (headerItem == null || currentUser == null || currentEncryptedChat != null || !currentUser.bot) { return; } boolean hasHelp = false; boolean hasSettings = false; if (botInfo.size() != 0) { for (int b = 0; b < botInfo.size(); b++) { TLRPC.BotInfo info = botInfo.valueAt(b); for (int a = 0; a < info.commands.size(); a++) { TLRPC.TL_botCommand command = info.commands.get(a); if (command.command.toLowerCase().equals("help")) { hasHelp = true; } else if (command.command.toLowerCase().equals("settings")) { hasSettings = true; } if (hasSettings && hasHelp) { break; } } } } if (hasHelp) { headerItem.showSubItem(bot_help); } else { headerItem.hideSubItem(bot_help); } if (hasSettings) { headerItem.showSubItem(bot_settings); } else { headerItem.hideSubItem(bot_settings); } } private void updateTitleIcons() { updateTitleIcons(false); } private void updateTitleIcons(boolean forceToggleMuted) { if (avatarContainer == null || chatMode != 0) { return; } boolean isMuted = getMessagesController().isDialogMuted(dialog_id); if (forceToggleMuted) { isMuted = !isMuted; } Drawable rightIcon = null; if (!UserObject.isReplyUser(currentUser) && !isThreadChat() && isMuted) { rightIcon = getThemedDrawable(Theme.key_drawable_muteIconDrawable); } avatarContainer.setTitleIcons(currentEncryptedChat != null ? getThemedDrawable(Theme.key_drawable_lockIconDrawable) : null, rightIcon); if (!forceToggleMuted && muteItem != null) { if (isMuted) { muteItem.getRightIcon().setVisibility(View.GONE); muteItem.setTextAndIcon(LocaleController.getString("Unmute", R.string.Unmute), R.drawable.msg_mute); } else { muteItem.getRightIcon().setVisibility(View.VISIBLE); if (getMessagesController().isDialogNotificationsSoundEnabled(dialog_id)) { muteItem.setTextAndIcon(LocaleController.getString("Mute", R.string.Mute), R.drawable.msg_unmute); } else { muteItem.setTextAndIcon(LocaleController.getString("Mute", R.string.Mute), R.drawable.msg_silent); } } } if (chatNotificationsPopupWrapper != null) { chatNotificationsPopupWrapper.update(dialog_id); } } private void checkAndUpdateAvatar() { if (currentUser != null) { TLRPC.User user = getMessagesController().getUser(currentUser.id); if (user == null) { return; } currentUser = user; } else if (currentChat != null) { TLRPC.Chat chat = getMessagesController().getChat(currentChat.id); if (chat == null) { return; } currentChat = chat; } if (avatarContainer != null) { avatarContainer.checkAndUpdateAvatar(); } } public void openVideoEditor(String videoPath, String caption) { if (getParentActivity() != null) { final Bitmap thumb = SendMessagesHelper.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND); PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); final ArrayList cameraPhoto = new ArrayList<>(); MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, videoPath, 0, true, 0, 0, 0); entry.caption = caption; cameraPhoto.add(entry); PhotoViewer.getInstance().openPhotoForSelect(cameraPhoto, 0, 0, false, new PhotoViewer.EmptyPhotoViewerProvider() { @Override public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { return new ImageReceiver.BitmapHolder(thumb, null, 0); } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { sendMedia((MediaController.PhotoEntry) cameraPhoto.get(0), videoEditedInfo, notify, scheduleDate, forceDocument); } @Override public boolean canScrollAway() { return false; } }, this); } else { fillEditingMediaWithCaption(caption, null); SendMessagesHelper.prepareSendingVideo(getAccountInstance(), videoPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, null, 0, editingMessageObject, true, 0, false); afterMessageSend(); } } public boolean openPhotosEditor(ArrayList photoPathes, CharSequence caption) { final ArrayList entries = new ArrayList<>(); for (int a = 0; a < photoPathes.size(); ++a) { SendMessagesHelper.SendingMediaInfo photoInfo = photoPathes.get(a); String path = null; if (photoInfo.path != null) { path = photoInfo.path; } else if (photoInfo.uri != null) { // path = AndroidUtilities.getPath(photoInfo.uri); if (path == null) { try { final File file = AndroidUtilities.generatePicturePath(isSecretChat(), ""); InputStream in = ApplicationLoader.applicationContext.getContentResolver().openInputStream(photoInfo.uri); FileOutputStream fos = new FileOutputStream(file); byte[] buffer = new byte[8 * 1024]; int lengthRead; while ((lengthRead = in.read(buffer)) > 0) { fos.write(buffer, 0, lengthRead); fos.flush(); } in.close(); fos.close(); path = file.getAbsolutePath(); } catch (Exception e) { FileLog.e(e); continue; } } } if (path == null) { continue; } int orientation = 0; try { ExifInterface ei = new ExifInterface(path); int exif = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (exif) { case ExifInterface.ORIENTATION_ROTATE_90: orientation = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: orientation = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: orientation = 270; break; } } catch (Exception e) { FileLog.e(e); } MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, path, orientation, photoInfo.isVideo, 0, 0, 0); if (a == photoPathes.size() - 1 && caption != null) { entry.caption = caption; } entries.add(entry); } if (entries.isEmpty()) { return false; } if (getParentActivity() != null) { final boolean[] checked = new boolean[entries.size()]; Arrays.fill(checked, true); PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); PhotoViewer.getInstance().openPhotoForSelect(new ArrayList<>(entries), entries.size() - 1, 0, false, new PhotoViewer.EmptyPhotoViewerProvider() { @Override public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { return null; } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { for (int i = entries.size() - 1; i >= 0; --i) { if (!checked[i]) { entries.remove(i); } } sendPhotosGroup(entries, notify, scheduleDate, forceDocument); } @Override public int setPhotoChecked(int index, VideoEditedInfo videoEditedInfo) { return index; } @Override public boolean isPhotoChecked(int index) { return checked[index]; } @Override public boolean canScrollAway() { return false; } }, this); } else { fillEditingMediaWithCaption(caption, null); sendPhotosGroup(entries, false, 0, false); afterMessageSend(); } return true; } private void sendPhotosGroup(ArrayList entries, boolean notify, int scheduleDate, boolean forceDocument) { if (!entries.isEmpty()) { ArrayList photos = new ArrayList<>(); for (MediaController.PhotoEntry entry : entries) { SendMessagesHelper.SendingMediaInfo info = new SendMessagesHelper.SendingMediaInfo(); if (!entry.isVideo && entry.imagePath != null) { info.path = entry.imagePath; } else if (entry.path != null) { info.path = entry.path; } info.thumbPath = entry.thumbPath; info.isVideo = entry.isVideo; info.caption = entry.caption != null ? entry.caption.toString() : null; info.entities = entry.entities; info.masks = entry.stickers; info.ttl = entry.ttl; info.videoEditedInfo = entry.editedInfo; info.canDeleteAfter = entry.canDeleteAfter; photos.add(info); entry.reset(); } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, null, getThreadMessage(), null, forceDocument, true, null, notify, scheduleDate); afterMessageSend(); chatActivityEnterView.setFieldText(""); } if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { scheduledMessagesCount = 0; } scheduledMessagesCount += entries.size(); updateScheduledInterface(true); } } private void openEditingMessageInPhotoEditor() { if (editingMessageObject == null || !editingMessageObject.canEditMedia() || editingMessageObjectReqId != 0) { return; } if (!editingMessageObject.isPhoto() && !editingMessageObject.isVideo()) { return; } final MessageObject object = editingMessageObject; File file = null; if (!TextUtils.isEmpty(object.messageOwner.attachPath)) { file = new File(object.messageOwner.attachPath); if (!file.exists()) { file = null; } } if (file == null) { file = FileLoader.getInstance(currentAccount).getPathToMessage(object.messageOwner); } if (!file.exists()) { return; } PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); final ArrayList photos = new ArrayList<>(); final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, object.isVideo(), 0, 0, 0); entry.caption = chatActivityEnterView.getFieldText(); photos.add(entry); PhotoViewer.getInstance().openPhotoForSelect(photos, 0, 2, false, new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { return ChatActivity.this.getPlaceForPhoto(object, null, needPreview, true); } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { if (editingMessageObject != object) { return; } if (entry.isCropped || entry.isPainted || entry.isFiltered || videoEditedInfo != null) { sendMedia(entry, videoEditedInfo, notify, scheduleDate, forceDocument); } else { chatActivityEnterView.doneEditingMessage(); } } @Override public boolean canCaptureMorePhotos() { return false; } @Override public boolean allowSendingSubmenu() { return false; } @Override public MessageObject getEditingMessageObject() { return editingMessageObject == object ? object : null; } @Override public void onCaptionChanged(CharSequence caption) { if (editingMessageObject == object) { chatActivityEnterView.setFieldText(caption, true); } } @Override public boolean closeKeyboard() { if (chatActivityEnterView != null && isKeyboardVisible()) { chatActivityEnterView.closeKeyboard(); return true; } return false; } }, this); } private PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, boolean needPreview, boolean onlyIfVisible) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { ImageReceiver imageReceiver = null; View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { if (messageObject != null) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject message = cell.getMessageObject(); if (message != null && message.getId() == messageObject.getId()) { imageReceiver = cell.getPhotoImage(); } } } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) view; MessageObject message = cell.getMessageObject(); if (message != null) { if (messageObject != null) { if (message.getId() == messageObject.getId()) { imageReceiver = cell.getPhotoImage(); } } else if (fileLocation != null && message.photoThumbs != null) { for (int b = 0; b < message.photoThumbs.size(); b++) { TLRPC.PhotoSize photoSize = message.photoThumbs.get(b); if (photoSize.location != null && photoSize.location.volume_id == fileLocation.volume_id && photoSize.location.local_id == fileLocation.local_id) { imageReceiver = cell.getPhotoImage(); break; } } } } } if (imageReceiver != null) { if (onlyIfVisible && view.getY() + imageReceiver.getImageY2() < chatListViewPaddingTop - AndroidUtilities.dp(4)) { return null; } int[] coords = new int[2]; view.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; object.viewY = coords[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight); object.parentView = chatListView; object.animatingImageView = !SharedConfig.smoothKeyboard && pagedownButton != null && pagedownButton.getTag() != null && view instanceof ChatMessageCell ? animatingImageView : null; object.imageReceiver = imageReceiver; if (needPreview) { object.thumb = imageReceiver.getBitmapSafe(); } object.radius = imageReceiver.getRoundRadius(); if (view instanceof ChatActionCell && currentChat != null) { object.dialogId = -currentChat.id; } object.clipTopAddition = (int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4)); object.clipBottomAddition = blurredViewBottomOffset; return object; } } return null; } private void showAttachmentError() { if (getParentActivity() == null) { return; } BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("UnsupportedAttachment", R.string.UnsupportedAttachment), themeDelegate).show(); } private void fillEditingMediaWithCaption(CharSequence caption, ArrayList entities) { if (editingMessageObject == null) { return; } if (!TextUtils.isEmpty(caption)) { editingMessageObject.editingMessage = caption; editingMessageObject.editingMessageEntities = entities; } else if (chatActivityEnterView != null) { editingMessageObject.editingMessage = chatActivityEnterView.getFieldText(); if (editingMessageObject.editingMessage == null && !TextUtils.isEmpty(editingMessageObject.messageOwner.message)) { editingMessageObject.editingMessage = ""; } } } private void sendUriAsDocument(Uri uri) { if (uri == null) { return; } String extractUriFrom = uri.toString(); if (extractUriFrom.contains("com.google.android.apps.photos.contentprovider")) { try { String firstExtraction = extractUriFrom.split("/1/")[1]; int index = firstExtraction.indexOf("/ACTUAL"); if (index != -1) { firstExtraction = firstExtraction.substring(0, index); String secondExtraction = URLDecoder.decode(firstExtraction, "UTF-8"); uri = Uri.parse(secondExtraction); } } catch (Exception e) { FileLog.e(e); } } String tempPath = AndroidUtilities.getPath(uri); String originalPath = tempPath; boolean sendAsUri = false; if (!BuildVars.NO_SCOPED_STORAGE) { sendAsUri = true; } else if (tempPath == null) { originalPath = uri.toString(); tempPath = MediaController.copyFileToCache(uri, "file"); if (tempPath == null) { showAttachmentError(); return; } } fillEditingMediaWithCaption(null, null); if (sendAsUri) { SendMessagesHelper.prepareSendingDocument(getAccountInstance(), null, null, uri, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0); } else { SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0); } hideFieldPanel(false); } @Override public void onActivityResultFragment(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK) { if (requestCode == 0 || requestCode == 2) { createChatAttachView(); if (chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().onActivityResultFragment(requestCode, data, currentPicturePath); } currentPicturePath = null; } else if (requestCode == 1) { if (data == null || data.getData() == null) { showAttachmentError(); return; } Uri uri = data.getData(); if (uri.toString().contains("video")) { String videoPath = null; try { videoPath = AndroidUtilities.getPath(uri); } catch (Exception e) { FileLog.e(e); } if (videoPath == null) { showAttachmentError(); } if (paused) { startVideoEdit = videoPath; } else { openVideoEditor(videoPath, null); } } else { if (editingMessageObject == null && chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> { fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, 0, editingMessageObject, notify, scheduleDate); }, themeDelegate); } else { fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, 0, editingMessageObject, true, 0); } } afterMessageSend(); } else if (requestCode == 21) { if (data == null) { showAttachmentError(); return; } if (data.getData() != null) { sendUriAsDocument(data.getData()); } else if (data.getClipData() != null) { ClipData clipData = data.getClipData(); for (int i = 0; i < clipData.getItemCount(); i++) { sendUriAsDocument(clipData.getItemAt(i).getUri()); } } else { showAttachmentError(); } if (chatAttachAlert != null) { chatAttachAlert.dismiss(); } afterMessageSend(); } } } @Override public void saveSelfArgs(Bundle args) { if (currentPicturePath != null) { args.putString("path", currentPicturePath); } } @Override public void restoreSelfArgs(Bundle args) { currentPicturePath = args.getString("path"); } private void removeUnreadPlane(boolean scrollToEnd) { if (unreadMessageObject != null) { if (scrollToEnd) { forwardEndReached[0] = forwardEndReached[1] = true; first_unread_id = 0; last_message_id = 0; } createUnreadMessageAfterId = 0; createUnreadMessageAfterIdLoading = false; removeMessageObject(unreadMessageObject); unreadMessageObject = null; } } @Override public void didReceivedNotification(int id, int account, final Object... args) { if (id == NotificationCenter.messagesDidLoad) { int guid = (Integer) args[10]; if (guid != classGuid) { return; } int queryLoadIndex = (Integer) args[11]; boolean doNotRemoveLoadIndex; if (queryLoadIndex < 0) { doNotRemoveLoadIndex = true; queryLoadIndex = -queryLoadIndex; } else { doNotRemoveLoadIndex = false; } if (!doNotRemoveLoadIndex && !fragmentBeginToShow && !paused) { int[] alowedNotifications = new int[]{NotificationCenter.messagesDidLoad, NotificationCenter.chatInfoDidLoad, NotificationCenter.groupCallUpdated, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}; if (transitionAnimationIndex == 0) { transitionAnimationIndex = getNotificationCenter().setAnimationInProgress(transitionAnimationIndex, alowedNotifications); AndroidUtilities.runOnUIThread(() -> getNotificationCenter().onAnimationFinish(transitionAnimationIndex), 800); } else { getNotificationCenter().updateAllowedNotifications(transitionAnimationIndex, alowedNotifications); } } int index = waitingForLoad.indexOf(queryLoadIndex); long currentUserId = getUserConfig().getClientUserId(); int mode = (Integer) args[14]; boolean isCache = (Boolean) args[3]; boolean postponedScroll = postponedScrollToLastMessageQueryIndex > 0 && queryLoadIndex == postponedScrollToLastMessageQueryIndex; if (postponedScroll) { postponedScrollToLastMessageQueryIndex = 0; } if (index == -1) { if (chatMode == MODE_SCHEDULED && mode == MODE_SCHEDULED && !isCache) { waitingForReplyMessageLoad = true; waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); } return; } else if (!doNotRemoveLoadIndex) { waitingForLoad.remove(index); } ArrayList messArr = (ArrayList) args[2]; if (messages.isEmpty() && messArr.size() == 1 && MessageObject.isSystemSignUp(messArr.get(0))) { forceHistoryEmpty = true; endReached[0] = endReached[1] = true; forwardEndReached[0] = forwardEndReached[1] = true; firstLoading = false; showProgressView(false); if (chatListView != null) { if (!fragmentOpened) { chatListView.setAnimateEmptyView(false, 1); chatListView.setEmptyView(emptyViewContainer); chatListView.setAnimateEmptyView(true, 1); } else { chatListView.setEmptyView(emptyViewContainer); } chatAdapter.notifyDataSetChanged(true); } resumeDelayedFragmentAnimation(); MessageObject messageObject = messArr.get(0); getMessagesController().markDialogAsRead(dialog_id, messageObject.getId(), messageObject.getId(), messageObject.messageOwner.date, false, 0, 0, true, 0); AndroidUtilities.cancelRunOnUIThread(fragmentTransitionRunnable); fragmentTransitionRunnable.run(); return; } if (chatMode != mode) { if (chatMode != MODE_SCHEDULED) { scheduledMessagesCount = messArr.size(); updateScheduledInterface(true); } return; } boolean createUnreadLoading = false; boolean showDateAfter = waitingForReplyMessageLoad; if (waitingForReplyMessageLoad) { if (chatMode != MODE_SCHEDULED && !createUnreadMessageAfterIdLoading) { boolean found = false; for (int a = 0; a < messArr.size(); a++) { MessageObject obj = messArr.get(a); if (obj.getId() == startLoadFromMessageId) { found = true; break; } if (a + 1 < messArr.size()) { MessageObject obj2 = messArr.get(a + 1); if (obj.getId() >= startLoadFromMessageId && obj2.getId() < startLoadFromMessageId) { startLoadFromMessageId = obj.getId(); found = true; break; } } } if (!found) { startLoadFromMessageId = 0; return; } } int startLoadFrom = startLoadFromMessageId; boolean needSelect = needSelectFromMessageId; int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; clearChatData(); if (chatMode == 0) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; } } loadsCount++; long did = (Long) args[0]; int loadIndex = did == dialog_id ? 0 : 1; int count = (Integer) args[1]; int fnid = (Integer) args[4]; int last_unread_date = (Integer) args[7]; int load_type = (Integer) args[8]; boolean isEnd = (Boolean) args[9]; int loaded_max_id = (Integer) args[12]; int loaded_mentions_count = chatWasReset ? 0 : (Integer) args[13]; if (loaded_mentions_count < 0) { loaded_mentions_count *= -1; hasAllMentionsLocal = false; } else if (first) { hasAllMentionsLocal = true; } if (load_type == 4) { startLoadFromMessageId = loaded_max_id; for (int a = messArr.size() - 1; a > 0; a--) { MessageObject obj = messArr.get(a); if (obj.type < 0 && obj.getId() == startLoadFromMessageId) { startLoadFromMessageId = messArr.get(a - 1).getId(); break; } } } if (postponedScroll) { if (load_type == 0 && isCache && messArr.size() < count) { postponedScrollToLastMessageQueryIndex = lastLoadIndex; waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, count, 0, 0, false, 0, classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); return; } if (load_type == 4) { postponedScrollMessageId = startLoadFromMessageId; } if (progressDialog != null) { progressDialog.dismiss(); } showPinnedProgress(false); if (postponedScrollIsCanceled) { return; } if (postponedScrollMessageId == 0) { clearChatData(); } else { if (showScrollToMessageError) { boolean found = false; for (int k = 0; k < messArr.size(); k++) { if (messArr.get(k).getId() == postponedScrollMessageId) { found = true; break; } } if (!found) { if (isThreadChat()) { Bundle bundle = new Bundle(); if (currentEncryptedChat != null) { bundle.putInt("enc_id", currentEncryptedChat.id); } else if (currentChat != null) { bundle.putLong("chat_id", currentChat.id); } else { bundle.putLong("user_id", currentUser.id); } bundle.putInt("message_id", postponedScrollMessageId); presentFragment(new ChatActivity(bundle), true); } else { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("MessageNotFound", R.string.MessageNotFound), themeDelegate).show(); } return; } showScrollToMessageError = false; } int startLoadFrom = startLoadFromMessageId; boolean needSelect = needSelectFromMessageId; int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; clearChatData(); if (chatMode == 0) { createUnreadMessageAfterId = unreadAfterId; startLoadFromMessageId = startLoadFrom; needSelectFromMessageId = needSelect; } } } if (chatListItemAnimator != null) { chatListItemAnimator.setShouldAnimateEnterFromBottom(false); } int unread_to_load = 0; if (fnid != 0) { if (!chatWasReset) { last_message_id = (Integer) args[5]; } if (load_type == 3) { if (loadingFromOldPosition) { if (!chatWasReset) { unread_to_load = (Integer) args[6]; if (unread_to_load != 0) { createUnreadMessageAfterId = fnid; } } loadingFromOldPosition = false; } first_unread_id = 0; } else { first_unread_id = fnid; if (!chatWasReset) { unread_to_load = (Integer) args[6]; } } } else if (!chatWasReset && startLoadFromMessageId != 0 && (load_type == 3 || load_type == 4)) { last_message_id = (Integer) args[5]; } else if (did == 777000 && load_type == 2) { int unreadCount = (Integer) args[6]; unreadCount--; if (unreadCount > 0 && unreadCount < messArr.size() - 1) { first_unread_id = messArr.get(unreadCount).messageOwner.id; } } if (isThreadChat() && threadUnreadMessagesCount != 0) { unread_to_load = threadUnreadMessagesCount; threadUnreadMessagesCount = 0; } int newRowsCount = 0; if (load_type != 0 && (isThreadChat() && first_unread_id != 0 || startLoadFromMessageId != 0 || last_message_id != 0)) { forwardEndReached[loadIndex] = false; hideForwardEndReached = false; } if ((load_type == 1 || load_type == 3) && loadIndex == 1) { endReached[0] = cacheEndReached[0] = true; forwardEndReached[0] = false; hideForwardEndReached = false; minMessageId[0] = 0; } if (chatMode == MODE_SCHEDULED) { endReached[0] = cacheEndReached[0] = true; forwardEndReached[0] = forwardEndReached[0] = true; } if (!isThreadChat() && ChatObject.isChannel(currentChat) && !getMessagesController().dialogs_dict.containsKey(dialog_id) && load_type == 2 && loadIndex == 0) { forwardEndReached[0] = false; hideForwardEndReached = true; } if (loadsCount == 1 && messArr.size() > 20) { loadsCount++; } boolean isFirstLoading = firstLoading; if (firstLoading) { if (!forwardEndReached[loadIndex]) { messages.clear(); messagesByDays.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; for (int a = 0; a < 2; a++) { messagesDict[a].clear(); if (currentEncryptedChat == null) { maxMessageId[a] = Integer.MAX_VALUE; minMessageId[a] = Integer.MIN_VALUE; } else { maxMessageId[a] = Integer.MIN_VALUE; minMessageId[a] = Integer.MAX_VALUE; } maxDate[a] = Integer.MIN_VALUE; minDate[a] = 0; } } firstLoading = false; AndroidUtilities.runOnUIThread(() -> { getNotificationCenter().runDelayedNotifications(); resumeDelayedFragmentAnimation(); AndroidUtilities.cancelRunOnUIThread(fragmentTransitionRunnable); fragmentTransitionRunnable.run(); }); } if (isThreadChat() && (load_type == 2 || load_type == 3) && !isCache) { if (load_type == 3 && scrollToThreadMessage) { startLoadFromMessageId = threadMessageId; } int beforMax = 0; int afterMax = 0; boolean hasMaxId = false; for (int a = 0, N = messArr.size(); a < N; a++) { MessageObject message = messArr.get(a); int mid = message.getId(); if (mid == loaded_max_id) { hasMaxId = true; } if (mid > loaded_max_id) { afterMax++; } else { beforMax++; } } int num; if (load_type == 2) { num = 10; } else { num = count / 2; } if (hasMaxId) { num++; } if (beforMax < num) { endReached[0] = true; } if (!chatWasReset && afterMax < count - num) { forwardEndReached[0] = true; } } if (chatMode == MODE_PINNED) { endReached[loadIndex] = true; } if (load_type == 0 && forwardEndReached[0] && !pendingSendMessages.isEmpty()) { for (int a = 0, N = messArr.size(); a < N; a++) { MessageObject existing = pendingSendMessagesDict.get(messArr.get(a).getId()); if (existing != null) { pendingSendMessagesDict.remove(existing.getId()); pendingSendMessages.remove(existing); } } if (!pendingSendMessages.isEmpty()) { int pasteIndex = 0; int date = pendingSendMessages.get(0).messageOwner.date; if (!messArr.isEmpty()) { if (date >= messArr.get(0).messageOwner.date) { pasteIndex = 0; } else if (date <= messArr.get(messArr.size() - 1).messageOwner.date) { pasteIndex = messArr.size(); } else { for (int a = 0, N = messArr.size(); a < N - 1; a++) { if (messArr.get(a).messageOwner.date >= date && messArr.get(a + 1).messageOwner.date <= date) { pasteIndex = a + 1; } } } } messArr = new ArrayList<>(messArr); messArr.addAll(pasteIndex, pendingSendMessages); pendingSendMessages.clear(); pendingSendMessagesDict.clear(); } } if (!threadMessageAdded && isThreadChat() && (load_type == 0 && messArr.size() < count || (load_type == 2 || load_type == 3) && endReached[0])) { TLRPC.Message msg = new TLRPC.TL_message(); if (threadMessageObject.getRepliesCount() == 0) { if (isComments) { msg.message = LocaleController.getString("NoComments", R.string.NoComments); } else { msg.message = LocaleController.getString("NoReplies", R.string.NoReplies); } } else { msg.message = LocaleController.getString("DiscussionStarted", R.string.DiscussionStarted); } msg.id = 0; msg.date = threadMessageObject.messageOwner.date; replyMessageHeaderObject = new MessageObject(currentAccount, msg, false, false); replyMessageHeaderObject.type = 10; replyMessageHeaderObject.contentType = 1; replyMessageHeaderObject.isDateObject = true; replyMessageHeaderObject.stableId = lastStableId++; messArr.add(replyMessageHeaderObject); updateReplyMessageHeader(false); messArr.addAll(threadMessageObjects); count += 2; threadMessageAdded = true; } if (load_type == 1) { Collections.reverse(messArr); } if (currentEncryptedChat == null) { getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode == MODE_SCHEDULED, null); } int approximateHeightSum = 0; if (!chatWasReset && (load_type == 2 || load_type == 1) && messArr.isEmpty() && !isCache) { forwardEndReached[0] = true; } LongSparseArray newGroups = null; LongSparseArray changedGroups = null; MediaController mediaController = MediaController.getInstance(); TLRPC.MessageAction dropPhotoAction = null; boolean createdWas = false; boolean moveCurrentDateObject = false; boolean scrolledToUnread = false; for (int a = 0, N = messArr.size(); a < N; a++) { MessageObject obj = messArr.get(N - a - 1); TLRPC.MessageAction action = obj.messageOwner.action; if (a == 0 && action instanceof TLRPC.TL_messageActionChatCreate) { createdWas = true; } else if (!createdWas) { break; } else if (a < 2 && action instanceof TLRPC.TL_messageActionChatEditPhoto) { dropPhotoAction = action; } } for (int a = 0; a < messArr.size(); a++) { MessageObject obj = messArr.get(a); if (obj.replyMessageObject != null) { repliesMessagesDict.put(obj.replyMessageObject.getId(), obj.replyMessageObject); addReplyMessageOwner(obj, 0); } int messageId = obj.getId(); if (threadMessageId != 0) { if (messageId <= (obj.isOut() ? threadMaxOutboxReadId : threadMaxInboxReadId)) { obj.setIsRead(); } } approximateHeightSum += obj.getApproximateHeight(); if (currentUser != null) { if (currentUser.self) { obj.messageOwner.out = true; } if (chatMode != MODE_SCHEDULED && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } } if (messagesDict[loadIndex].indexOfKey(messageId) >= 0) { continue; } if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { continue; } if (currentEncryptedChat != null && obj.messageOwner.stickerVerified == 0) { getMediaDataController().verifyAnimatedStickerMessage(obj.messageOwner); } addToPolls(obj, null); if (isSecretChat()) { checkSecretMessageForLocation(obj); } if (mediaController.isPlayingMessage(obj)) { MessageObject player = mediaController.getPlayingMessageObject(); obj.audioProgress = player.audioProgress; obj.audioProgressSec = player.audioProgressSec; obj.audioPlayerDuration = player.audioPlayerDuration; } if (loadIndex == 0 && ChatObject.isChannel(currentChat) && messageId == 1) { endReached[loadIndex] = true; cacheEndReached[loadIndex] = true; } if (messageId > 0) { maxMessageId[loadIndex] = Math.min(messageId, maxMessageId[loadIndex]); minMessageId[loadIndex] = Math.max(messageId, minMessageId[loadIndex]); } else if (currentEncryptedChat != null) { maxMessageId[loadIndex] = Math.max(messageId, maxMessageId[loadIndex]); minMessageId[loadIndex] = Math.min(messageId, minMessageId[loadIndex]); } if (obj.messageOwner.date != 0) { maxDate[loadIndex] = Math.max(maxDate[loadIndex], obj.messageOwner.date); if (minDate[loadIndex] == 0 || obj.messageOwner.date < minDate[loadIndex]) { minDate[loadIndex] = obj.messageOwner.date; } } if (!chatWasReset && messageId != 0 && messageId == last_message_id) { forwardEndReached[loadIndex] = true; } TLRPC.MessageAction action = obj.messageOwner.action; if (obj.type < 0 || loadIndex == 1 && action instanceof TLRPC.TL_messageActionChatMigrateTo) { continue; } if (currentChat != null && currentChat.creator && (action instanceof TLRPC.TL_messageActionChatCreate || dropPhotoAction != null && action == dropPhotoAction)) { continue; } if (obj.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { continue; } if (needAnimateToMessage != null && needAnimateToMessage.getId() == messageId && messageId < 0 && chatMode != MODE_SCHEDULED) { obj = needAnimateToMessage; animatingMessageObjects.add(obj); needAnimateToMessage = null; } messagesDict[loadIndex].put(messageId, obj); ArrayList dayArray = messagesByDays.get(obj.dateKey); if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { dateMsg.message = LocaleController.getString("MessageScheduledUntilOnline", R.string.MessageScheduledUntilOnline); } else { dateMsg.message = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); } } else { dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); } dateMsg.id = 0; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 10; dateObj.contentType = 1; dateObj.isDateObject = true; dateObj.stableId = lastStableId++; if (load_type == 1) { messages.add(0, dateObj); } else { messages.add(dateObj); } newRowsCount++; } else { if (!moveCurrentDateObject && !messages.isEmpty() && messages.get(messages.size() - 1).isDateObject) { messages.get(messages.size() - 1).stableId = lastStableId++; moveCurrentDateObject = true; } } if (obj.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(obj.getGroupIdForUse()); if (groupedMessages != null) { if (messages.size() > 1) { MessageObject previous; if (load_type == 1) { previous = messages.get(0); } else { previous = messages.get(messages.size() - 2); } if (previous.getGroupIdForUse() == obj.getGroupIdForUse()) { if (previous.localGroupId != 0) { obj.localGroupId = previous.localGroupId; groupedMessages = groupedMessagesMap.get(previous.localGroupId); } } else if (previous.getGroupIdForUse() != obj.getGroupIdForUse()) { obj.localGroupId = Utilities.random.nextLong(); groupedMessages = null; } } } if (groupedMessages == null) { groupedMessages = new MessageObject.GroupedMessages(); groupedMessages.groupId = obj.getGroupId(); groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); } else if (newGroups == null || newGroups.indexOfKey(obj.getGroupId()) < 0) { if (changedGroups == null) { changedGroups = new LongSparseArray<>(); } changedGroups.put(obj.getGroupId(), groupedMessages); } if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); if (load_type == 1) { groupedMessages.messages.add(obj); } else { groupedMessages.messages.add(0, obj); } } else if (obj.getGroupIdForUse() != 0) { obj.messageOwner.grouped_id = 0; obj.localSentGroupId = 0; } newRowsCount++; dayArray.add(obj); obj.stableId = lastStableId++; if (load_type == 1) { messages.add(0, obj); } else { messages.get(messages.size() - 1).stableId = lastStableId++; messages.add(messages.size() - 1, obj); } MessageObject prevObj; if (currentEncryptedChat == null) { if (createUnreadMessageAfterId != 0 && load_type != 1 && a + 1 < messArr.size()) { prevObj = messArr.get(a + 1); if (obj.isOut() && !obj.messageOwner.from_scheduled || prevObj.getId() >= createUnreadMessageAfterId) { prevObj = null; } } else { prevObj = null; } } else { if (createUnreadMessageAfterId != 0 && load_type != 1 && a - 1 >= 0) { prevObj = messArr.get(a - 1); if (obj.isOut() && !obj.messageOwner.from_scheduled || prevObj.getId() >= createUnreadMessageAfterId) { prevObj = null; } } else { prevObj = null; } } if (load_type == 2 && messageId != 0 && messageId == first_unread_id) { if ((approximateHeightSum > AndroidUtilities.displaySize.y / 2 || isThreadChat()) || !forwardEndReached[0]) { if (!isThreadChat() || threadMaxInboxReadId != 0) { TLRPC.Message dateMsg = new TLRPC.TL_message(); dateMsg.message = ""; dateMsg.id = 0; MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 6; dateObj.contentType = 2; dateObj.stableId = lastStableId++; messages.add(messages.size() - 1, dateObj); unreadMessageObject = dateObj; scrollToMessage = unreadMessageObject; } else { scrollToMessage = obj; } scrollToMessagePosition = -10000; scrolledToUnread = true; newRowsCount++; } } else if ((load_type == 3 || load_type == 4) && (startLoadFromMessageId < 0 && messageId == startLoadFromMessageId || startLoadFromMessageId > 0 && messageId > 0 && messageId <= startLoadFromMessageId)) { removeSelectedMessageHighlight(); if (needSelectFromMessageId && messageId == startLoadFromMessageId) { highlightMessageId = messageId; } if (showScrollToMessageError && messageId != startLoadFromMessageId) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("MessageNotFound", R.string.MessageNotFound), themeDelegate).show(); } scrollToMessage = obj; if (postponedScroll) { postponedScrollMessageId = scrollToMessage.getId(); } startLoadFromMessageId = 0; if (scrollToMessagePosition == -10000) { scrollToMessagePosition = -9000; } } if (load_type != 2 && unreadMessageObject == null && createUnreadMessageAfterId != 0 && (currentEncryptedChat == null && (!obj.isOut() || obj.messageOwner.from_scheduled) && messageId >= createUnreadMessageAfterId || currentEncryptedChat != null && (!obj.isOut() || obj.messageOwner.from_scheduled) && messageId <= createUnreadMessageAfterId) && (load_type == 1 || prevObj != null || prevObj == null && createUnreadLoading && a == messArr.size() - 1)) { TLRPC.Message dateMsg = new TLRPC.TL_message(); dateMsg.message = ""; dateMsg.id = 0; MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 6; dateObj.contentType = 2; dateObj.stableId = lastStableId++; if (load_type == 1) { messages.add(1, dateObj); } else { messages.add(messages.size() - 1, dateObj); } unreadMessageObject = dateObj; if (load_type == 3) { scrollToMessage = unreadMessageObject; startLoadFromMessageId = 0; scrollToMessagePosition = -9000; } newRowsCount++; } } if (createUnreadLoading) { createUnreadMessageAfterId = 0; } if (load_type == 0 && newRowsCount == 0) { loadsCount--; } if (forwardEndReached[loadIndex] && loadIndex != 1) { first_unread_id = 0; last_message_id = 0; createUnreadMessageAfterId = 0; } if (load_type == 1) { if (!chatWasReset && messArr.size() != count && (!isCache || currentEncryptedChat != null || forwardEndReached[loadIndex])) { forwardEndReached[loadIndex] = true; if (loadIndex != 1) { first_unread_id = 0; last_message_id = 0; createUnreadMessageAfterId = 0; chatAdapter.notifyItemRemoved(chatAdapter.loadingDownRow); } startLoadFromMessageId = 0; } if (newRowsCount > 0) { int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition(); int lastVisPos = chatLayoutManager.findLastVisibleItemPosition(); int top = 0; MessageObject scrollToMessageObject = null; if (firstVisPos != RecyclerView.NO_POSITION) { for (int i = firstVisPos; i <= lastVisPos; i++) { View v = chatLayoutManager.findViewByPosition(i); if (v instanceof ChatMessageCell) { scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); break; } else if (v instanceof ChatActionCell) { scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); break; } } } if (!postponedScroll) { chatAdapter.notifyItemRangeInserted(1, newRowsCount); if (scrollToMessageObject != null) { int scrollToIndex = messages.indexOf(scrollToMessageObject); if (scrollToIndex > 0) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, top); } } } } loadingForward = false; } else { if (messArr.size() < count && load_type != 3 && load_type != 4) { if (isCache) { if (currentEncryptedChat != null || loadIndex == 1 && mergeDialogId != 0 && isEnd) { endReached[loadIndex] = true; } if (load_type != 2) { cacheEndReached[loadIndex] = true; } } else if (load_type != 2 || messArr.size() == 0 && messages.isEmpty()) { endReached[loadIndex] = true; } } loading = false; if (onChatMessagesLoaded != null) { onChatMessagesLoaded.run(); onChatMessagesLoaded = null; } loadSendAsPeers(false); if (chatListView != null && chatScrollHelper != null) { if (first || scrollToTopOnResume || forceScrollToTop) { forceScrollToTop = false; if (!postponedScroll) { chatAdapter.notifyDataSetChanged(true); } if (scrollToMessage != null) { addSponsoredMessages(!isFirstLoading); int yOffset; boolean bottom = true; if (startLoadFromMessageOffset != Integer.MAX_VALUE) { yOffset = -startLoadFromMessageOffset - chatListView.getPaddingBottom(); startLoadFromMessageOffset = Integer.MAX_VALUE; } else if (scrollToMessagePosition == -9000) { yOffset = getScrollOffsetForMessage(scrollToMessage); bottom = false; } else if (scrollToMessagePosition == -10000) { yOffset = -AndroidUtilities.dp(11); if (scrolledToUnread && threadMessageId != 0) { yOffset += AndroidUtilities.dp(48); } bottom = false; } else { yOffset = scrollToMessagePosition; } yOffset += AndroidUtilities.dp(50); // in case pinned message view is visible if (!postponedScroll) { if (!messages.isEmpty()) { if (chatAdapter.loadingUpRow >= 0 && !messages.isEmpty() && (messages.get(messages.size() - 1) == scrollToMessage || messages.get(messages.size() - 2) == scrollToMessage)) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.loadingUpRow, yOffset, bottom); } else { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messages.indexOf(scrollToMessage), yOffset, bottom); } } } chatListView.invalidate(); if (scrollToMessagePosition == -10000 || scrollToMessagePosition == -9000) { canShowPagedownButton = true; updatePagedownButtonVisibility(true); if (unread_to_load != 0) { if (pagedownButtonCounter != null) { if (prevSetUnreadCount != newUnreadMessageCount) { pagedownButtonCounter.setCount(newUnreadMessageCount = unread_to_load, openAnimationEnded); prevSetUnreadCount = newUnreadMessageCount; } } } } scrollToMessagePosition = -10000; scrollToMessage = null; } else { addSponsoredMessages(!isFirstLoading); moveScrollToLastMessage(true); } if (loaded_mentions_count != 0) { showMentionDownButton(true, true); if (mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); mentiondownButtonCounter.setText(String.format("%d", newMentionsCount = loaded_mentions_count)); } } } else { if (newRowsCount != 0) { int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition(); int lastVisPos = chatLayoutManager.findLastVisibleItemPosition(); int top = 0; MessageObject scrollToMessageObject = null; if (firstVisPos != RecyclerView.NO_POSITION) { for (int i = firstVisPos; i <= lastVisPos; i++) { View v = chatLayoutManager.findViewByPosition(i); if (v instanceof ChatMessageCell) { scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); break; } else if (v instanceof ChatActionCell) { scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); break; } } } int insertStart = chatAdapter.messagesEndRow; int loadingUpRow = chatAdapter.loadingUpRow; chatAdapter.updateRowsInternal(); if (loadingUpRow >= 0 && chatAdapter.loadingUpRow < 0) { chatAdapter.notifyItemRemoved(loadingUpRow); } if (newRowsCount > 0) { if (moveCurrentDateObject) { chatAdapter.notifyItemRemoved(insertStart - 1); chatAdapter.notifyItemRangeInserted(insertStart - 1, newRowsCount + 1); } else { chatAdapter.notifyItemChanged(insertStart - 1); chatAdapter.notifyItemRangeInserted(insertStart, newRowsCount); } } if (!postponedScroll && scrollToMessageObject != null) { int scrollToIndex = messages.indexOf(scrollToMessageObject); if (scrollToIndex > 0) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, top); } } } else if (chatAdapter.loadingUpRow >= 0 && endReached[loadIndex] && (loadIndex == 0 && mergeDialogId == 0 || loadIndex == 1)) { chatAdapter.notifyItemRemoved(chatAdapter.loadingUpRow); } else { chatAdapter.notifyDataSetChanged(true); } } if (paused) { scrollToTopOnResume = true; if (scrollToMessage != null) { scrollToTopUnReadOnResume = true; } } if (first) { if (chatListView != null) { if (!fragmentBeginToShow) { chatListView.setAnimateEmptyView(false, 1); chatListView.setEmptyView(emptyViewContainer); chatListView.setAnimateEmptyView(true, 1); } else { chatListView.setEmptyView(emptyViewContainer); } } } } else { scrollToTopOnResume = true; if (scrollToMessage != null) { scrollToTopUnReadOnResume = true; } } } if (newGroups != null) { for (int a = 0; a < newGroups.size(); a++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); groupedMessages.calculate(); if (chatAdapter != null && changedGroups != null && changedGroups.indexOfKey(newGroups.keyAt(a)) >= 0) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int idx = messages.indexOf(messageObject); if (idx >= 0) { if (chatListItemAnimator != null) { chatListItemAnimator.groupWillChanged(groupedMessages); } chatAdapter.notifyItemRangeChanged(idx + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } } if (first && messages.size() > 0) { first = false; if (isThreadChat()) { invalidateMessagesVisiblePart(); } if (startLoadFromDate != 0) { int dateObjectIndex = -1; int closeDateObjectIndex = -1; int closeDateDiff = 0; for (int i = 0; i < messages.size(); i++) { if (messages.get(i).isDateObject && Math.abs(startLoadFromDate - messages.get(i).messageOwner.date) <= 100) { dateObjectIndex = i; break; } if (messages.get(i).isDateObject) { int timeDiff = Math.abs(startLoadFromDate - messages.get(i).messageOwner.date); if (closeDateObjectIndex == -1 || timeDiff < closeDateDiff) { closeDateDiff = timeDiff; closeDateObjectIndex = i; } } } if (dateObjectIndex >= 0) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + dateObjectIndex, (int) (AndroidUtilities.dp(4)), false); } else if (closeDateObjectIndex >= 0) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + closeDateObjectIndex, chatListView.getMeasuredHeight() / 2 - AndroidUtilities.dp(24), false); } } } if (messages.isEmpty() && currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { botUser = ""; updateBottomOverlay(); } if (newRowsCount == 0 && (mergeDialogId != 0 && loadIndex == 0 || currentEncryptedChat != null && !endReached[0])) { first = true; if (chatListView != null) { chatListView.setEmptyView(null); } if (emptyViewContainer != null) { emptyViewContainer.setVisibility(View.INVISIBLE); } } else { showProgressView(false); } if (newRowsCount == 0 && mergeDialogId != 0 && loadIndex == 0) { getNotificationCenter().updateAllowedNotifications(transitionAnimationIndex, new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.groupCallUpdated, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); } if (showDateAfter) { showFloatingDateView(false); } addSponsoredMessages(!isFirstLoading); checkScrollForLoad(false); if (postponedScroll) { chatAdapter.notifyDataSetChanged(true); if (progressDialog != null) { progressDialog.dismiss(); } updatePinnedListButton(false); if (postponedScrollMessageId == 0) { chatScrollHelperCallback.scrollTo = null; chatScrollHelperCallback.lastBottom = true; chatScrollHelperCallback.lastItemOffset = 0; chatScrollHelperCallback.lastPadding = (int) chatListViewPaddingTop; chatScrollHelper.scrollToPosition(0, 0, true, true); } else { MessageObject object = messagesDict[loadIndex].get(postponedScrollMessageId); if (object != null) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(object.getGroupId()); if (object.getGroupId() != 0 && groupedMessages != null) { MessageObject primary = groupedMessages.findPrimaryMessageObject(); if (primary != null) { object = primary; } } } if (object != null) { int k = messages.indexOf(object); if (k >= 0) { int fromPosition = chatLayoutManager.findFirstVisibleItemPosition(); highlightMessageId = object.getId(); int direction; if (postponedScrollMinMessageId != 0) { if (highlightMessageId < 0 && postponedScrollMinMessageId < 0) { direction = highlightMessageId < postponedScrollMinMessageId ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else { direction = highlightMessageId > postponedScrollMinMessageId ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } } else { direction = fromPosition > k ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } chatScrollHelper.setScrollDirection(direction); if (!needSelectFromMessageId) { removeSelectedMessageHighlight(); } int yOffset = getScrollOffsetForMessage(object); chatScrollHelperCallback.scrollTo = object; chatScrollHelperCallback.lastBottom = false; chatScrollHelperCallback.lastItemOffset = yOffset; chatScrollHelperCallback.lastPadding = (int) chatListViewPaddingTop; chatScrollHelper.scrollToPosition(chatAdapter.messagesStartRow + k, yOffset, false, true); } } } } chatWasReset = false; } else if (id == NotificationCenter.invalidateMotionBackground) { if (chatListView != null) { chatListView.invalidateViews(); } if (messageEnterTransitionContainer != null) { messageEnterTransitionContainer.invalidate(); } } else if (id == NotificationCenter.emojiLoaded) { if (chatListView != null) { chatListView.invalidateViews(); } if (replyObjectTextView != null) { replyObjectTextView.invalidate(); } if (alertTextView != null) { alertTextView.invalidate(); } for (int a = 0; a < 2; a++) { if (pinnedMessageTextView[a] != null) { pinnedMessageTextView[a].invalidate(); } } if (mentionContainer != null) { mentionContainer.getListView().invalidateViews(); } if (messagesSearchListView != null) { messagesSearchListView.invalidateViews(); } if (undoView != null) { undoView.invalidate(); } if (chatActivityEnterView != null) { EditTextBoldCursor editText = chatActivityEnterView.getEditField(); int color = editText.getCurrentTextColor(); editText.setTextColor(0xffffffff); editText.setTextColor(color); } if (pinnedMessageButton[0] != null) { pinnedMessageButton[0].invalidate(); } if (pinnedMessageButton[1] != null) { pinnedMessageButton[1].invalidate(); } } else if (id == NotificationCenter.didUpdateConnectionState) { int state = ConnectionsManager.getInstance(account).getConnectionState(); if (state == ConnectionsManager.ConnectionStateConnected) { checkAutoDownloadMessages(false); } } else if (id == NotificationCenter.chatOnlineCountDidLoad) { Long chatId = (Long) args[0]; if (chatInfo == null || currentChat == null || currentChat.id != chatId) { return; } chatInfo.online_count = (Integer) args[1]; if (avatarContainer != null) { avatarContainer.updateOnlineCount(); avatarContainer.updateSubtitle(); } } else if (id == NotificationCenter.updateDefaultSendAsPeer) { long chatId = (long) args[0]; if (chatId == dialog_id) { chatActivityEnterView.updateSendAsButton(true); } } else if (id == NotificationCenter.updateInterfaces) { int updateMask = (Integer) args[0]; if ((updateMask & MessagesController.UPDATE_MASK_NAME) != 0 || (updateMask & MessagesController.UPDATE_MASK_CHAT_NAME) != 0) { if (currentChat != null) { TLRPC.Chat chat = getMessagesController().getChat(currentChat.id); if (chat != null) { currentChat = chat; } } else if (currentUser != null) { TLRPC.User user = getMessagesController().getUser(currentUser.id); if (user != null) { currentUser = user; } } updateTitle(); } boolean updateSubtitle = false; if (!isThreadChat() && ((updateMask & MessagesController.UPDATE_MASK_CHAT_MEMBERS) != 0 || (updateMask & MessagesController.UPDATE_MASK_STATUS) != 0)) { if (currentChat != null && avatarContainer != null) { avatarContainer.updateOnlineCount(); } updateSubtitle = true; } if ((updateMask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (updateMask & MessagesController.UPDATE_MASK_CHAT_AVATAR) != 0 || (updateMask & MessagesController.UPDATE_MASK_NAME) != 0) { checkAndUpdateAvatar(); updateVisibleRows(); } if ((updateMask & MessagesController.UPDATE_MASK_USER_PRINT) != 0) { updateSubtitle = true; } if ((updateMask & MessagesController.UPDATE_MASK_CHAT) != 0 && currentChat != null) { boolean fwdBefore = getMessagesController().isChatNoForwards(currentChat); TLRPC.Chat chat = getMessagesController().getChat(currentChat.id); if (chat == null) { return; } currentChat = chat; boolean fwdChanged = getMessagesController().isChatNoForwards(currentChat) != fwdBefore; updateSubtitle = !isThreadChat(); updateBottomOverlay(); if (chatActivityEnterView != null) { chatActivityEnterView.setDialogId(dialog_id, currentAccount); } if (currentEncryptedChat != null && SharedConfig.passcodeHash.length() == 0 && !SharedConfig.allowScreenCapture && unregisterFlagSecurePasscode == null) { unregisterFlagSecurePasscode = AndroidUtilities.registerFlagSecure(getParentActivity().getWindow()); } if (fwdChanged) { boolean value = getMessagesController().isChatNoForwards(currentChat); if (!value && unregisterFlagSecureNoforwards != null) { unregisterFlagSecureNoforwards.run(); unregisterFlagSecureNoforwards = null; } else if (value && unregisterFlagSecureNoforwards == null) { unregisterFlagSecureNoforwards = AndroidUtilities.registerFlagSecure(getParentActivity().getWindow()); } } } if (avatarContainer != null && updateSubtitle) { avatarContainer.updateSubtitle(true); } if ((updateMask & MessagesController.UPDATE_MASK_USER_PHONE) != 0) { updateTopPanel(true); } } else if (id == NotificationCenter.didReceiveNewMessages) { long did = (Long) args[0]; ArrayList arr = (ArrayList) args[1]; if (did == dialog_id) { boolean scheduled = (Boolean) args[2]; if (scheduled != (chatMode == MODE_SCHEDULED)) { if (chatMode != MODE_SCHEDULED && !isPaused && forwardingMessages == null) { if (!arr.isEmpty() && arr.get(0).getId() < 0) { openScheduledMessages(); } } return; } processNewMessages(arr); } else if (ChatObject.isChannel(currentChat) && !currentChat.megagroup && chatInfo != null && did == -chatInfo.linked_chat_id) { for (int a = 0, N = arr.size(); a < N; a++) { MessageObject messageObject = arr.get(a); if (messageObject.isReply()) { waitingForReplies.put(messageObject.getId(), messageObject); } } checkWaitingForReplies(); } } else if (id == NotificationCenter.didLoadSendAsPeers) { loadSendAsPeers(true); } else if (id == NotificationCenter.didLoadSponsoredMessages) { addSponsoredMessages(true); } else if (id == NotificationCenter.closeChats) { if (args != null && args.length > 0) { long did = (Long) args[0]; if (did == dialog_id) { finishFragment(); } } else { if (AndroidUtilities.isTablet() && parentLayout != null && parentLayout.fragmentsStack.size() > 1) { finishFragment(); } else { removeSelfFromStack(); } } } else if (id == NotificationCenter.commentsRead) { long channelId = (Long) args[0]; if (currentChat != null && currentChat.id == channelId) { int mid = (Integer) args[1]; MessageObject obj = messagesDict[0].get(mid); if (obj != null && obj.hasReplies()) { int maxReadId = (Integer) args[2]; if (paused) { if (delayedReadRunnable != null) { AndroidUtilities.cancelRunOnUIThread(delayedReadRunnable); delayedReadRunnable = null; } obj.messageOwner.replies.read_max_id = maxReadId; } else { AndroidUtilities.runOnUIThread(delayedReadRunnable = () -> { delayedReadRunnable = null; obj.messageOwner.replies.read_max_id = maxReadId; }, 500); } } } } else if (id == NotificationCenter.changeRepliesCounter) { long channelId = (Long) args[0]; if (currentChat != null && currentChat.id == channelId) { int mid = (Integer) args[1]; MessageObject obj = messagesDict[0].get(mid); if (obj != null && obj.messageOwner.replies != null) { Integer count = (Integer) args[2]; obj.messageOwner.replies.replies += count; if (count > 0) { TLRPC.Peer peer = getMessagesController().getPeer(ChatObject.getSendAsPeerId(currentChat, getMessagesController().getChatFull(currentChat.id))); for (int c = 0, N = obj.messageOwner.replies.recent_repliers.size(); c < N; c++) { if (MessageObject.getPeerId(obj.messageOwner.replies.recent_repliers.get(c)) == MessageObject.getPeerId(peer)) { obj.messageOwner.replies.recent_repliers.remove(c); break; } } obj.messageOwner.replies.recent_repliers.add(0, peer); } if (obj.messageOwner.replies.replies < 0) { obj.messageOwner.replies.replies = 0; } } } } else if (id == NotificationCenter.threadMessagesRead) { long did = (Long) args[0]; if (dialog_id != did) { return; } int threadId = (Integer) args[1]; if (threadId != threadMessageId) { return; } int inbox = (Integer) args[2]; int outbox = (Integer) args[3]; if (inbox > threadMaxInboxReadId) { threadMaxInboxReadId = inbox; for (int a = 0, size2 = messages.size(); a < size2; a++) { MessageObject obj = messages.get(a); int messageId = obj.getId(); if (!obj.isOut() && messageId > 0 && messageId <= threadMaxInboxReadId) { if (!obj.isUnread()) { break; } obj.setIsRead(); if (chatAdapter != null) { chatAdapter.invalidateRowWithMessageObject(obj); } } } } if (outbox > threadMaxOutboxReadId) { threadMaxOutboxReadId = outbox; for (int a = 0, size2 = messages.size(); a < size2; a++) { MessageObject obj = messages.get(a); int messageId = obj.getId(); if (obj.isOut() && messageId > 0 && messageId <= threadMaxOutboxReadId) { if (!obj.isUnread()) { break; } obj.setIsRead(); if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(obj, false); } } } } } else if (id == NotificationCenter.messagesRead) { if (chatMode == MODE_SCHEDULED) { return; } LongSparseIntArray inbox = (LongSparseIntArray) args[0]; LongSparseIntArray outbox = (LongSparseIntArray) args[1]; boolean updated = false; if (inbox != null) { for (int b = 0, size = inbox.size(); b < size; b++) { long key = inbox.keyAt(b); long messageId = inbox.get(key); if (key != dialog_id) { continue; } for (int a = 0, size2 = messages.size(); a < size2; a++) { MessageObject obj = messages.get(a); if (!obj.isOut() && obj.getId() > 0 && obj.getId() <= (int) messageId) { if (!obj.isUnread()) { break; } obj.setIsRead(); if (chatAdapter != null) { chatAdapter.invalidateRowWithMessageObject(obj); } updated = true; newUnreadMessageCount--; } } removeUnreadPlane(false); break; } } if (updated) { if (newUnreadMessageCount < 0) { newUnreadMessageCount = 0; } if (pagedownButtonCounter != null) { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; pagedownButtonCounter.setCount(newUnreadMessageCount, true); } } } if (outbox != null) { for (int b = 0, size = outbox.size(); b < size; b++) { long key = outbox.keyAt(b); int messageId = (int) outbox.get(key); if (key != dialog_id) { continue; } for (int a = 0, size2 = messages.size(); a < size2; a++) { MessageObject obj = messages.get(a); if (obj.isOut() && obj.getId() > 0 && obj.getId() <= messageId) { obj.setIsRead(); if (chatAdapter != null) { chatAdapter.invalidateRowWithMessageObject(obj); } } } break; } } } else if (id == NotificationCenter.historyCleared) { long did = (Long) args[0]; if (did != dialog_id) { return; } int max_id = (Integer) args[1]; if (!pinnedMessageIds.isEmpty()) { pinnedMessageIds.clear(); pinnedMessageObjects.clear(); currentPinnedMessageId = 0; loadedPinnedMessagesCount = 0; totalPinnedMessagesCount = 0; updatePinnedMessageView(true); } boolean updated = false; for (int b = 0; b < messages.size(); b++) { MessageObject obj = messages.get(b); int mid = obj.getId(); if (mid <= 0 || mid > max_id) { continue; } messages.remove(b); b--; messagesDict[0].remove(mid); ArrayList dayArr = messagesByDays.get(obj.dateKey); if (dayArr != null) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); if (b >= 0 && b < messages.size()) { messages.remove(b); b--; } } } updated = true; } if (messages.isEmpty()) { if (!endReached[0] && !loading) { showProgressView(false); if (chatListView != null) { chatListView.setEmptyView(null); } if (currentEncryptedChat == null) { maxMessageId[0] = maxMessageId[1] = Integer.MAX_VALUE; minMessageId[0] = minMessageId[1] = Integer.MIN_VALUE; } else { maxMessageId[0] = maxMessageId[1] = Integer.MIN_VALUE; minMessageId[0] = minMessageId[1] = Integer.MAX_VALUE; } maxDate[0] = maxDate[1] = Integer.MIN_VALUE; minDate[0] = minDate[1] = 0; waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loading = true; } else { if (botButtons != null) { botButtons = null; if (chatActivityEnterView != null) { chatActivityEnterView.setButtons(null, false); } } if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { botUser = ""; updateBottomOverlay(); } } } canShowPagedownButton = false; updatePagedownButtonVisibility(true); showMentionDownButton(false, true); removeUnreadPlane(true); if (updated && chatAdapter != null) { chatAdapter.notifyDataSetChanged(false); } } else if (id == NotificationCenter.messagesDeleted) { boolean scheduled = (Boolean) args[2]; if (scheduled != (chatMode == MODE_SCHEDULED)) { return; } ArrayList markAsDeletedMessages = (ArrayList) args[0]; long channelId = (Long) args[1]; processDeletedMessages(markAsDeletedMessages, channelId); } else if (id == NotificationCenter.messageReceivedByServer) { Boolean scheduled = (Boolean) args[6]; if (scheduled != (chatMode == MODE_SCHEDULED)) { return; } Integer msgId = (Integer) args[0]; MessageObject obj = messagesDict[0].get(msgId); if (isThreadChat() && pendingSendMessagesDict.size() > 0) { MessageObject object = pendingSendMessagesDict.get(msgId); if (object != null) { Integer newMsgId = (Integer) args[1]; pendingSendMessagesDict.put(newMsgId, object); } } if (obj != null) { checkChecksHint(); if (obj.shouldRemoveVideoEditedInfo) { obj.videoEditedInfo = null; obj.shouldRemoveVideoEditedInfo = false; } Integer newMsgId = (Integer) args[1]; if (!newMsgId.equals(msgId) && messagesDict[0].indexOfKey(newMsgId) >= 0) { MessageObject removed = messagesDict[0].get(msgId); messagesDict[0].remove(msgId); if (removed != null) { int index = messages.indexOf(removed); messages.remove(index); ArrayList dayArr = messagesByDays.get(removed.dateKey); dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); if (index >= 0 && index < messages.size()) { messages.remove(index); } } if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } } return; } TLRPC.Message newMsgObj = (TLRPC.Message) args[2]; Long grouped_id; if (args.length >= 4) { grouped_id = (Long) args[4]; } else { grouped_id = 0L; } boolean mediaUpdated = false; boolean updatedForward = false; if (newMsgObj != null) { try { updatedForward = obj.isForwarded() && (obj.messageOwner.reply_markup == null && newMsgObj.reply_markup != null || !obj.messageOwner.message.equals(newMsgObj.message)); mediaUpdated = updatedForward || obj.messageOwner.params != null && obj.messageOwner.params.containsKey("query_id") || newMsgObj.media != null && obj.messageOwner.media != null && !newMsgObj.media.getClass().equals(obj.messageOwner.media.getClass()); } catch (Exception e) { FileLog.e(e); } if (obj.getGroupId() != 0 && newMsgObj.grouped_id != 0) { MessageObject.GroupedMessages oldGroup = groupedMessagesMap.get(obj.getGroupId()); if (oldGroup != null) { groupedMessagesMap.put(newMsgObj.grouped_id, oldGroup); } obj.localSentGroupId = obj.messageOwner.grouped_id; obj.messageOwner.grouped_id = grouped_id; } TLRPC.MessageFwdHeader fwdHeader = obj.messageOwner.fwd_from; obj.messageOwner = newMsgObj; if (fwdHeader != null && newMsgObj.fwd_from != null && !TextUtils.isEmpty(newMsgObj.fwd_from.from_name)) { obj.messageOwner.fwd_from = fwdHeader; } obj.generateThumbs(true); obj.setType(); if (newMsgObj.media instanceof TLRPC.TL_messageMediaGame) { obj.applyNewText(); } } if (updatedForward) { obj.measureInlineBotButtons(); } messagesDict[0].remove(msgId); messagesDict[0].put(newMsgId, obj); obj.messageOwner.id = newMsgId; obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; obj.forceUpdate = mediaUpdated; addReplyMessageOwner(obj, msgId); if (args.length >= 6) { obj.applyMediaExistanceFlags((Integer) args[5]); } addToPolls(obj, null); ArrayList messArr = new ArrayList<>(); messArr.add(obj); if (currentEncryptedChat == null) { getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode == MODE_SCHEDULED, null); } if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(obj, false); } if (chatLayoutManager != null) { if (mediaUpdated && chatLayoutManager.findFirstVisibleItemPosition() == 0) { moveScrollToLastMessage(false); } } if (obj == null || obj.messageOwner == null || !obj.messageOwner.silent) { getNotificationsController().playOutChatSound(); } } } else if (id == NotificationCenter.messageReceivedByAck) { Integer msgId = (Integer) args[0]; MessageObject obj = messagesDict[0].get(msgId); if (obj != null) { obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(obj, false); } } } else if (id == NotificationCenter.messageSendError) { Integer msgId = (Integer) args[0]; MessageObject obj = messagesDict[0].get(msgId); if (obj != null) { obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; updateVisibleRows(); } } else if (id == NotificationCenter.groupCallUpdated) { Long chatId = (Long) args[0]; if (dialog_id == -chatId) { groupCall = getMessagesController().getGroupCall(currentChat.id, false); if (fragmentContextView != null) { fragmentContextView.checkCall(openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150); } checkGroupCallJoin(false); } } else if (id == NotificationCenter.didLoadChatInviter) { long chatId = (Long) args[0]; if (dialog_id == -chatId && chatInviterId == 0) { chatInviterId = (Long) args[1]; if (chatInfo != null) { chatInfo.inviterId = chatInviterId; } updateInfoTopView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); } } else if (id == NotificationCenter.chatInfoDidLoad) { TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0]; if (currentChat != null && chatFull.id == currentChat.id) { if (chatFull instanceof TLRPC.TL_channelFull) { if (currentChat.megagroup) { int lastDate = 0; if (chatFull.participants != null) { for (int a = 0; a < chatFull.participants.participants.size(); a++) { lastDate = Math.max(chatFull.participants.participants.get(a).date, lastDate); } } if (lastDate == 0 || Math.abs(System.currentTimeMillis() / 1000 - lastDate) > 60 * 60) { getMessagesController().loadChannelParticipants(currentChat.id); } } if (chatFull.participants == null && chatInfo != null) { chatFull.participants = chatInfo.participants; } } showGigagroupConvertAlert(); long prevLinkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; chatInfo = chatFull; groupCall = getMessagesController().getGroupCall(currentChat.id, true); if (ChatObject.isChannel(currentChat) && currentChat.megagroup && fragmentContextView != null) { fragmentContextView.checkCall(openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150); } loadSendAsPeers(false); if (chatActivityEnterView != null) { chatActivityEnterView.updateSendAsButton(false); chatActivityEnterView.updateFieldHint(false); } if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } if (prevLinkedChatId != chatInfo.linked_chat_id) { if (prevLinkedChatId != 0) { TLRPC.Chat chat = getMessagesController().getChat(prevLinkedChatId); getMessagesController().startShortPoll(chat, classGuid, true); } if (chatInfo.linked_chat_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(chatInfo.linked_chat_id); if (chat != null && chat.megagroup) { getMessagesController().startShortPoll(chat, classGuid, false); } } } boolean animated = openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150; checkActionBarMenu(animated); if (chatInviterId == 0) { fillInviterId(true); updateInfoTopView(animated); } if (chatActivityEnterView != null) { chatActivityEnterView.setChatInfo(chatInfo); } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().setChatInfo(chatInfo); } if (!isThreadChat()) { if (avatarContainer != null) { avatarContainer.updateOnlineCount(); avatarContainer.updateSubtitle(); } if (!inMenuMode && !loadingPinnedMessagesList && !pinnedMessageIds.isEmpty() && chatInfo.pinned_msg_id > pinnedMessageIds.get(0)) { getMediaDataController().loadPinnedMessages(dialog_id, 0, chatInfo.pinned_msg_id); loadingPinnedMessagesList = true; } } if (chatInfo instanceof TLRPC.TL_chatFull) { hasBotsCommands = false; botInfo.clear(); botsCount = 0; URLSpanBotCommand.enabled = false; for (int a = 0; a < chatInfo.participants.participants.size(); a++) { TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); TLRPC.User user = getMessagesController().getUser(participant.user_id); if (user != null && user.bot) { URLSpanBotCommand.enabled = true; botsCount++; if (!isThreadChat()) { hasBotsCommands = true; } getMediaDataController().loadBotInfo(user.id, -chatInfo.id, true, classGuid); } } if (chatListView != null) { chatListView.invalidateViews(); } } else if (chatInfo instanceof TLRPC.TL_channelFull) { hasBotsCommands = false; botInfo.clear(); botsCount = 0; URLSpanBotCommand.enabled = !chatInfo.bot_info.isEmpty() && currentChat != null && currentChat.megagroup; botsCount = chatInfo.bot_info.size(); for (int a = 0; a < chatInfo.bot_info.size(); a++) { TLRPC.BotInfo bot = chatInfo.bot_info.get(a); if (!isThreadChat() && !bot.commands.isEmpty() && (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup)) { hasBotsCommands = true; } botInfo.put(bot.user_id, bot); } if (chatListView != null) { chatListView.invalidateViews(); } if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().setBotInfo(botInfo); } if (chatActivityEnterView != null) { chatActivityEnterView.setBotInfo(botInfo); } } } if (chatActivityEnterView != null) { chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands, true); } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().setBotsCount(botsCount); } if (chatMode == 0 && ChatObject.isChannel(currentChat) && mergeDialogId == 0 && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } if (mergeDialogId != 0 && endReached[0]) { checkScrollForLoad(false); } } checkGroupCallJoin((Boolean) args[3]); checkThemeEmoticon(); if (pendingRequestsDelegate != null) { pendingRequestsDelegate.setChatInfo(chatInfo, true); } } } else if (id == NotificationCenter.chatInfoCantLoad) { long chatId = (Long) args[0]; if (currentChat != null && currentChat.id == chatId) { int reason = (Integer) args[1]; if (getParentActivity() == null || closeChatDialog != null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); if (reason == 0) { if (currentChat instanceof TLRPC.TL_channelForbidden) { builder.setMessage(LocaleController.getString("ChannelCantOpenBannedByAdmin", R.string.ChannelCantOpenBannedByAdmin)); } else { builder.setTitle(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate)); builder.setMessage(LocaleController.getString("ChannelCantOpenPrivate2", R.string.ChannelCantOpenPrivate2)); } } else if (reason == 1) { builder.setMessage(LocaleController.getString("ChannelCantOpenNa", R.string.ChannelCantOpenNa)); } else if (reason == 2) { builder.setMessage(LocaleController.getString("ChannelCantOpenBanned", R.string.ChannelCantOpenBanned)); } else if (reason == 3) { builder.setTitle(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate)); builder.setMessage(LocaleController.getString("JoinByPeekChannelText", R.string.JoinByPeekChannelText)); } builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); if (showDialog(closeChatDialog = builder.create()) == null) { showCloseChatDialogLater = true; } loading = false; showProgressView(false); if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(false); } } } else if (id == NotificationCenter.contactsDidLoad) { updateTopPanel(true); if (!isThreadChat() && avatarContainer != null) { avatarContainer.updateSubtitle(); } } else if (id == NotificationCenter.encryptedChatUpdated) { TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) args[0]; if (currentEncryptedChat != null && chat.id == currentEncryptedChat.id) { currentEncryptedChat = chat; updateTopPanel(true); updateSecretStatus(); if (suggestEmojiPanel != null) { suggestEmojiPanel.fireUpdate(); } if (chatActivityEnterView != null) { chatActivityEnterView.setAllowStickersAndGifs(true, true, true); chatActivityEnterView.checkRoundVideo(); } if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().setNeedBotContext(!chatActivityEnterView.isEditingMessage()); } } } else if (id == NotificationCenter.messagesReadEncrypted) { int encId = (Integer) args[0]; if (currentEncryptedChat != null && currentEncryptedChat.id == encId) { int date = (Integer) args[1]; for (MessageObject obj : messages) { if (!obj.isOut()) { continue; } else if (obj.isOut() && !obj.isUnread()) { break; } if (obj.messageOwner.date - 1 <= date) { obj.setIsRead(); if (chatAdapter != null) { chatAdapter.invalidateRowWithMessageObject(obj); } } } } } else if (id == NotificationCenter.removeAllMessagesFromDialog) { long did = (Long) args[0]; if (dialog_id == did) { if (threadMessageId != 0) { if (forwardEndReached[0]) { forwardEndReached[0] = false; hideForwardEndReached = false; chatAdapter.notifyItemInserted(0); } getMessagesController().addToViewsQueue(threadMessageObject); } else { clearHistory((Boolean) args[1], (TLRPC.TL_updates_channelDifferenceTooLong) args[2]); } } } else if (id == NotificationCenter.screenshotTook) { updateInformationForScreenshotDetector(); } else if (id == NotificationCenter.blockedUsersDidLoad) { if (currentUser != null && !UserObject.isReplyUser(currentUser)) { boolean oldValue = userBlocked; userBlocked = getMessagesController().blockePeers.indexOfKey(currentUser.id) >= 0; if (oldValue != userBlocked) { updateBottomOverlay(); } } } else if (id == NotificationCenter.fileNewChunkAvailable) { MessageObject messageObject = (MessageObject) args[0]; long finalSize = (Long) args[3]; if (finalSize != 0 && dialog_id == messageObject.getDialogId()) { MessageObject currentObject = messagesDict[0].get(messageObject.getId()); if (currentObject != null && currentObject.messageOwner.media.document != null) { currentObject.messageOwner.media.document.size = (int) finalSize; updateVisibleRows(); } } } else if (id == NotificationCenter.didCreatedNewDeleteTask) { long dialogId = (Long) args[0]; if (dialogId != dialog_id) { return; } SparseArray> mids = (SparseArray>) args[1]; boolean changed = false; for (int i = 0; i < mids.size(); i++) { int key = mids.keyAt(i); ArrayList arr = mids.get(key); for (int a = 0; a < arr.size(); a++) { Integer mid = arr.get(a); MessageObject messageObject = messagesDict[0].get(mid); if (messageObject != null) { messageObject.messageOwner.destroyTime = key; changed = true; } } } if (changed) { updateVisibleRows(); } } else if (id == NotificationCenter.messagePlayingDidStart) { MessageObject messageObject = (MessageObject) args[0]; if (messageObject.eventId != 0) { return; } sendSecretMessageRead(messageObject, true); if ((messageObject.isRoundVideo() || messageObject.isVideo()) && fragmentView != null && fragmentView.getParent() != null) { MediaController.getInstance().setTextureView(createTextureView(true), aspectRatioFrameLayout, videoPlayerContainer, true); updateTextureViewPosition(true); } if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject messageObject1 = cell.getMessageObject(); if (messageObject1 != null) { boolean isVideo = messageObject1.isVideo(); if (messageObject1.isRoundVideo() || isVideo) { cell.checkVideoPlayback(!messageObject.equals(messageObject1), null); if (!MediaController.getInstance().isPlayingMessage(messageObject1)) { if (isVideo && !MediaController.getInstance().isGoingToShowMessageObject(messageObject1)) { AnimatedFileDrawable animation = cell.getPhotoImage().getAnimation(); if (animation != null) { animation.start(); } } if (messageObject1.audioProgress != 0) { messageObject1.resetPlayingProgress(); cell.invalidate(); } } else if (isVideo) { cell.updateButtonState(false, true, false); } if (messageObject1.isRoundVideo()) { int position = chatListView.getChildAdapterPosition(cell); if (position >= 0) { if (MediaController.getInstance().isPlayingMessage(messageObject1)) { boolean keyboardIsVisible = contentView.getKeyboardHeight() >= AndroidUtilities.dp(20); float topPadding = chatListViewPaddingTop - (contentPanTranslation + bottomPanelTranslationY); int offset = (int) ((chatListView.getMeasuredHeight() - topPadding - blurredViewBottomOffset) / 2 - (keyboardIsVisible ? AndroidUtilities.roundMessageSize : AndroidUtilities.roundPlayingMessageSize) / 2 - (cell.reactionsLayoutInBubble == null ? 0 : cell.reactionsLayoutInBubble.totalHeight)); chatLayoutManager.scrollToPositionWithOffset(position, offset, false); } chatAdapter.notifyItemChanged(position); } } } else if (messageObject1.isVoice() || messageObject1.isMusic()) { cell.updateButtonState(false, true, false); } } } } if (mentionContainer != null && mentionContainer.getListView() != null) { count = mentionContainer.getListView().getChildCount(); for (int a = 0; a < count; a++) { View view = mentionContainer.getListView().getChildAt(a); if (view instanceof ContextLinkCell) { ContextLinkCell cell = (ContextLinkCell) view; MessageObject messageObject1 = cell.getMessageObject(); if (messageObject1 != null && (messageObject1.isVoice() || messageObject1.isMusic())) { cell.updateButtonState(false, true); } } } } } } else if (id == NotificationCenter.messagePlayingGoingToStop) { boolean injecting = (Boolean) args[1]; if (injecting) { contentView.removeView(videoPlayerContainer); videoPlayerContainer = null; videoTextureView = null; aspectRatioFrameLayout = null; } else { if (chatListView != null && videoPlayerContainer != null && videoPlayerContainer.getTag() != null) { MessageObject messageObject = (MessageObject) args[0]; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject messageObject1 = cell.getMessageObject(); if (messageObject == messageObject1) { AnimatedFileDrawable animation = cell.getPhotoImage().getAnimation(); if (animation != null) { Bitmap bitmap = animation.getAnimatedBitmap(); if (bitmap != null) { try { Bitmap src = videoTextureView.getBitmap(bitmap.getWidth(), bitmap.getHeight()); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(src, 0, 0, null); src.recycle(); } catch (Throwable e) { FileLog.e(e); } } animation.seekTo(messageObject.audioProgressMs, !getFileLoader().isLoadingVideo(messageObject.getDocument(), true)); } break; } } } } } } else if (id == NotificationCenter.messagePlayingDidReset || id == NotificationCenter.messagePlayingPlayStateChanged) { if (id == NotificationCenter.messagePlayingDidReset) { AndroidUtilities.runOnUIThread(destroyTextureViewRunnable); } int messageId = (int) args[0]; if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject messageObject = cell.getMessageObject(); if (messageObject != null) { if (messageObject.isVoice() || messageObject.isMusic()) { cell.updateButtonState(false, true, false); } else if (messageObject.isVideo()) { cell.updateButtonState(false, true, false); if (!MediaController.getInstance().isPlayingMessage(messageObject) && !MediaController.getInstance().isGoingToShowMessageObject(messageObject)) { AnimatedFileDrawable animation = cell.getPhotoImage().getAnimation(); if (animation != null) { animation.start(); } } } else if (messageObject.isRoundVideo()) { if (!MediaController.getInstance().isPlayingMessage(messageObject)) { Bitmap bitmap = null; if (id == NotificationCenter.messagePlayingDidReset && cell.getMessageObject().getId() == messageId && videoTextureView != null) { bitmap = videoTextureView.getBitmap(); if (bitmap != null && bitmap.getPixel(0, 0) == Color.TRANSPARENT) { bitmap = null; } } cell.checkVideoPlayback(true, bitmap); } int position = chatListView.getChildAdapterPosition(cell); messageObject.forceUpdate = true; if (position >= 0) { chatAdapter.notifyItemChanged(position); } } } } } if (mentionContainer != null && mentionContainer.getListView() != null) { count = mentionContainer.getListView().getChildCount(); for (int a = 0; a < count; a++) { View view = mentionContainer.getListView().getChildAt(a); if (view instanceof ContextLinkCell) { ContextLinkCell cell = (ContextLinkCell) view; MessageObject messageObject = cell.getMessageObject(); if (messageObject != null && (messageObject.isVoice() || messageObject.isMusic())) { cell.updateButtonState(false, true); } } } } } } else if (id == NotificationCenter.messagePlayingProgressDidChanged) { Integer mid = (Integer) args[0]; if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject playing = cell.getMessageObject(); if (playing != null && playing.getId() == mid) { MessageObject player = MediaController.getInstance().getPlayingMessageObject(); if (player != null && !cell.getSeekBar().isDragging()) { playing.audioProgress = player.audioProgress; playing.audioProgressSec = player.audioProgressSec; playing.audioPlayerDuration = player.audioPlayerDuration; cell.updatePlayingMessageProgress(); if (drawLaterRoundProgressCell == cell) { fragmentView.invalidate(); } } break; } } } } } else if (id == NotificationCenter.didUpdatePollResults) { long pollId = (Long) args[0]; ArrayList arrayList = polls.get(pollId); if (arrayList != null) { TLRPC.TL_poll poll = (TLRPC.TL_poll) args[1]; TLRPC.PollResults results = (TLRPC.PollResults) args[2]; View pollView = null; boolean isVotedChanged = false; boolean isQuiz = false; for (int a = 0, N = arrayList.size(); a < N; a++) { MessageObject object = arrayList.get(a); boolean isVoted = object.isVoted(); TLRPC.TL_messageMediaPoll media = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (poll != null) { media.poll = poll; isQuiz = poll.quiz; } else if (media.poll != null) { isQuiz = media.poll.quiz; } MessageObject.updatePollResults(media, results); if (chatAdapter != null) { pollView = chatAdapter.updateRowWithMessageObject(object, true); } if (isVoted != object.isVoted()) { isVotedChanged = true; } } if (isVotedChanged && isQuiz && undoView != null && pollView instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) pollView; if (cell.isAnimatingPollAnswer()) { for (int a = 0, N = results.results.size(); a < N; a++) { TLRPC.TL_pollAnswerVoters voters = results.results.get(a); if (voters.chosen) { if (voters.correct) { fireworksOverlay.start(); pollView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } else { ((ChatMessageCell) pollView).shakeView(); pollView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); showPollSolution(cell.getMessageObject(), results); cell.showHintButton(false, true, 0); } break; } } } } } } else if (id == NotificationCenter.didUpdateReactions) { long did = (Long) args[0]; if (did == dialog_id || did == mergeDialogId) { int msgId = (Integer) args[1]; MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); if (messageObject != null) { MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); messageObject.forceUpdate = true; messageObject.reactionsChanged = true; updateMessageAnimated(messageObject, true); } } } else if (id == NotificationCenter.didVerifyMessagesStickers) { ArrayList messages = (ArrayList) args[0]; for (int a = 0, N = messages.size(); a < N; a++) { TLRPC.Message message = messages.get(a); MessageObject existMessageObject = messagesDict[0].get(message.id); if (existMessageObject != null) { existMessageObject.messageOwner.stickerVerified = message.stickerVerified; existMessageObject.setType(); if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(existMessageObject, false); } } } } else if (id == NotificationCenter.updateMessageMedia) { TLRPC.Message message = (TLRPC.Message) args[0]; MessageObject existMessageObject = messagesDict[0].get(message.id); if (existMessageObject != null) { existMessageObject.messageOwner.media = message.media; existMessageObject.messageOwner.attachPath = message.attachPath; existMessageObject.generateThumbs(false); if (existMessageObject.getGroupId() != 0 && (existMessageObject.photoThumbs == null || existMessageObject.photoThumbs.isEmpty())) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(existMessageObject.getGroupId()); if (groupedMessages != null) { int idx = groupedMessages.messages.indexOf(existMessageObject); if (idx >= 0) { int updateCount = groupedMessages.messages.size(); MessageObject messageObject = null; if (idx > 0 && idx < groupedMessages.messages.size() - 1) { MessageObject.GroupedMessages slicedGroup = new MessageObject.GroupedMessages(); slicedGroup.groupId = Utilities.random.nextLong(); slicedGroup.messages.addAll(groupedMessages.messages.subList(idx + 1, groupedMessages.messages.size())); for (int b = 0; b < slicedGroup.messages.size(); b++) { slicedGroup.messages.get(b).localGroupId = slicedGroup.groupId; groupedMessages.messages.remove(idx + 1); } groupedMessagesMap.put(slicedGroup.groupId, slicedGroup); messageObject = slicedGroup.messages.get(slicedGroup.messages.size() - 1); slicedGroup.calculate(); } groupedMessages.messages.remove(idx); if (groupedMessages.messages.isEmpty()) { groupedMessagesMap.remove(groupedMessages.groupId); } else { if (messageObject == null) { messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); } groupedMessages.calculate(); int index = messages.indexOf(messageObject); if (index >= 0) { if (chatAdapter != null) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); } } } } } } if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) { existMessageObject.setType(); if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(existMessageObject, false); } } else { updateVisibleRows(); } } } else if (id == NotificationCenter.voiceTranscriptionUpdate) { if (chatAdapter != null) { MessageObject messageObject = (MessageObject) args[0]; long transcriptionId = 0; String transcriptionText = null; if (args[1] != null) { transcriptionId = (Long) args[1]; transcriptionText = (String) args[2]; } ArrayList messages = chatAdapter.isFrozen ? chatAdapter.frozenMessages : ChatActivity.this.messages; if (messages != null && !messages.contains(messageObject) && args[1] != null) { for (int a = 0; a < messages.size(); ++a) { if (messages.get(a) != null && messages.get(a).messageOwner != null && (messages.get(a).messageOwner.voiceTranscriptionId == transcriptionId || messageObject != null && messageObject.getId() == messages.get(a).getId() && messageObject.getDialogId() == messages.get(a).getDialogId())) { messageObject = messages.get(a); break; } } } if (messageObject != null) { if (transcriptionText != null && messageObject.messageOwner != null) { messageObject.messageOwner.voiceTranscription = transcriptionText; } boolean wasOpen = messageObject.isVoiceTranscriptionOpen(); if (args.length > 3 && args[3] != null) { messageObject.messageOwner.voiceTranscriptionOpen = (Boolean) args[3]; } if (args.length > 4 && args[4] != null) { messageObject.messageOwner.voiceTranscriptionFinal = (Boolean) args[4]; } int index = messages.indexOf(messageObject); if (index >= 0 && index < messages.size()) { int position = index + chatAdapter.messagesStartRow; chatAdapter.updateRowAtPosition(position); for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == messageObject) { int top = child.getTop() - (int) chatListViewPaddingTop; int halfHeight = (int) ((chatListView.getMeasuredHeight() - chatListViewPaddingTop) / 2); if (messageObject.measureVoiceTranscriptionHeight() > halfHeight * .4f) { chatLayoutManager.scrollToPositionWithOffset(position, (top > halfHeight * .6f && messageObject.isVoiceTranscriptionOpen() ? (int) (halfHeight * .6f) : top), false); } break; } } } } } } else if (id == NotificationCenter.animatedEmojiDocumentLoaded) { if (chatAdapter != null) { MessageObject messageObject = (MessageObject) args[0]; if (messageObject != null) { ArrayList messages = chatAdapter.isFrozen ? chatAdapter.frozenMessages : ChatActivity.this.messages; int index = messages.indexOf(messageObject); if (index >= 0 && index < messages.size()) { int position = index + chatAdapter.messagesStartRow; chatAdapter.updateRowAtPosition(position); } } } } else if (id == NotificationCenter.replaceMessagesObjects) { long did = (long) args[0]; if (did != dialog_id && did != mergeDialogId) { return; } int loadIndex = did == dialog_id ? 0 : 1; ArrayList messageObjects = (ArrayList) args[1]; replaceMessageObjects(messageObjects, loadIndex, false); } else if (id == NotificationCenter.notificationsSettingsUpdated) { updateTitleIcons(); if (ChatObject.isChannel(currentChat) || UserObject.isReplyUser(currentUser)) { updateBottomOverlay(); } } else if (id == NotificationCenter.replyMessagesDidLoad) { long did = (Long) args[0]; if (did == dialog_id) { ArrayList loadedMessages = (ArrayList) args[1]; LongSparseArray>> replyMessageOwners = (LongSparseArray>>) args[2]; for (int a = 0, N = loadedMessages.size(); a < N; a++) { MessageObject obj = loadedMessages.get(a); repliesMessagesDict.put(obj.getId(), obj); } if (replyMessageOwners != null) { for (int a = 0, N = replyMessageOwners.size(); a < N; a++) { SparseArray> sparseArray = replyMessageOwners.valueAt(a); for (int c = 0, N3 = sparseArray.size(); c < N3; c++) { ArrayList arrayList = sparseArray.valueAt(c); for (int b = 0, N2 = arrayList.size(); b < N2; b++) { addReplyMessageOwner(arrayList.get(b), 0); } } } } updateVisibleRows(); } else if (waitingForReplies.size() != 0 && ChatObject.isChannel(currentChat) && !currentChat.megagroup && chatInfo != null && did == -chatInfo.linked_chat_id) { checkWaitingForReplies(); } updateReplyMessageHeader(true); } else if (id == NotificationCenter.didLoadPinnedMessages) { long did = (Long) args[0]; if (did == dialog_id) { ArrayList ids = (ArrayList) args[1]; boolean pin = (Boolean) args[2]; ArrayList arrayList = (ArrayList) args[3]; HashMap dict = null; if (ids != null) { HashMap replaceObjects = (HashMap) args[4]; int maxId = (Integer) args[5]; int totalPinnedCount = (Integer) args[6]; boolean endReached = (Boolean) args[7]; HashMap oldPinned = new HashMap<>(pinnedMessageObjects); if (replaceObjects != null) { loadingPinnedMessagesList = false; if (maxId == 0) { pinnedMessageIds.clear(); pinnedMessageObjects.clear(); } totalPinnedMessagesCount = totalPinnedCount; pinnedEndReached = endReached; } boolean updated = false; if (arrayList != null) { getMediaDataController().loadReplyMessagesForMessages(arrayList, dialog_id, false, null); } for (int a = 0, N = ids.size(); a < N; a++) { Integer mid = ids.get(a); if (pin) { if (pinnedMessageObjects.containsKey(mid)) { continue; } pinnedMessageIds.add(mid); MessageObject object = oldPinned.get(mid); if (object == null) { object = messagesDict[0].get(mid); } if (object == null && arrayList != null) { if (dict == null) { dict = new HashMap<>(); for (int b = 0, N2 = arrayList.size(); b < N2; b++) { MessageObject obj = arrayList.get(b); if (obj != null) { dict.put(obj.getId(), obj); } } } object = dict.get(mid); } if (object == null && replaceObjects != null) { object = replaceObjects.get(mid); } pinnedMessageObjects.put(mid, object); if (replaceObjects == null) { totalPinnedMessagesCount++; } } else { if (!pinnedMessageObjects.containsKey(mid)) { continue; } pinnedMessageObjects.remove(mid); pinnedMessageIds.remove(mid); if (replaceObjects == null) { totalPinnedMessagesCount--; } } loadedPinnedMessagesCount = pinnedMessageIds.size(); if (chatAdapter != null) { MessageObject obj = messagesDict[0].get(mid); if (obj != null) { if (obj.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(obj.getGroupId()); if (groupedMessages != null) { int index = messages.indexOf(groupedMessages.messages.get(groupedMessages.messages.size() - 1)); if (index >= 0) { chatAdapter.notifyItemRangeChanged(index, groupedMessages.messages.size()); } } } else { chatAdapter.updateRowWithMessageObject(obj, false); } } } updated = true; } if (updated) { if (chatMode == MODE_PINNED && avatarContainer != null) { avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } Collections.sort(pinnedMessageIds, (o1, o2) -> o2.compareTo(o1)); if (pinnedMessageIds.isEmpty()) { hidePinnedMessageView(true); } else { updateMessagesVisiblePart(false); } } if (chatMode == MODE_PINNED) { if (pin) { if (arrayList != null) { processNewMessages(arrayList); } } else { processDeletedMessages(ids, ChatObject.isChannel(currentChat) ? dialog_id : 0); } } } else { if (pin) { for (int a = 0, N = arrayList.size(); a < N; a++) { MessageObject message = arrayList.get(a); if (pinnedMessageObjects.containsKey(message.getId())) { pinnedMessageObjects.put(message.getId(), message); } loadingPinnedMessages.remove(message.getId()); } getMediaDataController().loadReplyMessagesForMessages(arrayList, dialog_id, false, null); updateMessagesVisiblePart(false); } else { pinnedMessageIds.clear(); pinnedMessageObjects.clear(); currentPinnedMessageId = 0; loadedPinnedMessagesCount = 0; totalPinnedMessagesCount = 0; hidePinnedMessageView(true); } } } } else if (id == NotificationCenter.didReceivedWebpages) { ArrayList arrayList = (ArrayList) args[0]; boolean updated = false; for (int a = 0; a < arrayList.size(); a++) { TLRPC.Message message = arrayList.get(a); long did = MessageObject.getDialogId(message); if (did != dialog_id && did != mergeDialogId) { continue; } MessageObject currentMessage = messagesDict[did == dialog_id ? 0 : 1].get(message.id); if (currentMessage != null) { currentMessage.messageOwner.media = new TLRPC.TL_messageMediaWebPage(); currentMessage.messageOwner.media.webpage = message.media.webpage; currentMessage.generateThumbs(true); updated = true; } } if (updated) { updateVisibleRows(); } } else if (id == NotificationCenter.didReceivedWebpagesInUpdates) { if (foundWebPage != null) { LongSparseArray hashMap = (LongSparseArray) args[0]; for (int a = 0; a < hashMap.size(); a++) { TLRPC.WebPage webPage = hashMap.valueAt(a); if (webPage.id == foundWebPage.id) { showFieldPanelForWebPage(!(webPage instanceof TLRPC.TL_webPageEmpty), webPage, false); break; } } } } else if (id == NotificationCenter.messagesReadContent) { long did = (Long) args[0]; if (did != dialog_id && (ChatObject.isChannel(currentChat) || did != 0)) { return; } ArrayList arrayList = (ArrayList) args[1]; for (int a = 0, N = arrayList.size(); a < N; a++) { int mid = arrayList.get(a); MessageObject currentMessage = messagesDict[0].get(mid); if (currentMessage != null) { currentMessage.setContentIsRead(); if (currentMessage.messageOwner.mentioned) { newMentionsCount--; if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { if (mentiondownButtonCounter != null) { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } } } if (chatAdapter != null) { chatAdapter.invalidateRowWithMessageObject(currentMessage); } } } } else if (id == NotificationCenter.botInfoDidLoad) { int guid = (Integer) args[1]; if (classGuid == guid || guid == 0) { TLRPC.BotInfo info = (TLRPC.BotInfo) args[0]; if (currentEncryptedChat == null) { if (!info.commands.isEmpty() && !ChatObject.isChannel(currentChat) && !isThreadChat()) { hasBotsCommands = true; } if (info.user_id == 0 && currentUser != null) { info.user_id = currentUser.id; } botInfo.put(info.user_id, info); if (chatAdapter != null) { int prevRow = chatAdapter.botInfoRow; chatAdapter.updateRowsInternal(); if (prevRow < 0 && chatAdapter.botInfoRow >= 0) { chatAdapter.notifyItemInserted(chatAdapter.botInfoRow); } else if (prevRow >= 0 && chatAdapter.botInfoRow < 0) { chatAdapter.notifyItemRemoved(prevRow); } else if (prevRow >= 0 && chatAdapter.botInfoRow >= 0) { chatAdapter.notifyItemChanged(chatAdapter.botInfoRow); } } if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().setBotInfo(botInfo); } if (chatActivityEnterView != null) { chatActivityEnterView.setBotInfo(botInfo); } } if (chatActivityEnterView != null) { chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands, true); hasBotWebView = getMessagesController().getUser(info.user_id).bot_menu_webview; chatActivityEnterView.updateBotWebView(true); } } updateBotButtons(); } } else if (id == NotificationCenter.botKeyboardDidLoad) { if (dialog_id == (Long) args[1]) { TLRPC.Message message = (TLRPC.Message) args[0]; if (message != null && !userBlocked) { botButtons = new MessageObject(currentAccount, message, false, false); checkBotKeyboard(); } else { botButtons = null; if (chatActivityEnterView != null) { if (replyingMessageObject != null && botReplyButtons == replyingMessageObject) { botReplyButtons = null; hideFieldPanel(true); } chatActivityEnterView.setButtons(botButtons); } } } } else if (id == NotificationCenter.chatSearchResultsAvailable) { if (classGuid == (Integer) args[0]) { boolean jumpToMessage = (Boolean) args[6]; if (jumpToMessage) { int messageId = (Integer) args[1]; long did = (Long) args[3]; if (messageId != 0) { scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, true, 0); } else { updateVisibleRows(); } updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (searchItem != null) { searchItem.setShowSearchProgress(false); } } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } } } else if (id == NotificationCenter.chatSearchResultsLoading) { if (classGuid == (Integer) args[0]) { if (searchItem != null) { searchItem.setShowSearchProgress(true); } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } } } else if (id == NotificationCenter.didUpdateMessagesViews) { LongSparseArray channelViews = (LongSparseArray) args[0]; LongSparseArray channelForwards = (LongSparseArray) args[1]; LongSparseArray> channelReplies = (LongSparseArray>) args[2]; boolean addingReplies = (Boolean) args[3]; boolean updated = false; LongSparseArray newGroups = null; ArrayList updatedRows = null; for (int b = 0; b < 2; b++) { LongSparseArray sparseArray = b == 0 ? channelViews : channelForwards; if (sparseArray == null) { continue; } SparseIntArray array = sparseArray.get(dialog_id); if (array != null) { for (int a = 0; a < array.size(); a++) { int messageId = array.keyAt(a); MessageObject messageObject = messagesDict[0].get(messageId); if (messageObject != null) { int newValue = array.get(messageId); if (b == 0) { if (newValue <= messageObject.messageOwner.views) { continue; } messageObject.messageOwner.views = newValue; } else { if (newValue <= messageObject.messageOwner.forwards) { continue; } messageObject.messageOwner.forwards = newValue; } if (messageObject.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); if (groupedMessages != null) { if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); } } if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(messageObject, false); } } } } } if (channelReplies != null) { SparseArray array = channelReplies.get(dialog_id); boolean hasChatInBack = false; if (threadMessageObject != null && parentLayout != null) { for (int a = 0, N = parentLayout.fragmentsStack.size() - 1; a < N; a++) { BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getChatMode() == getChatMode()) { hasChatInBack = true; break; } } } } if (array != null) { for (int a = 0; a < array.size(); a++) { int messageId = array.keyAt(a); MessageObject messageObject = messagesDict[0].get(messageId); if (messageObject != null && messageObject != threadMessageObject) { TLRPC.MessageReplies newValue = array.get(messageId); if (newValue == null || !addingReplies && messageObject.messageOwner.replies != null && newValue.replies_pts <= messageObject.messageOwner.replies.replies_pts && newValue.read_max_id <= messageObject.messageOwner.replies.read_max_id && newValue.max_id <= messageObject.messageOwner.replies.max_id) { continue; } if (addingReplies) { if (!hasChatInBack) { if (messageObject.messageOwner.replies == null) { messageObject.messageOwner.replies = new TLRPC.TL_messageReplies(); } messageObject.messageOwner.replies.replies += newValue.replies; for (int c = 0, N = newValue.recent_repliers.size(); c < N; c++) { messageObject.messageOwner.replies.recent_repliers.remove(newValue.recent_repliers.get(c)); } messageObject.messageOwner.replies.recent_repliers.addAll(0, newValue.recent_repliers); while (messageObject.messageOwner.replies.recent_repliers.size() > 3) { messageObject.messageOwner.replies.recent_repliers.remove(0); } } } else { if (messageObject.messageOwner.replies != null && messageObject.messageOwner.replies.read_max_id > newValue.read_max_id) { newValue.read_max_id = messageObject.messageOwner.replies.read_max_id; } messageObject.messageOwner.replies = newValue; } if (messageObject.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); if (groupedMessages != null) { if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); for (int b = 0, N2 = groupedMessages.messages.size(); b < N2; b++) { groupedMessages.messages.get(b).animateComments = true; } } } else if (chatAdapter != null) { int row = messages.indexOf(messageObject); if (row >= 0) { if (updatedRows == null) { updatedRows = new ArrayList<>(); } updatedRows.add(row + chatAdapter.messagesStartRow); } messageObject.animateComments = true; } updated = true; } } } } if (updated) { if (chatAdapter != null) { if (newGroups != null) { for (int b = 0, N = newGroups.size(); b < N; b++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); if (index >= 0) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } if (updatedRows != null) { for (int b = 0, N = updatedRows.size(); b < N; b++) { chatAdapter.notifyItemChanged(updatedRows.get(b)); } } } updateVisibleRows(); updateReplyMessageHeader(true); } } else if (id == NotificationCenter.peerSettingsDidLoad) { long did = (Long) args[0]; if (did == dialog_id || currentUser != null && currentUser.id == did) { updateTopPanel(!paused); updateInfoTopView(true); } } else if (id == NotificationCenter.newDraftReceived) { long did = (Long) args[0]; if (did == dialog_id) { applyDraftMaybe(true); } } else if (id == NotificationCenter.pinnedInfoDidLoad) { long did = (Long) args[0]; if (did == dialog_id) { ArrayList pinnedMessages = (ArrayList) args[1]; if (chatMode == MODE_PINNED) { pinnedMessageIds = new ArrayList<>(pinnedMessages); pinnedMessageObjects = new HashMap<>((HashMap) args[2]); } else { pinnedMessageIds = pinnedMessages; pinnedMessageObjects = (HashMap) args[2]; } loadedPinnedMessagesCount = pinnedMessageIds.size(); totalPinnedMessagesCount = (Integer) args[3]; pinnedEndReached = (Boolean) args[4]; getMediaDataController().loadReplyMessagesForMessages(new ArrayList<>(pinnedMessageObjects.values()), dialog_id, false, null); if (!inMenuMode && !loadingPinnedMessagesList && totalPinnedMessagesCount == 0 && !pinnedEndReached) { getMediaDataController().loadPinnedMessages(dialog_id, 0, pinnedMessageIds.isEmpty() ? 0 : pinnedMessageIds.get(0)); loadingPinnedMessagesList = true; } } } else if (id == NotificationCenter.userInfoDidLoad) { Long uid = (Long) args[0]; if (currentUser != null && currentUser.id == uid) { userInfo = (TLRPC.UserFull) args[1]; checkThemeEmoticon(); if (chatActivityEnterView != null) { chatActivityEnterView.checkChannelRights(); } if (headerItem != null) { showAudioCallAsIcon = userInfo.phone_calls_available && !inPreviewMode; if (userInfo.phone_calls_available) { if (showAudioCallAsIcon) { if (audioCallIconItem != null) { if (openAnimationStartTime != 0 && audioCallIconItem.getVisibility() != View.VISIBLE) { audioCallIconItem.setAlpha(0f); audioCallIconItem.animate().alpha(1f).setDuration(160).setInterpolator(CubicBezierInterpolator.EASE_IN).setStartDelay(50).start(); } audioCallIconItem.setVisibility(View.VISIBLE); } } else { headerItem.showSubItem(call, true); } if (userInfo.video_calls_available) { headerItem.showSubItem(video_call, true); } else { headerItem.hideSubItem(video_call); } } else { headerItem.hideSubItem(call); headerItem.hideSubItem(video_call); if (audioCallIconItem != null) { audioCallIconItem.setVisibility(View.GONE); } } } checkActionBarMenu(fragmentOpened); if (!inMenuMode && !loadingPinnedMessagesList && !pinnedMessageIds.isEmpty() && userInfo.pinned_msg_id > pinnedMessageIds.get(0)) { getMediaDataController().loadPinnedMessages(dialog_id, 0, userInfo.pinned_msg_id); loadingPinnedMessagesList = true; } } } else if (id == NotificationCenter.didSetNewWallpapper) { if (fragmentView != null) { contentView.setBackgroundImage(Theme.getCachedWallpaper(), Theme.isWallpaperMotion()); progressView2.invalidate(); if (emptyView != null) { emptyView.invalidate(); } if (bigEmptyView != null) { bigEmptyView.invalidate(); } if (floatingDateView != null) { floatingDateView.invalidate(); } chatListView.invalidateViews(); } } else if (id == NotificationCenter.didApplyNewTheme) { if (undoView == null || paused) { return; } Theme.ThemeInfo themeInfo = (Theme.ThemeInfo) args[0]; Theme.ThemeAccent themeAccent = (Theme.ThemeAccent) args[1]; if (!themeInfo.firstAccentIsDefault || themeAccent == null || themeAccent.id != Theme.DEFALT_THEME_ACCENT_ID) { return; } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (preferences.getBoolean("themehint", false)) { return; } preferences.edit().putBoolean("themehint", true).commit(); boolean deleteTheme = (Boolean) args[2]; undoView.showWithAction(0, UndoView.ACTION_THEME_CHANGED, null, () -> { if (themeAccent != null) { Theme.ThemeAccent prevAccent = themeInfo.getAccent(false); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, null, themeAccent.id); if (deleteTheme) { Theme.deleteThemeAccent(themeInfo, prevAccent, true); } } else { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, null, -1); } }); } else if (id == NotificationCenter.goingToPreviewTheme) { isPauseOnThemePreview = true; if (chatLayoutManager != null) { scrollToPositionOnRecreate = chatLayoutManager.findFirstVisibleItemPosition(); RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(scrollToPositionOnRecreate); if (holder != null) { scrollToOffsetOnRecreate = chatListView.getMeasuredHeight() - holder.itemView.getBottom() - chatListView.getPaddingBottom(); } else { scrollToPositionOnRecreate = -1; } } } else if (id == NotificationCenter.channelRightsUpdated) { TLRPC.Chat chat = (TLRPC.Chat) args[0]; if (currentChat != null && chat.id == currentChat.id && chatActivityEnterView != null) { currentChat = chat; chatActivityEnterView.checkChannelRights(); checkRaiseSensors(); updateSecretStatus(); if (currentChat.gigagroup) { updateBottomOverlay(); } } } else if (id == NotificationCenter.updateMentionsCount) { if (dialog_id == (Long) args[0]) { int count = (int) args[1]; if (newMentionsCount > count) { newMentionsCount = count; if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } } } } else if (id == NotificationCenter.audioRecordTooShort) { int guid = (Integer) args[0]; if (guid != classGuid) { return; } int time = (Integer) args[2]; if (time < 100) { showVoiceHint(false, (Boolean) args[1]); } } else if (id == NotificationCenter.videoLoadingStateChanged) { if (chatListView != null) { String fileName = (String) args[0]; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (!(child instanceof ChatMessageCell)) { continue; } ChatMessageCell cell = (ChatMessageCell) child; TLRPC.Document document = cell.getStreamingMedia(); if (document == null) { continue; } if (FileLoader.getAttachFileName(document).equals(fileName)) { cell.updateButtonState(false, true, false); } } } } else if (id == NotificationCenter.scheduledMessagesUpdated) { long did = (Long) args[0]; if (dialog_id == did) { scheduledMessagesCount = (Integer) args[1]; updateScheduledInterface(openAnimationEnded); } } else if (id == NotificationCenter.diceStickersDidLoad) { if (chatListView == null) { return; } int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (!(child instanceof ChatMessageCell)) { continue; } ChatMessageCell cell = (ChatMessageCell) child; if (cell.getMessageObject().isDice()) { cell.setCurrentDiceValue(true); } } } else if (id == NotificationCenter.dialogDeleted) { long did = (Long) args[0]; if (did == dialog_id) { if (parentLayout != null && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) == this) { finishFragment(); } else { removeSelfFromStack(); } } } else if (id == NotificationCenter.needSetDayNightTheme) { Theme.ThemeInfo theme = (Theme.ThemeInfo) args[0]; if (theme != null) { if (chatThemeBottomSheet != null) { chatThemeBottomSheet.setupLightDarkTheme(theme.isDark()); } else { themeDelegate.setCurrentTheme(themeDelegate.chatTheme, true, theme.isDark()); } } } else if (id == NotificationCenter.chatAvailableReactionsUpdated) { long chatId = (long) args[0]; if (chatId == -dialog_id) { chatInfo = getMessagesController().getChatFull(chatId); } } else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) { long dialogId = (long) args[0]; if (dialogId == dialog_id) { reactionsMentionCount = (int) args[1]; ArrayList messages = null; if (args[2] != null) { messages = (ArrayList) args[2]; } if (messages != null) { for (int i = 0; i < messages.size(); i++) { int messageId = messages.get(i); ChatMessageCell cell = findMessageCell(messageId, true); if (cell != null && reactionsMentionCount > 0) { reactionsMentionCount--; getMessagesStorage().markMessageReactionsAsRead(getDialogId(), cell.getMessageObject().getId(), true); AndroidUtilities.runOnUIThread(() -> { playReactionAnimation(messageId); }, 200); } } } if (reactionsMentionCount <= 0) { reactionsMentionCount = 0; getMessagesController().markReactionsAsRead(dialogId); } updateReactionsMentionButton(true); } } } private void checkSecretMessageForLocation(MessageObject messageObject) { if (messageObject.type != 4 || locationAlertShown || SharedConfig.isSecretMapPreviewSet()) { return; } locationAlertShown = true; AlertsCreator.showSecretLocationAlert(getParentActivity(), currentAccount, () -> { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject message = cell.getMessageObject(); if (message.type == 4) { cell.forceResetMessageObject(); } } } }, true, themeDelegate); } private void loadSendAsPeers(boolean animatedUpdate) { if (sendAsPeersObj != null || currentChat == null || !ChatObject.canSendAsPeers(currentChat) || chatActivityEnterView == null) { return; } sendAsPeersObj = getMessagesController().getSendAsPeers(dialog_id); if (sendAsPeersObj != null) { chatActivityEnterView.updateSendAsButton(animatedUpdate); } } private boolean sponsoredMessagesAdded; private void addSponsoredMessages(boolean animated) { if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium()) { return; } ArrayList arrayList = getMessagesController().getSponsoredMessages(dialog_id); if (arrayList == null) { return; } for (int i = 0; i < arrayList.size(); i++) { MessageObject messageObject = arrayList.get(i); messageObject.resetLayout(); long dialogId = MessageObject.getPeerId(messageObject.messageOwner.from_id); int messageId = 0 ; if (messageObject.sponsoredChannelPost != 0) { messageId = messageObject.sponsoredChannelPost; } getMessagesController().ensureMessagesLoaded(dialogId, messageId, null); } sponsoredMessagesAdded = true; processNewMessages(arrayList); } private void checkGroupCallJoin(boolean fromServer) { if (groupCall == null || voiceChatHash == null || !openAnimationEnded) { if (voiceChatHash != null && fromServer && chatInfo != null && chatInfo.call == null && fragmentView != null && getParentActivity() != null) { BulletinFactory.of(this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("LinkHashExpired", R.string.LinkHashExpired)).show(); voiceChatHash = null; } lastCallCheckFromServer = !openAnimationEnded; return; } VoIPHelper.startCall(currentChat, null, voiceChatHash, createGroupCall, !groupCall.call.rtmp_stream, getParentActivity(), ChatActivity.this, getAccountInstance()); voiceChatHash = null; } private void checkWaitingForReplies() { if (waitingForReplies.size() == 0) { return; } ArrayList idsToRemove = null; LongSparseArray newGroups = null; ArrayList updatedRows = null; for (int a = 0, N = waitingForReplies.size(); a < N; a++) { MessageObject object = waitingForReplies.valueAt(a); if (object.replyMessageObject != null) { if (idsToRemove == null) { idsToRemove = new ArrayList<>(); } idsToRemove.add(waitingForReplies.keyAt(a)); if (!(object.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) && object.replyMessageObject.messageOwner.fwd_from != null && MessageObject.getPeerId(object.replyMessageObject.messageOwner.fwd_from.saved_from_peer) == dialog_id && object.replyMessageObject.messageOwner.fwd_from.channel_post != 0) { MessageObject obj = messagesDict[0].get(object.replyMessageObject.messageOwner.fwd_from.channel_post); if (obj != null && obj.messageOwner.replies != null) { obj.messageOwner.replies.replies += 1; obj.animateComments = true; TLRPC.Peer peer = object.messageOwner.from_id; if (peer == null) { peer = object.messageOwner.peer_id; } for (int c = 0, N2 = obj.messageOwner.replies.recent_repliers.size(); c < N2; c++) { if (MessageObject.getPeerId(obj.messageOwner.replies.recent_repliers.get(c)) == MessageObject.getPeerId(peer)) { obj.messageOwner.replies.recent_repliers.remove(c); break; } } obj.messageOwner.replies.recent_repliers.add(0, peer); if (!object.isOut()) { obj.messageOwner.replies.max_id = object.getId(); } getMessagesStorage().updateRepliesCount(currentChat.id, obj.getId(), obj.messageOwner.replies.recent_repliers, obj.messageOwner.replies.max_id, 1); if (obj.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(obj.getGroupId()); if (groupedMessages != null) { if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); for (int b = 0, N2 = groupedMessages.messages.size(); b < N2; b++) { groupedMessages.messages.get(b).animateComments = true; } } } else if (chatAdapter != null) { int row = messages.indexOf(obj); if (row >= 0) { if (updatedRows == null) { updatedRows = new ArrayList<>(); } updatedRows.add(row + chatAdapter.messagesStartRow); } } } } } } if (idsToRemove != null) { for (int a = 0, N = idsToRemove.size(); a < N; a++) { waitingForReplies.remove(idsToRemove.get(a)); } } if (chatAdapter != null) { if (newGroups != null) { for (int b = 0, N = newGroups.size(); b < N; b++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); if (index >= 0) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } if (updatedRows != null) { for (int b = 0, N = updatedRows.size(); b < N; b++) { chatAdapter.notifyItemChanged(updatedRows.get(b)); } } } } private void clearHistory(boolean overwrite, TLRPC.TL_updates_channelDifferenceTooLong differenceTooLong) { if (overwrite) { if (BuildVars.LOGS_ENABLED) { FileLog.d("clear history by overwrite firstLoading=" + firstLoading + " minMessage=" + minMessageId[0] + " topMessage=" + differenceTooLong.dialog.top_message); } if (differenceTooLong.dialog.top_message > minMessageId[0]) { createUnreadMessageAfterId = Math.max(minMessageId[0] + 1, differenceTooLong.dialog.read_inbox_max_id); } forwardEndReached[0] = false; hideForwardEndReached = false; if (chatAdapter != null && chatAdapter.loadingDownRow < 0) { chatAdapter.notifyItemInserted(0); } newUnreadMessageCount = differenceTooLong.dialog.unread_count; newMentionsCount = differenceTooLong.dialog.unread_mentions_count; if (prevSetUnreadCount != newUnreadMessageCount) { if (pagedownButtonCounter != null) { pagedownButtonCounter.setCount(newUnreadMessageCount, openAnimationEnded); } prevSetUnreadCount = newUnreadMessageCount; updatePagedownButtonVisibility(true); } if (newMentionsCount != differenceTooLong.dialog.unread_mentions_count) { newMentionsCount = differenceTooLong.dialog.unread_mentions_count; if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { if (mentiondownButtonCounter != null) { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } showMentionDownButton(true, true); } } checkScrollForLoad(false); return; } messages.clear(); waitingForLoad.clear(); messagesByDays.clear(); groupedMessagesMap.clear(); threadMessageAdded = false; for (int a = 1; a >= 0; a--) { messagesDict[a].clear(); if (currentEncryptedChat == null) { maxMessageId[a] = Integer.MAX_VALUE; minMessageId[a] = Integer.MIN_VALUE; } else { maxMessageId[a] = Integer.MIN_VALUE; minMessageId[a] = Integer.MAX_VALUE; } maxDate[a] = Integer.MIN_VALUE; minDate[a] = 0; selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); if (botButtons != null) { botButtons = null; if (chatActivityEnterView != null) { chatActivityEnterView.setButtons(null, false); } } if (progressView != null) { showProgressView(false); chatListView.setEmptyView(emptyViewContainer); } if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(false); } if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { botUser = ""; updateBottomOverlay(); } } public boolean processSwitchButton(TLRPC.TL_keyboardButtonSwitchInline button) { if (inlineReturn == 0 || button.same_peer || parentLayout == null) { return false; } String query = "@" + currentUser.username + " " + button.query; if (inlineReturn == dialog_id) { inlineReturn = 0; chatActivityEnterView.setFieldText(query); } else { getMediaDataController().saveDraft(inlineReturn, 0, query, null, null, false); if (parentLayout.fragmentsStack.size() > 1) { BaseFragment prevFragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2); if (prevFragment instanceof ChatActivity && ((ChatActivity) prevFragment).dialog_id == inlineReturn) { finishFragment(); } else { Bundle bundle = new Bundle(); if (DialogObject.isEncryptedDialog(inlineReturn)) { bundle.putInt("enc_id", DialogObject.getEncryptedChatId(inlineReturn)); } else if (DialogObject.isUserDialog(inlineReturn)) { bundle.putLong("user_id", inlineReturn); } else { bundle.putLong("chat_id", -inlineReturn); } addToPulledDialogsMyself(); presentFragment(new ChatActivity(bundle), true); } } } return true; } private void showGigagroupConvertAlert() { if (chatInfo != null && !paused && currentChat.creator && currentChat.megagroup && !currentChat.gigagroup && chatInfo.pending_suggestions.contains("CONVERT_GIGAGROUP") && visibleDialog == null) { AndroidUtilities.runOnUIThread(() -> { if (chatInfo != null && !paused && currentChat.creator && currentChat.megagroup && !currentChat.gigagroup && chatInfo.pending_suggestions.contains("CONVERT_GIGAGROUP") && visibleDialog == null) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); int lastShowTime = preferences.getInt("group_convert_time", 0); int timeout = BuildVars.DEBUG_PRIVATE_VERSION ? 120 : 60 * 60 * 24 * 7; int currentTime = getConnectionsManager().getCurrentTime(); if (Math.abs(currentTime - lastShowTime) >= timeout) { if (visibleDialog == null && getParentActivity() != null) { preferences.edit().putInt("group_convert_time", currentTime).commit(); showDialog(AlertsCreator.createGigagroupConvertAlert(getParentActivity(), (dialog, which) -> showDialog(new GigagroupConvertAlert(getParentActivity(), ChatActivity.this) { @Override protected void onCovert() { getMessagesController().convertToGigaGroup(getParentActivity(), currentChat, ChatActivity.this, (result) -> { if (result) { undoView.showWithAction(0, UndoView.ACTION_GIGAGROUP_SUCCESS, null); } }); } @Override protected void onCancel() { undoView.showWithAction(0, UndoView.ACTION_GIGAGROUP_CANCEL, null); getMessagesController().removeSuggestion(dialog_id, "CONVERT_GIGAGROUP"); } }), (dialog, which) -> undoView.showWithAction(0, UndoView.ACTION_GIGAGROUP_CANCEL, null)).create()); } } } }, 1000); } } private void addReplyMessageOwner(MessageObject obj, Integer oldId) { if (obj.replyMessageObject == null) { return; } int id = obj.replyMessageObject.getId(); ArrayList ids = replyMessageOwners.get(id); if (ids == null) { ids = new ArrayList<>(); replyMessageOwners.put(id, ids); } id = obj.getId(); if (!ids.contains(id)) { ids.add(id); } if (oldId != 0) { ids.remove(oldId); } } private void updateReplyMessageOwners(int id, MessageObject update) { ArrayList ids = replyMessageOwners.get(id); if (ids == null) { return; } MessageObject emptyMessage = update == null ? new MessageObject(currentAccount, new TLRPC.TL_messageEmpty(), false, false) : null; for (int a = 0, N = ids.size(); a < N; a++) { MessageObject object = messagesDict[0].get(ids.get(a)); if (object != null) { if (update == null) { object.replyMessageObject = emptyMessage; } else { object.replyMessageObject = update; } if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(object, true); } } } if (update == null) { replyMessageOwners.remove(id); } } private void rotateMotionBackgroundDrawable() { Drawable wallpaper = themeDelegate.getWallpaperDrawable(); if (fragmentView != null) { wallpaper = ((SizeNotifierFrameLayout) fragmentView).getBackgroundImage(); } if (wallpaper instanceof MotionBackgroundDrawable) { ((MotionBackgroundDrawable) wallpaper).switchToNextPosition(); } Drawable drawable = getThemedDrawable(Theme.key_drawable_msgOut); if (drawable instanceof Theme.MessageDrawable) { MotionBackgroundDrawable motionDrawable = ((Theme.MessageDrawable) drawable).getMotionBackgroundDrawable(); if (motionDrawable != null) { motionDrawable.switchToNextPosition(); } } } private void processNewMessages(ArrayList arr) { long currentUserId = getUserConfig().getClientUserId(); boolean updateChat = false; boolean hasFromMe = false; boolean isAd = false; if (chatListItemAnimator != null) { chatListItemAnimator.setShouldAnimateEnterFromBottom(true); } boolean notifiedSearch = false; LongSparseArray scheduledGroupReplacement = null; for (int a = 0, N = arr.size(); a < N; a++) { MessageObject messageObject = arr.get(a); if (!isAd) { isAd = messageObject.isSponsored(); } int messageId = messageObject.getId(); if (threadMessageId != 0) { if (messageId > 0 && messageId <= (messageObject.isOut() ? threadMaxOutboxReadId : threadMaxInboxReadId)) { messageObject.setIsRead(); } } if (currentEncryptedChat == null && !forwardEndReached[0] && messageId < 0) { pendingSendMessagesDict.put(messageId, messageObject); pendingSendMessages.add(0, messageObject); } if (messageObject.isDice() && !messageObject.isForwarded() || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { messageObject.wasUnread = true; } if (chatMode == MODE_SCHEDULED && messageObject.hasValidGroupId() && messagesDict[0].indexOfKey(messageObject.getId()) >= 0) { long groupId = messageObject.getGroupId(); if (scheduledGroupReplacement == null) { scheduledGroupReplacement = new LongSparseArray<>(); } Long localId = scheduledGroupReplacement.get(groupId); if (localId == null) { localId = Utilities.random.nextLong(); scheduledGroupReplacement.put(groupId, localId); } messageObject.localGroupId = localId; } if (messageObject.isOut()) { if (!notifiedSearch) { notifiedSearch = true; NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); } if (currentChat != null) { TLRPC.Chat newChat = getMessagesController().getChat(currentChat.id); if (newChat != null) { currentChat = newChat; if (!newChat.gigagroup && newChat.slowmode_enabled && messageObject.isSent() && chatMode != MODE_SCHEDULED) { if (chatInfo != null) { int date = messageObject.messageOwner.date + chatInfo.slowmode_seconds; int currentTime = getConnectionsManager().getCurrentTime(); if (date > getConnectionsManager().getCurrentTime()) { chatInfo.slowmode_next_send_date = Math.max(chatInfo.slowmode_next_send_date, Math.min(currentTime + chatInfo.slowmode_seconds, date)); if (chatActivityEnterView != null) { chatActivityEnterView.setSlowModeTimer(chatInfo.slowmode_next_send_date); } } } getMessagesController().loadFullChat(currentChat.id, 0, true); } } } if (messageObject.wasJustSent && (getUserConfig().isPremium() || messageObject.isAnimatedAnimatedEmoji())) { messageObject.forcePlayEffect = true; } } if (currentChat != null) { if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser && messageObject.messageOwner.action.user_id == currentUserId || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser && messageObject.messageOwner.action.users.contains(currentUserId)) { TLRPC.Chat newChat = getMessagesController().getChat(currentChat.id); if (newChat != null) { currentChat = newChat; checkActionBarMenu(false); updateBottomOverlay(); if (avatarContainer != null) { avatarContainer.updateSubtitle(true); } } } } else if (inlineReturn != 0) { if (messageObject.messageOwner.reply_markup != null) { for (int b = 0; b < messageObject.messageOwner.reply_markup.rows.size(); b++) { TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(b); for (int c = 0; c < row.buttons.size(); c++) { TLRPC.KeyboardButton button = row.buttons.get(c); if (button instanceof TLRPC.TL_keyboardButtonSwitchInline) { processSwitchButton((TLRPC.TL_keyboardButtonSwitchInline) button); break; } } } } } if (messageObject.getReplyMsgId() != 0 && messageObject.replyMessageObject == null) { messageObject.replyMessageObject = messagesDict[0].get(messageObject.getReplyMsgId()); if (messageObject.replyMessageObject == null && messageObject.getDialogId() != mergeDialogId) { messageObject.replyMessageObject = repliesMessagesDict.get(messageObject.getReplyMsgId()); } if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { messageObject.generatePinMessageText(null, null); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { messageObject.generateGameMessageText(null); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { messageObject.generatePaymentSentMessageText(null); } } if (messageObject.replyMessageObject != null) { repliesMessagesDict.put(messageObject.replyMessageObject.getId(), messageObject.replyMessageObject); addReplyMessageOwner(messageObject, 0); } } if (chatMode == MODE_SCHEDULED && !arr.isEmpty()) { replaceMessageObjects(arr, 0, true); } boolean needMoveScrollToLastMessage = false; boolean reloadMegagroup = false; if (!forwardEndReached[0]) { int currentMaxDate = Integer.MIN_VALUE; for (int a = 0; a < arr.size(); a++) { MessageObject obj = arr.get(a); if (obj.isOut()) { rotateMotionBackgroundDrawable(); } if (threadMessageId != 0 && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { continue; } int messageId = obj.getId(); if (obj.isOut() && waitingForSendingMessageLoad) { waitingForSendingMessageLoad = false; chatActivityEnterView.hideTopView(true); if (changeBoundAnimator != null) { changeBoundAnimator.start(); } } if (chatMode != MODE_SCHEDULED && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } TLRPC.MessageAction action = obj.messageOwner.action; if (avatarContainer != null && currentEncryptedChat != null && action instanceof TLRPC.TL_messageEncryptedAction && action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { avatarContainer.setTime(action.encryptedAction.ttl_seconds, true); } if (action instanceof TLRPC.TL_messageActionChatMigrateTo) { migrateToNewChat(obj); return; } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { reloadMegagroup = true; } if (a == 0 && obj.shouldAnimateSending() && chatMode != MODE_SCHEDULED) { needAnimateToMessage = obj; } if (obj.isOut() && obj.wasJustSent) { scrollToLastMessage(true); return; } if (obj.type < 0 || messagesDict[0].indexOfKey(messageId) >= 0) { continue; } if (currentChat != null && currentChat.creator && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && (action instanceof TLRPC.TL_messageActionChatCreate || action instanceof TLRPC.TL_messageActionChatEditPhoto && messages.size() < 2)) { continue; } if (action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { continue; } if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { continue; } if (threadMessageObject != null && obj.isReply() && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage)) { int mid = obj.getReplyAnyMsgId(); if (threadMessageObject.getId() == mid) { threadMessageObject.messageOwner.replies.replies++; } } addToPolls(obj, null); obj.checkLayout(); currentMaxDate = Math.max(currentMaxDate, obj.messageOwner.date); if (messageId > 0) { last_message_id = Math.max(last_message_id, messageId); } else if (currentEncryptedChat != null) { last_message_id = Math.min(last_message_id, messageId); } if (threadMessageId == 0) { if (obj.messageOwner.mentioned && obj.isContentUnread()) { newMentionsCount++; } } if (!isAd) { newUnreadMessageCount++; } if (obj.type == 10 || obj.type == 11) { updateChat = true; } } if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) { pagedownButtonCounter.setVisibility(View.VISIBLE); if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; pagedownButtonCounter.setCount(newUnreadMessageCount, true); } } if (newMentionsCount != 0 && mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); showMentionDownButton(true, true); } updateVisibleRows(); } else { LongSparseArray newGroups = null; HashMap> webpagesToReload = null; if (BuildVars.LOGS_ENABLED) { FileLog.d("received new messages " + arr.size() + " in dialog " + dialog_id); } MessageObject lastActionSetChatThemeMessageObject = null; for (int a = 0; a < arr.size(); a++) { MessageObject obj = arr.get(a); if (obj.scheduled != (chatMode == MODE_SCHEDULED) || threadMessageId != 0 && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { continue; } if (obj.isOut()) { rotateMotionBackgroundDrawable(); } int placeToPaste = -1; int messageId = obj.getId(); if (chatMode == MODE_SCHEDULED && messagesDict[0].indexOfKey(messageId) >= 0) { MessageObject removed = messagesDict[0].get(messageId); messagesDict[0].remove(messageId); if (removed != null) { int index = messages.indexOf(removed); messages.remove(index); ArrayList dayArr = messagesByDays.get(removed.dateKey); dayArr.remove(removed); if (dayArr.isEmpty()) { messagesByDays.remove(removed.dateKey); if (index >= 0 && index < messages.size()) { messages.remove(index); } } if (removed.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(removed.getGroupId()); groupedMessages.messages.remove(removed); if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); } if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } } } if (isSecretChat()) { checkSecretMessageForLocation(obj); } if (chatMode != MODE_SCHEDULED && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } TLRPC.MessageAction action = obj.messageOwner.action; if (avatarContainer != null && currentEncryptedChat != null && action instanceof TLRPC.TL_messageEncryptedAction && action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { avatarContainer.setTime(action.encryptedAction.ttl_seconds, true); } if (obj.type < 0 || messagesDict[0].indexOfKey(messageId) >= 0) { continue; } if (currentChat != null && currentChat.creator && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && (action instanceof TLRPC.TL_messageActionChatCreate || action instanceof TLRPC.TL_messageActionChatEditPhoto && messages.size() < 2)) { continue; } if (action instanceof TLRPC.TL_messageActionChannelMigrateFrom) { continue; } if (threadMessageId != 0 && obj.messageOwner instanceof TLRPC.TL_messageEmpty) { continue; } if (threadMessageObject != null && threadMessageObject.messageOwner.replies != null && obj.isReply() && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage)) { int mid = obj.getReplyAnyMsgId(); if (threadMessageObject.getId() == mid) { threadMessageObject.messageOwner.replies.replies++; } } addToPolls(obj, null); if (a == 0 && obj.shouldAnimateSending() && chatMode != MODE_SCHEDULED) { animatingMessageObjects.add(obj); } MessageObject.GroupedMessages groupedMessages; if (obj.hasValidGroupId()) { groupedMessages = groupedMessagesMap.get(obj.getGroupId()); if (groupedMessages == null) { groupedMessages = new MessageObject.GroupedMessages(); groupedMessages.groupId = obj.getGroupId(); groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); } if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); groupedMessages.messages.add(obj); } else { groupedMessages = null; } if (groupedMessages != null) { int size = groupedMessages.messages.size(); MessageObject messageObject = size > 1 ? groupedMessages.messages.get(groupedMessages.messages.size() - 2) : null; if (messageObject != null) { placeToPaste = messages.indexOf(messageObject); } } if (placeToPaste == -1) { if (!obj.scheduled && obj.messageOwner.id < 0 || messages.isEmpty()) { placeToPaste = 0; } else { int size = messages.size(); for (int b = 0; b < size; b++) { MessageObject lastMessage = messages.get(b); if (lastMessage.type >= 0 && lastMessage.messageOwner.date > 0) { if (chatMode != MODE_SCHEDULED && lastMessage.messageOwner.id > 0 && obj.messageOwner.id > 0 && lastMessage.messageOwner.id < obj.messageOwner.id || lastMessage.messageOwner.date <= obj.messageOwner.date) { MessageObject.GroupedMessages lastGroupedMessages; if (lastMessage.getGroupId() != 0) { lastGroupedMessages = groupedMessagesMap.get(lastMessage.getGroupId()); if (lastGroupedMessages != null && lastGroupedMessages.messages.size() == 0) { lastGroupedMessages = null; } } else { lastGroupedMessages = null; } if (lastGroupedMessages == null) { placeToPaste = b; } else { placeToPaste = messages.indexOf(lastGroupedMessages.messages.get(lastGroupedMessages.messages.size() - 1)); } break; } } } if (placeToPaste == -1 || placeToPaste > messages.size()) { placeToPaste = messages.size(); } } } if (currentEncryptedChat != null && obj.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && obj.messageOwner.media.webpage instanceof TLRPC.TL_webPageUrlPending) { if (webpagesToReload == null) { webpagesToReload = new HashMap<>(); } ArrayList arrayList = webpagesToReload.get(obj.messageOwner.media.webpage.url); if (arrayList == null) { arrayList = new ArrayList<>(); webpagesToReload.put(obj.messageOwner.media.webpage.url, arrayList); } arrayList.add(obj); } obj.checkLayout(); if (action instanceof TLRPC.TL_messageActionChatMigrateTo) { migrateToNewChat(obj); if (newGroups != null) { for (int b = 0; b < newGroups.size(); b++) { newGroups.valueAt(b).calculate(); } } return; } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { reloadMegagroup = true; } if (minDate[0] == 0 || obj.messageOwner.date < minDate[0]) { minDate[0] = obj.messageOwner.date; } if (obj.isOut() && !obj.messageOwner.from_scheduled) { removeUnreadPlane(true); hideInfoView(); hasFromMe = true; } if (messageId > 0) { maxMessageId[0] = Math.min(messageId, maxMessageId[0]); minMessageId[0] = Math.max(messageId, minMessageId[0]); } else if (currentEncryptedChat != null) { maxMessageId[0] = Math.max(messageId, maxMessageId[0]); minMessageId[0] = Math.min(messageId, minMessageId[0]); } maxDate[0] = Math.max(maxDate[0], obj.messageOwner.date); messagesDict[0].put(messageId, obj); ArrayList dayArray; if (isAd && !messages.isEmpty()) { dayArray = messagesByDays.get(messages.get(0).dateKey); } else { dayArray = messagesByDays.get(obj.dateKey); } if (placeToPaste > messages.size()) { placeToPaste = messages.size(); } int sponsoredMessagesCount = getSponsoredMessagesCount(); if (!isAd && placeToPaste < sponsoredMessagesCount && (currentChat == null || ChatObject.isChannelAndNotMegaGroup(currentChat))) { placeToPaste = sponsoredMessagesCount; } if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { dateMsg.message = LocaleController.getString("MessageScheduledUntilOnline", R.string.MessageScheduledUntilOnline); } else { dateMsg.message = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); } } else { dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); } dateMsg.id = 0; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 10; dateObj.contentType = 1; dateObj.isDateObject = true; dateObj.stableId = lastStableId++; messages.add(placeToPaste, dateObj); if (chatAdapter != null) { chatAdapter.notifyItemInserted(placeToPaste); } } if (!(obj.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) && (!obj.isOut() || obj.messageOwner.from_scheduled)) { if (paused && placeToPaste == 0) { if (!scrollToTopUnReadOnResume && unreadMessageObject != null) { removeMessageObject(unreadMessageObject); unreadMessageObject = null; } if (unreadMessageObject == null) { TLRPC.Message dateMsg = new TLRPC.TL_message(); dateMsg.message = ""; dateMsg.id = 0; MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 6; dateObj.contentType = 2; dateObj.stableId = lastStableId++; messages.add(0, dateObj); if (chatAdapter != null) { chatAdapter.notifyItemInserted(0); } unreadMessageObject = dateObj; scrollToMessage = unreadMessageObject; scrollToMessagePosition = -10000; scrollToTopUnReadOnResume = true; } } } dayArray.add(0, obj); if (chatAdapter != null && placeToPaste < messages.size()) { MessageObject prevMessage = messages.get(placeToPaste); if (prevMessage.hasValidGroupId() && prevMessage.getGroupId() != obj.getGroupId()) { MessageObject.GroupedMessages group = groupedMessagesMap.get(prevMessage.getGroupId()); if (group != null && group.messages.size() > 1) { int size = group.messages.size(); chatAdapter.notifyItemRangeChanged(1, size - 1); } } } obj.stableId = lastStableId++; messages.add(placeToPaste, obj); if (placeToPaste == 0 && !obj.isSponsored()) { needMoveScrollToLastMessage = true; } if (chatAdapter != null) { chatAdapter.notifyItemChanged(placeToPaste); chatAdapter.notifyItemInserted(placeToPaste); } if (obj.isOut() && waitingForSendingMessageLoad) { waitingForSendingMessageLoad = false; if (!animatingMessageObjects.contains(obj)) { chatActivityEnterView.hideTopView(true); } if (changeBoundAnimator != null) { changeBoundAnimator.start(); } } if (threadMessageId == 0) { if (!obj.isOut() && obj.messageOwner.mentioned && obj.isContentUnread()) { newMentionsCount++; } } if (!isAd) { newUnreadMessageCount++; } if (obj.type == 10 || obj.type == 11) { updateChat = true; } if (obj.messageOwner.action instanceof TLRPC.TL_messageActionSetChatTheme) { lastActionSetChatThemeMessageObject = obj; } } if (lastActionSetChatThemeMessageObject != null && lastActionSetChatThemeMessageObject.messageOwner != null && lastActionSetChatThemeMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionSetChatTheme) { TLRPC.TL_messageActionSetChatTheme action = (TLRPC.TL_messageActionSetChatTheme) lastActionSetChatThemeMessageObject.messageOwner.action; setChatThemeEmoticon(action.emoticon); } if (webpagesToReload != null) { getMessagesController().reloadWebPages(dialog_id, webpagesToReload, chatMode == MODE_SCHEDULED); } if (newGroups != null) { for (int a = 0; a < newGroups.size(); a++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); int oldCount = groupedMessages.posArray.size(); groupedMessages.calculate(); int newCount = groupedMessages.posArray.size(); if (newCount - oldCount > 0 && chatAdapter != null) { int index = messages.indexOf(groupedMessages.messages.get(groupedMessages.messages.size() - 1)); if (index >= 0) { chatAdapter.notifyItemRangeChanged(index, newCount); } } } } showProgressView(false); if (chatAdapter == null) { scrollToTopOnResume = true; } if (chatListView != null && chatAdapter != null) { int lastVisible = chatLayoutManager.findFirstVisibleItemPosition(); if (lastVisible == RecyclerView.NO_POSITION) { lastVisible = 0; } View child = chatLayoutManager.findViewByPosition(lastVisible); int diff; if (child != null) { diff = child.getBottom() - chatListView.getMeasuredHeight(); } else { diff = 0; } if (!isAd) { if (lastVisible == 0 && diff <= AndroidUtilities.dp(5) || hasFromMe) { newUnreadMessageCount = 0; if (!firstLoading && chatMode != MODE_SCHEDULED) { if (paused) { scrollToTopOnResume = true; } else { forceScrollToTop = true; moveScrollToLastMessage(true); } } } else { if (newUnreadMessageCount != 0 && pagedownButtonCounter != null) { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; pagedownButtonCounter.setCount(newUnreadMessageCount, true); } } canShowPagedownButton = true; updatePagedownButtonVisibility(true); } } else { if (child != null) { chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom()); } } if (newMentionsCount != 0 && mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); showMentionDownButton(true, true); } } else { scrollToTopOnResume = true; } } if (chatMode == MODE_SCHEDULED && !arr.isEmpty()) { MessageObject messageObject = arr.get(0); int mid = messageObject.getId(); if (mid < 0) { if (chatListItemAnimator != null) { chatListItemAnimator.setShouldAnimateEnterFromBottom(needMoveScrollToLastMessage); } if (needMoveScrollToLastMessage) { moveScrollToLastMessage(false); } else { int index = messages.indexOf(messageObject); if (chatLayoutManager != null && index > 0 && (chatLayoutManager.findViewByPosition(chatAdapter.messagesStartRow + index) != null || chatLayoutManager.findViewByPosition(chatAdapter.messagesStartRow + index - 1) != null)) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messages.indexOf(messageObject), getScrollOffsetForMessage(messageObject), false); } else { AndroidUtilities.runOnUIThread(() -> scrollToMessageId(mid, 0, false, 0, true, 0)); } } } } if (!messages.isEmpty() && botUser != null && botUser.length() == 0) { botUser = null; updateBottomOverlay(); } if (updateChat) { updateTitle(); checkAndUpdateAvatar(); } if (reloadMegagroup) { getMessagesController().loadFullChat(currentChat.id, 0, true); } checkWaitingForReplies(); updateReplyMessageHeader(true); } private int getSponsoredMessagesCount() { int sponsoredMessagesCount = 0; while (sponsoredMessagesCount < messages.size()) { if (!messages.get(sponsoredMessagesCount).isSponsored()) { break; } sponsoredMessagesCount++; } return sponsoredMessagesCount; } private void processDeletedMessages(ArrayList markAsDeletedMessages, long channelId) { ArrayList removedIndexes = new ArrayList<>(); int loadIndex = 0; if (ChatObject.isChannel(currentChat)) { if (channelId == 0 && mergeDialogId != 0) { loadIndex = 1; } else if (channelId == -dialog_id) { loadIndex = 0; } else { return; } } else if (channelId != 0) { return; } boolean updated = false; LongSparseArray newGroups = null; LongSparseArray newGroupsSizes = null; int size = markAsDeletedMessages.size(); boolean updatedSelected = false; boolean updatedSelectedLast = false; boolean updateScheduled = false; boolean hasChatInBack = false; boolean updatedReplies = false; if (threadMessageObject != null && parentLayout != null) { for (int a = 0, N = parentLayout.fragmentsStack.size() - 1; a < N; a++) { BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getChatMode() == getChatMode()) { hasChatInBack = true; break; } } } } int commentsDeleted = 0; for (int a = 0; a < size; a++) { Integer mid = markAsDeletedMessages.get(a); MessageObject obj = messagesDict[loadIndex].get(mid); if (selectedObject != null && obj == selectedObject || obj != null && selectedObjectGroup != null && selectedObjectGroup == groupedMessagesMap.get(obj.getGroupId())) { closeMenu(); } if (loadIndex == 0) { if (pinnedMessageObjects.containsKey(mid)) { pinnedMessageObjects.remove(mid); pinnedMessageIds.remove(mid); loadedPinnedMessagesCount = pinnedMessageIds.size(); totalPinnedMessagesCount--; if (totalPinnedMessagesCount < 0) { totalPinnedMessagesCount = 0; } if (currentPinnedMessageId == mid) { currentPinnedMessageId = 0; } } repliesMessagesDict.remove(mid); updateReplyMessageOwners(mid, null); } if (obj != null) { if (obj.messageOwner.reply_to != null && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage)) { int replyId = obj.getReplyAnyMsgId(); if (threadMessageObject != null && threadMessageObject.getId() == replyId) { if (!hasChatInBack && threadMessageObject.hasReplies()) { threadMessageObject.messageOwner.replies.replies--; } if (replyOriginalMessageId != 0) { commentsDeleted++; } updatedReplies = true; } else { MessageObject replyObject = messagesDict[loadIndex].get(replyId); if (replyObject != null && replyObject.hasReplies()) { replyObject.messageOwner.replies.replies--; replyObject.viewsReloaded = false; } } } obj.deleted = true; if (editingMessageObject == obj) { hideFieldPanel(true); } int index = messages.indexOf(obj); if (index != -1) { if (obj.scheduled) { scheduledMessagesCount--; updateScheduled = true; } if (selectedMessagesIds[loadIndex].indexOfKey(mid) >= 0) { updatedSelected = true; addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); } MessageObject removed = messages.remove(index); if (chatAdapter != null) { removedIndexes.add(chatAdapter.messagesStartRow + index); } if (removed.getGroupId() != 0) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(removed.getGroupId()); if (groupedMessages != null) { if (newGroups == null) { newGroups = new LongSparseArray<>(); newGroupsSizes = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); if (newGroupsSizes.get(groupedMessages.groupId) == null) { newGroupsSizes.put(groupedMessages.groupId, groupedMessages.messages.size()); } groupedMessages.messages.remove(obj); } } messagesDict[loadIndex].remove(mid); ArrayList dayArr = messagesByDays.get(obj.dateKey); if (dayArr != null) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); if (index < messages.size()) { messages.remove(index); if (chatAdapter != null) { removedIndexes.add(chatAdapter.messagesStartRow + index); } } } } updated = true; } } } if (updatedReplies) { updateReplyMessageHeader(true); } if (commentsDeleted != 0) { getNotificationCenter().postNotificationName(NotificationCenter.changeRepliesCounter, replyOriginalChat.id, replyOriginalMessageId, -commentsDeleted); getMessagesStorage().updateRepliesCount(replyOriginalChat.id, replyOriginalMessageId, null, 0, -commentsDeleted); } if (updatedSelected) { if (!updatedSelectedLast) { addToSelectedMessages(null, false, true); } updateActionModeTitle(); } if (newGroups != null) { for (int a = 0; a < newGroups.size(); a++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(a); if (chatListItemAnimator != null) { if (groupedMessages.messages.size() == 1) { chatListItemAnimator.groupWillTransformToSingleMessage(groupedMessages); } else { chatListItemAnimator.groupWillChanged(groupedMessages); } } if (groupedMessages.messages.isEmpty()) { groupedMessagesMap.remove(groupedMessages.groupId); } else { groupedMessages.calculate(); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); if (index >= 0) { if (chatAdapter != null) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); } } } } } if (messages.isEmpty()) { if (!endReached[0] && !loading) { showProgressView(false); if (chatListView != null) { chatListView.setEmptyView(null); } if (currentEncryptedChat == null) { maxMessageId[0] = maxMessageId[1] = Integer.MAX_VALUE; minMessageId[0] = minMessageId[1] = Integer.MIN_VALUE; } else { maxMessageId[0] = maxMessageId[1] = Integer.MIN_VALUE; minMessageId[0] = minMessageId[1] = Integer.MAX_VALUE; } maxDate[0] = maxDate[1] = Integer.MIN_VALUE; minDate[0] = minDate[1] = 0; waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++); loading = true; } else { if (botButtons != null) { botButtons = null; if (chatActivityEnterView != null) { chatActivityEnterView.setButtons(null, false); } } if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { botUser = ""; updateBottomOverlay(); } } canShowPagedownButton = false; updatePagedownButtonVisibility(true); showMentionDownButton(false, true); } if (updated) { if (chatMode == MODE_PINNED) { if (avatarContainer != null) { avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } } if (chatAdapter != null) { int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; for (int a = 0, N = removedIndexes.size(); a < N; a++) { chatAdapter.notifyItemRemoved(removedIndexes.get(a)); } if (!isThreadChat() || messages.size() <= 3) { removeUnreadPlane(false); } if (messages.isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevLoadingDownRow >= 0) { chatAdapter.notifyItemRemoved(0); } } else { chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, messages.size()); } } updateVisibleRows(); } else if (threadMessageId == 0) { first_unread_id = 0; last_message_id = 0; createUnreadMessageAfterId = 0; removeMessageObject(unreadMessageObject); unreadMessageObject = null; } if (updateScheduled) { updateScheduledInterface(true); } } private void replaceMessageObjects(ArrayList messageObjects, int loadIndex, boolean remove) { LongSparseArray newGroups = null; for (int a = 0; a < messageObjects.size(); a++) { MessageObject messageObject = messageObjects.get(a); MessageObject pinnedOld = pinnedMessageObjects.get(messageObject.getId()); if (pinnedOld != null) { pinnedMessageObjects.put(messageObject.getId(), messageObject); } MessageObject old = messagesDict[loadIndex].get(messageObject.getId()); if (pinnedMessageObjects.containsKey(messageObject.getId())) { pinnedMessageObjects.put(messageObject.getId(), messageObject); if (messageObject.getId() == currentPinnedMessageId) { updatePinnedMessageView(true); } } if (loadIndex == 0 && repliesMessagesDict.indexOfKey(messageObject.getId()) >= 0) { repliesMessagesDict.put(messageObject.getId(), messageObject); } if (old == null || remove && old.messageOwner.date != messageObject.messageOwner.date) { continue; } if (remove) { messageObjects.remove(a); a--; } addToPolls(messageObject, old); if (messageObject.type >= 0) { if (old.replyMessageObject != null) { messageObject.replyMessageObject = old.replyMessageObject; if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { messageObject.generateGameMessageText(null); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { messageObject.generatePaymentSentMessageText(null); } } if (!old.isEditing()) { if (old.getFileName().equals(messageObject.getFileName())) { messageObject.messageOwner.attachPath = old.messageOwner.attachPath; messageObject.attachPathExists = old.attachPathExists; messageObject.mediaExists = old.mediaExists; } else { messageObject.checkMediaExistance(); } } messagesDict[loadIndex].put(old.getId(), messageObject); } else { messagesDict[loadIndex].remove(old.getId()); } int index = messages.indexOf(old); if (index >= 0) { ArrayList dayArr = messagesByDays.get(old.dateKey); int index2 = -1; if (dayArr != null) { index2 = dayArr.indexOf(old); } if (old.getGroupId() != 0) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(old.getGroupId()); if (groupedMessages != null) { int idx = groupedMessages.messages.indexOf(old); if (idx >= 0) { if (old.getGroupId() != messageObject.getGroupId()) { groupedMessagesMap.put(messageObject.getGroupId(), groupedMessages); } if (!messageObject.isMusic() && !messageObject.isDocument() && (messageObject.photoThumbs == null || messageObject.photoThumbs.isEmpty())) { if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); if (idx > 0 && idx < groupedMessages.messages.size() - 1) { MessageObject.GroupedMessages slicedGroup = new MessageObject.GroupedMessages(); slicedGroup.groupId = Utilities.random.nextLong(); slicedGroup.messages.addAll(groupedMessages.messages.subList(idx + 1, groupedMessages.messages.size())); for (int b = 0; b < slicedGroup.messages.size(); b++) { slicedGroup.messages.get(b).localGroupId = slicedGroup.groupId; groupedMessages.messages.remove(idx + 1); } newGroups.put(slicedGroup.groupId, slicedGroup); groupedMessagesMap.put(slicedGroup.groupId, slicedGroup); } groupedMessages.messages.remove(idx); } else { groupedMessages.messages.set(idx, messageObject); MessageObject.GroupedMessagePosition oldPosition = groupedMessages.positions.remove(old); if (oldPosition != null) { groupedMessages.positions.put(messageObject, oldPosition); } if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); } } } } if (messageObject.type >= 0) { messageObject.copyStableParams(old); messages.set(index, messageObject); if (chatAdapter != null) { chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { dayArr.set(index2, messageObject); } } else { messages.remove(index); if (chatAdapter != null) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { dayArr.remove(index2); if (dayArr.isEmpty()) { messagesByDays.remove(old.dateKey); messages.remove(index); int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); if (messages.isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevLoadingDownRow >= 0) { chatAdapter.notifyItemRemoved(0); } } } } } } updateReplyMessageOwners(old.getId(), messageObject); } if (newGroups != null) { for (int b = 0; b < newGroups.size(); b++) { MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); if (groupedMessages.messages.isEmpty()) { groupedMessagesMap.remove(groupedMessages.groupId); } else { groupedMessages.calculate(); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); if (index >= 0) { if (chatAdapter != null) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); if (chatListItemAnimator != null) { chatListItemAnimator.groupWillChanged(groupedMessages); } } } } } } } private void migrateToNewChat(MessageObject obj) { if (parentLayout == null) { return; } final long channelId = obj.messageOwner.action.channel_id; final BaseFragment lastFragment = parentLayout.fragmentsStack.size() > 0 ? parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) : null; int index = parentLayout.fragmentsStack.indexOf(ChatActivity.this); final ActionBarLayout actionBarLayout = parentLayout; if (index > 0 && !(lastFragment instanceof ChatActivity) && !(lastFragment instanceof ProfileActivity) && currentChat.creator) { for (int a = index, N = actionBarLayout.fragmentsStack.size() - 1; a < N; a++) { BaseFragment fragment = actionBarLayout.fragmentsStack.get(a); if (fragment instanceof ChatActivity) { final Bundle bundle = new Bundle(); bundle.putLong("chat_id", channelId); actionBarLayout.addFragmentToStack(new ChatActivity(bundle), a); fragment.removeSelfFromStack(); } else if (fragment instanceof ProfileActivity) { Bundle args = new Bundle(); args.putLong("chat_id", channelId); actionBarLayout.addFragmentToStack(new ProfileActivity(args), a); fragment.removeSelfFromStack(); } else if (fragment instanceof ChatEditActivity) { Bundle args = new Bundle(); args.putLong("chat_id", channelId); actionBarLayout.addFragmentToStack(new ChatEditActivity(args), a); fragment.removeSelfFromStack(); } else if (fragment instanceof ChatUsersActivity) { ChatUsersActivity usersActivity = (ChatUsersActivity) fragment; if (!usersActivity.hasSelectType()) { Bundle args = fragment.getArguments(); args.putLong("chat_id", channelId); actionBarLayout.addFragmentToStack(new ChatUsersActivity(args), a); } fragment.removeSelfFromStack(); } } } else { AndroidUtilities.runOnUIThread(() -> { if (lastFragment instanceof NotificationCenter.NotificationCenterDelegate) { getNotificationCenter().removeObserver((NotificationCenter.NotificationCenterDelegate) lastFragment, NotificationCenter.closeChats); } getNotificationCenter().postNotificationName(NotificationCenter.closeChats); final Bundle bundle = new Bundle(); bundle.putLong("chat_id", obj.messageOwner.action.channel_id); actionBarLayout.addFragmentToStack(new ChatActivity(bundle), actionBarLayout.fragmentsStack.size() - 1); lastFragment.finishFragment(); }); } AndroidUtilities.runOnUIThread(() -> getMessagesController().loadFullChat(channelId, 0, true), 1000); } private void addToPolls(MessageObject obj, MessageObject old) { long pollId = obj.getPollId(); if (pollId != 0) { ArrayList arrayList = polls.get(pollId); if (arrayList == null) { arrayList = new ArrayList<>(); polls.put(pollId, arrayList); } arrayList.add(obj); if (old != null) { arrayList.remove(old); } } } private void showInfoHint(MessageObject messageObject, CharSequence text, int type) { if (topUndoView == null) { return; } Runnable runnable = () -> { if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (!(view instanceof ChatMessageCell)) { continue; } ChatMessageCell cell = (ChatMessageCell) view; MessageObject message = cell.getMessageObject(); if (message != null && message.equals(hintMessageObject)) { cell.showHintButton(true, true, type); } } } hintMessageObject = null; }; topUndoView.showWithAction(0, UndoView.ACTION_TEXT_INFO, text, runnable, runnable); hintMessageObject = messageObject; hintMessageType = type; } private void showPollSolution(MessageObject messageObject, TLRPC.PollResults results) { if (results == null || TextUtils.isEmpty(results.solution)) { return; } CharSequence text; if (!results.solution_entities.isEmpty()) { text = new SpannableStringBuilder(results.solution); MessageObject.addEntitiesToText(text, results.solution_entities, false, true, true, false); } else { text = results.solution; } showInfoHint(messageObject, text, 0); } private void updateSearchButtons(int mask, int num, int count) { if (searchUpButton != null) { searchUpButton.setEnabled((mask & 1) != 0); searchDownButton.setEnabled((mask & 2) != 0); searchUpButton.setAlpha(searchUpButton.isEnabled() ? 1.0f : 0.5f); searchDownButton.setAlpha(searchDownButton.isEnabled() ? 1.0f : 0.5f); if (count < 0) { searchCountText.setCount("", 0, false); } else if (count == 0) { searchCountText.setCount(LocaleController.getString("NoResult", R.string.NoResult), 0, false); } else { searchCountText.setCount(LocaleController.formatString("OfCounted", R.string.OfCounted, num + 1, count), num + 1, true); } } } @Override public boolean needDelayOpenAnimation() { if (chatMode != MODE_SCHEDULED && getParentLayout().fragmentsStack.size() > 1) { BaseFragment previousFragment = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2); if (previousFragment instanceof ChatActivity && ((ChatActivity) previousFragment).isKeyboardVisible()) { return false; } } return firstLoading; } @Override protected void onBecomeFullyVisible() { isFullyVisible = true; super.onBecomeFullyVisible(); if (showCloseChatDialogLater) { showDialog(closeChatDialog); } if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); } } @Override protected void onBecomeFullyHidden() { isFullyVisible = false; hideUndoViews(); if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(Theme.getColor(Theme.key_windowBackgroundWhite)); } } public void saveKeyboardPositionBeforeTransition() { if (cancelFixedPositionRunnable != null) { AndroidUtilities.cancelRunOnUIThread(cancelFixedPositionRunnable); } if (chatActivityEnterView != null && contentView != null && chatActivityEnterView.getAdjustPanLayoutHelper() != null && !chatActivityEnterView.getAdjustPanLayoutHelper().animationInProgress()) { fixedKeyboardHeight = contentView.getKeyboardHeight(); } else { fixedKeyboardHeight = -1; } } public void removeKeyboardPositionBeforeTransition() { if (fixedKeyboardHeight > 0) { AndroidUtilities.runOnUIThread(cancelFixedPositionRunnable = () -> { cancelFixedPositionRunnable = null; fixedKeyboardHeight = -1; if (fragmentView != null) { fragmentView.requestLayout(); } }, 200); } } @Override public void onTransitionAnimationStart(boolean isOpen, boolean backward) { super.onTransitionAnimationStart(isOpen, backward); int[] alowedNotifications = null; if (isOpen) { if (!fragmentOpened) { fragmentOpened = true; updateMessagesVisiblePart(false); } if (transitionAnimationIndex == 0) { alowedNotifications = new int[]{ NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.needDeleteDialog, NotificationCenter.messagesDidLoad }; } else { alowedNotifications = new int[]{ NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.needDeleteDialog }; } openAnimationEnded = false; if (!backward) { openAnimationStartTime = SystemClock.elapsedRealtime(); } } else { if (UserObject.isUserSelf(currentUser)) { alowedNotifications = new int[]{ NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.needDeleteDialog, NotificationCenter.mediaDidLoad }; } if (chatActivityEnterView != null) { chatActivityEnterView.onBeginHide(); } } checkShowBlur(true); transitionAnimationIndex = getNotificationCenter().setAnimationInProgress(transitionAnimationIndex, alowedNotifications); } @Override public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { super.onTransitionAnimationEnd(isOpen, backward); if (isOpen) { if (backward) { if (showPinBulletin && pinBulletin != null) { pinBulletin.show(); showPinBulletin = false; } } } if (cancelFixedPositionRunnable != null) { AndroidUtilities.cancelRunOnUIThread(cancelFixedPositionRunnable); } fixedKeyboardHeight = -1; if (isOpen) { checkShowBlur(false); openAnimationEnded = true; getNotificationCenter().onAnimationFinish(transitionAnimationIndex); if (Build.VERSION.SDK_INT >= 21) { createChatAttachView(); } checkGroupCallJoin(lastCallCheckFromServer); if (chatActivityEnterView.hasRecordVideo() && !chatActivityEnterView.isSendButtonVisible()) { boolean isChannel = false; if (currentChat != null) { isChannel = ChatObject.isChannel(currentChat) && !currentChat.megagroup; } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); String key = isChannel ? "needShowRoundHintChannel2" : "needShowRoundHint2"; int showCount = preferences.getInt(key, 0); if (showCount < 3) { if (Utilities.random.nextFloat() <= 0.2f) { showVoiceHint(false, chatActivityEnterView.isInVideoMode()); preferences.edit().putInt(key, ++showCount).commit(); } } } if (!backward && parentLayout != null && needRemovePreviousSameChatActivity) { for (int a = 0, N = parentLayout.fragmentsStack.size() - 1; a < N; a++) { BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getChatMode() == getChatMode() && chatActivity.threadMessageId == threadMessageId && chatActivity.reportType == reportType) { fragment.removeSelfFromStack(); break; } } } } showScheduledOrNoSoundHint(); if (!backward && firstOpen) { if (chatActivityEnterView != null && threadMessageObject != null && threadMessageObject.getRepliesCount() == 0 && ChatObject.canSendMessages(currentChat)) { chatActivityEnterView.setFieldFocused(); chatActivityEnterView.openKeyboard(); } if (getMessagesController().isPromoDialog(dialog_id, true)) { int type = getMessagesController().promoDialogType; String message; SharedPreferences preferences = MessagesController.getGlobalNotificationsSettings(); boolean check; if (type == MessagesController.PROMO_TYPE_PROXY) { if (AndroidUtilities.getPrefIntOrLong(preferences, "proxychannel", 0) != dialog_id) { message = LocaleController.getString("UseProxySponsorInfo", R.string.UseProxySponsorInfo); } else { message = null; } } else if (type == MessagesController.PROMO_TYPE_PSA) { String psaType = getMessagesController().promoPsaType; if (!preferences.getBoolean(psaType + "_shown", false)) { message = LocaleController.getString("PsaInfo_" + psaType); if (TextUtils.isEmpty(message)) { message = LocaleController.getString("PsaInfoDefault", R.string.PsaInfoDefault); } } else { message = null; } } else { message = null; } if (!TextUtils.isEmpty(message)) { if (topUndoView != null) { if (type == MessagesController.PROMO_TYPE_PROXY) { preferences.edit().putLong("proxychannel", dialog_id).commit(); } else if (type == MessagesController.PROMO_TYPE_PSA) { String psaType = getMessagesController().promoPsaType; preferences.edit().putBoolean(psaType + "_shown", true).commit(); } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(message); MessageObject.addLinks(false, stringBuilder); topUndoView.showWithAction(0, UndoView.ACTION_TEXT_INFO, stringBuilder, null, null); } } } firstOpen = false; } if (!backward && fromPullingDownTransition && parentLayout != null && parentLayout.fragmentsStack.size() >= 2) { BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2); if (fragment instanceof ChatActivity) { backToPreviousFragment = (ChatActivity) fragment; parentLayout.fragmentsStack.remove(backToPreviousFragment); } } if (pendingRequestsDelegate != null && backward) { pendingRequestsDelegate.onBackToScreen(); } updateMessagesVisiblePart(false); } else { getNotificationCenter().onAnimationFinish(transitionAnimationIndex); } contentView.invalidate(); if (!TextUtils.isEmpty(attachMenuBotToOpen)) { TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); req.username = attachMenuBotToOpen; getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{ if (response != null) { TLRPC.TL_contacts_resolvedPeer resolvedPeer = (TLRPC.TL_contacts_resolvedPeer) response; if (!resolvedPeer.users.isEmpty()) { TLRPC.User user = resolvedPeer.users.get(0); if (user.bot && user.bot_attach_menu) { TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot(); getAttachMenuBot.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); ConnectionsManager.getInstance(currentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(()-> { if (response1 instanceof TLRPC.TL_attachMenuBotsBot) { TLRPC.TL_attachMenuBotsBot attachMenuBotsBot = (TLRPC.TL_attachMenuBotsBot) response1; MessagesController.getInstance(currentAccount).putUsers(attachMenuBotsBot.users, false); TLRPC.TL_attachMenuBot attachMenuBot = attachMenuBotsBot.bot; if (!MediaDataController.canShowAttachMenuBot(attachMenuBot, getCurrentUser() != null ? getCurrentUser() : getCurrentChat())) { if (currentUser != null && currentUser.bot && user.id == attachMenuBot.bot_id) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuSameBot)).show(); } else if (currentUser != null && currentUser.bot && user.id != attachMenuBot.bot_id) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuBot)).show(); } else if (currentUser != null && !currentUser.bot) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuUser)).show(); } else if (currentChat != null && !ChatObject.isChannelAndNotMegaGroup(currentChat)) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuGroup)).show(); } else if (currentChat != null && ChatObject.isChannelAndNotMegaGroup(currentChat)) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuChannel)).show(); } return; } if (!attachMenuBot.inactive) { openAttachBotLayout(user.id, attachMenuBotStartCommand); } else { AttachBotIntroTopView introTopView = new AttachBotIntroTopView(getParentActivity()); introTopView.setColor(Theme.getColor(Theme.key_chat_attachContactIcon)); introTopView.setBackgroundColor(Theme.getColor(Theme.key_dialogTopBackground)); introTopView.setAttachBot(attachMenuBot); new AlertDialog.Builder(getParentActivity()) .setTopView(introTopView) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("BotRequestAttachPermission", R.string.BotRequestAttachPermission, UserObject.getUserName(user)))) .setPositiveButton(LocaleController.getString(R.string.BotAddToMenu), (dialog, which) -> { TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); botRequest.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); botRequest.enabled = true; ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { if (error2 == null) { MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); openAttachBotLayout(user.id, attachMenuBotStartCommand); } }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); }) .setNegativeButton(LocaleController.getString(R.string.Cancel), null) .show(); } } })); } } } })); attachMenuBotToOpen = null; } } public void openAttachBotLayout(long botId, String startCommand) { openAttachMenu(); chatAttachAlert.showBotLayout(botId, startCommand); } @Override protected void onDialogDismiss(Dialog dialog) { if (closeChatDialog != null && dialog == closeChatDialog) { getMessagesController().deleteDialog(dialog_id, 0); if (parentLayout != null && !parentLayout.fragmentsStack.isEmpty() && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) != this) { BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1); removeSelfFromStack(); fragment.finishFragment(); } else { finishFragment(); } } } @Override public boolean extendActionMode(Menu menu) { if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { if (PhotoViewer.getInstance().getSelectiongLength() == 0 || menu.findItem(android.R.id.copy) == null) { return true; } } else { if (chatActivityEnterView.getSelectionLength() == 0 || menu.findItem(android.R.id.copy) == null) { return true; } } fillActionModeMenu(menu); return true; } public void fillActionModeMenu(Menu menu) { if (menu.findItem(R.id.menu_bold) != null) { return; } if (Build.VERSION.SDK_INT >= 23) { menu.removeItem(android.R.id.shareText); } int order = 6; menu.add(R.id.menu_groupbolditalic, R.id.menu_spoiler, order++, LocaleController.getString("Spoiler", R.string.Spoiler)); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, order++, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString("Italic", R.string.Italic)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_italic, order++, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_mono, order++, stringBuilder); if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_strike, order++, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString("Underline", R.string.Underline)); run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_underline, order++, stringBuilder); } menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, LocaleController.getString("CreateLink", R.string.CreateLink)); menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, LocaleController.getString("Regular", R.string.Regular)); } private void updateScheduledInterface(boolean animated) { if (chatActivityEnterView != null) { chatActivityEnterView.updateScheduleButton(animated); } } private void updateBottomOverlay() { if (bottomOverlayChatText == null || chatMode == MODE_SCHEDULED) { return; } if (reportType >= 0) { updateActionModeTitle(); } else if (chatMode == MODE_PINNED) { boolean allowPin; if (currentChat != null) { allowPin = ChatObject.canPinMessages(currentChat); } else { if (userInfo != null) { allowPin = userInfo.can_pin_message; } else { allowPin = false; } } if (allowPin) { bottomOverlayChatText.setTag(1); bottomOverlayChatText.setText(LocaleController.getString("UnpinAllMessages", R.string.UnpinAllMessages)); } else { bottomOverlayChatText.setTag(null); bottomOverlayChatText.setText(LocaleController.getString("HidePinnedMessages", R.string.HidePinnedMessages)); } showBottomOverlayProgress(false, false); } else if (currentChat != null) { long requestedTime = MessagesController.getNotificationsSettings(currentAccount).getLong("dialog_join_requested_time_" + dialog_id, -1); boolean shouldApply = false; if (ChatObject.isChannel(currentChat) && !(currentChat instanceof TLRPC.TL_channelForbidden)) { if (ChatObject.isNotInChat(currentChat) && (!isThreadChat() || currentChat.join_to_send)) { if (getMessagesController().isJoiningChannel(currentChat.id)) { showBottomOverlayProgress(true, false); } else { if (currentChat.join_request) { shouldApply = true; if (requestedTime > 0 && System.currentTimeMillis() - requestedTime < 1000 * 60 * 2) { bottomOverlayChatText.setText(LocaleController.getString("ChannelJoinRequestSent", R.string.ChannelJoinRequestSent), true); bottomOverlayChatText.setEnabled(false); } else { bottomOverlayChatText.setText(LocaleController.getString("ChannelJoinRequest", R.string.ChannelJoinRequest)); bottomOverlayChatText.setEnabled(true); } } else { bottomOverlayChatText.setText(LocaleController.getString("ChannelJoin", R.string.ChannelJoin)); bottomOverlayChatText.setEnabled(true); } showBottomOverlayProgress(false, false); } } else if (!isThreadChat()) { if (!getMessagesController().isDialogMuted(dialog_id)) { bottomOverlayChatText.setText(LocaleController.getString("ChannelMute", R.string.ChannelMute), false); bottomOverlayChatText.setEnabled(true); } else { bottomOverlayChatText.setText(LocaleController.getString("ChannelUnmute", R.string.ChannelUnmute), true); bottomOverlayChatText.setEnabled(true); } showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); } } else if (!isThreadChat()) { bottomOverlayChatText.setText(LocaleController.getString("DeleteThisGroup", R.string.DeleteThisGroup)); bottomOverlayChatText.setEnabled(true); } if (!shouldApply && requestedTime > 0) { MessagesController.getNotificationsSettings(currentAccount).edit().putLong("dialog_join_requested_time_" + dialog_id, -1).commit(); } } else { showBottomOverlayProgress(false, true); if (userBlocked) { if (currentUser.bot) { bottomOverlayChatText.setText(LocaleController.getString("BotUnblock", R.string.BotUnblock)); } else { bottomOverlayChatText.setText(LocaleController.getString("Unblock", R.string.Unblock)); } if (botButtons != null) { botButtons = null; if (chatActivityEnterView != null) { if (replyingMessageObject != null && botReplyButtons == replyingMessageObject) { botReplyButtons = null; hideFieldPanel(false); } chatActivityEnterView.setButtons(botButtons, false); } } } else if (UserObject.isReplyUser(currentUser)) { if (!getMessagesController().isDialogMuted(dialog_id)) { bottomOverlayChatText.setText(LocaleController.getString("ChannelMute", R.string.ChannelMute), false); } else { bottomOverlayChatText.setText(LocaleController.getString("ChannelUnmute", R.string.ChannelUnmute), true); } showBottomOverlayProgress(false, true); } else if (botUser != null && currentUser.bot) { bottomOverlayChatText.setText(LocaleController.getString("BotStart", R.string.BotStart)); chatActivityEnterView.hidePopup(false); if (getParentActivity() != null) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } } else { bottomOverlayChatText.setText(LocaleController.getString("DeleteThisChat", R.string.DeleteThisChat)); } } if (currentChat != null && currentChat.gigagroup && reportType < 0 && chatMode == 0) { bottomOverlayImage.setVisibility(View.VISIBLE); } else { bottomOverlayImage.setVisibility(View.INVISIBLE); } if (inPreviewMode) { searchContainer.setVisibility(View.INVISIBLE); bottomOverlayChat.setVisibility(View.INVISIBLE); chatActivityEnterView.setFieldFocused(false); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (searchItem != null && searchItemVisible) { searchContainer.animate().setListener(null).cancel(); if (searchContainer.getVisibility() != View.VISIBLE) { searchContainer.setVisibility(View.VISIBLE); searchContainer.setAlpha(0f); } searchContainer.animate().alpha(1f).setDuration(150).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } }).start(); if (searchExpandAnimator != null) { searchExpandAnimator.removeAllListeners(); searchExpandAnimator.cancel(); } if (searchExpandProgress != 1f) { searchExpandAnimator = ValueAnimator.ofFloat(searchExpandProgress, 1f); searchExpandAnimator.addUpdateListener(animation -> { searchExpandProgress = (float) animation.getAnimatedValue(); chatListView.setTranslationY(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); chatActivityEnterView.setChatSearchExpandOffset(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); invalidateChatListViewTopPadding(); }); searchExpandAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { searchExpandProgress = 1f; chatActivityEnterView.setVisibility(View.INVISIBLE); bottomOverlayChat.setVisibility(View.INVISIBLE); invalidateChatListViewTopPadding(); } }); searchExpandAnimator.setDuration(250); searchExpandAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); searchExpandAnimator.start(); } else { chatActivityEnterView.setVisibility(View.INVISIBLE); bottomOverlayChat.setVisibility(View.INVISIBLE); invalidateChatListViewTopPadding(); } chatActivityEnterView.setFieldFocused(false); if (chatActivityEnterView.isTopViewVisible()) { topViewWasVisible = 1; chatActivityEnterView.hideTopView(false); } else { topViewWasVisible = 2; } } else { searchContainer.animate().setListener(null).cancel(); if (searchContainer.getVisibility() == View.VISIBLE) { searchContainer.animate().alpha(0).setDuration(150).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); searchContainer.setVisibility(View.INVISIBLE); } }).start(); } chatActivityEnterView.setVisibility(View.VISIBLE); if (searchExpandAnimator != null) { searchExpandAnimator.removeAllListeners(); searchExpandAnimator.cancel(); } if (searchExpandProgress != 0) { searchExpandAnimator = ValueAnimator.ofFloat(searchExpandProgress, 0f); invalidateChatListViewTopPadding(); searchExpandAnimator.addUpdateListener(animation -> { searchExpandProgress = (float) animation.getAnimatedValue(); chatListView.setTranslationY(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); chatActivityEnterView.setChatSearchExpandOffset(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); invalidateChatListViewTopPadding(); }); searchExpandAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { searchExpandProgress = 0; invalidateChatListViewTopPadding(); } }); searchExpandAnimator.setDuration(250); searchExpandAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); searchExpandAnimator.start(); } if (muteItem != null) { if (currentChat != null && ChatObject.isNotInChat(currentChat)) { muteItem.setVisibility(View.GONE); muteItemGap.setVisibility(View.GONE); } else { muteItem.setVisibility(View.VISIBLE); muteItemGap.setVisibility(View.VISIBLE); } } if (reportType >= 0) { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (chatMode == MODE_PINNED || currentChat != null && (ChatObject.isNotInChat(currentChat) || !ChatObject.canWriteToChat(currentChat)) && (currentChat.join_to_send || !isThreadChat()) || currentUser != null && (UserObject.isDeleted(currentUser) || userBlocked || UserObject.isReplyUser(currentUser))) { if (chatActivityEnterView.isEditingMessage()) { chatActivityEnterView.setVisibility(View.VISIBLE); bottomOverlayChat.setVisibility(View.INVISIBLE); chatActivityEnterView.setFieldFocused(); AndroidUtilities.runOnUIThread(() -> chatActivityEnterView.openKeyboard(), 100); } else { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setFieldFocused(false); chatActivityEnterView.setVisibility(View.INVISIBLE); chatActivityEnterView.closeKeyboard(); if (suggestEmojiPanel != null) { suggestEmojiPanel.forceClose(); } } if (attachItem != null) { attachItem.setVisibility(View.GONE); } if (editTextItem != null) { editTextItem.setVisibility(View.GONE); } if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } } else { if (botUser != null && currentUser.bot) { bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else { chatActivityEnterView.setVisibility(View.VISIBLE); bottomOverlayChat.setVisibility(View.INVISIBLE); } } if (topViewWasVisible == 1) { chatActivityEnterView.showTopView(false, false); topViewWasVisible = 0; } } checkRaiseSensors(); } public void updateReplyMessageHeader(boolean notify) { if (avatarContainer != null && threadMessageId != 0) { if (isComments) { if (threadMessageObject.hasReplies()) { avatarContainer.setTitle(LocaleController.formatPluralString("Comments", threadMessageObject.getRepliesCount())); } else { avatarContainer.setTitle(LocaleController.getString("CommentsTitle", R.string.CommentsTitle)); } } else { avatarContainer.setTitle(LocaleController.formatPluralString("Replies", threadMessageObject.getRepliesCount())); } } if (replyMessageHeaderObject == null) { return; } String text; if (threadMessageObject.getRepliesCount() == 0) { if (isComments) { text = LocaleController.getString("NoComments", R.string.NoComments); } else { text = LocaleController.getString("NoReplies", R.string.NoReplies); } } else { text = LocaleController.getString("DiscussionStarted", R.string.DiscussionStarted); } replyMessageHeaderObject.messageText = replyMessageHeaderObject.messageOwner.message = text; if (notify) { chatAdapter.updateRowWithMessageObject(replyMessageHeaderObject, true); } } public void showAlert(String name, String message) { if (alertView == null || name == null || message == null) { return; } if (alertView.getTag() != null) { alertView.setTag(null); if (alertViewAnimator != null) { alertViewAnimator.cancel(); alertViewAnimator = null; } if (alertView.getVisibility() != View.VISIBLE) { alertViewEnterProgress = 0; invalidateChatListViewTopPadding(); } alertView.setVisibility(View.VISIBLE); alertViewAnimator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(alertViewEnterProgress, 1f); animator.addUpdateListener(valueAnimator -> { alertViewEnterProgress = (float) valueAnimator.getAnimatedValue(); invalidateChatListViewTopPadding(); }); alertViewAnimator.playTogether(animator); alertViewAnimator.setDuration(200); alertViewAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (alertViewAnimator != null && alertViewAnimator.equals(animation)) { alertViewEnterProgress = 1f; invalidateChatListViewTopPadding(); alertViewAnimator = null; } } @Override public void onAnimationCancel(Animator animation) { if (alertViewAnimator != null && alertViewAnimator.equals(animation)) { alertViewAnimator = null; } } }); alertViewAnimator.start(); } alertNameTextView.setText(name); alertTextView.setText(Emoji.replaceEmoji(message.replace('\n', ' '), alertTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); if (hideAlertViewRunnable != null) { AndroidUtilities.cancelRunOnUIThread(hideAlertViewRunnable); } AndroidUtilities.runOnUIThread(hideAlertViewRunnable = new Runnable() { @Override public void run() { if (hideAlertViewRunnable != this) { return; } if (alertView.getTag() == null) { alertView.setTag(1); if (alertViewAnimator != null) { alertViewAnimator.cancel(); alertViewAnimator = null; } alertViewAnimator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(alertViewEnterProgress, 0f); animator.addUpdateListener(valueAnimator -> { alertViewEnterProgress = (float) valueAnimator.getAnimatedValue(); invalidateChatListViewTopPadding(); }); alertViewAnimator.playTogether(animator); alertViewAnimator.setDuration(200); alertViewAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (alertViewAnimator != null && alertViewAnimator.equals(animation)) { alertView.setVisibility(View.GONE); alertViewEnterProgress = 0; invalidateChatListViewTopPadding(); alertViewAnimator = null; } } @Override public void onAnimationCancel(Animator animation) { if (alertViewAnimator != null && alertViewAnimator.equals(animation)) { alertViewAnimator = null; } } }); alertViewAnimator.start(); } } }, 3000); } private boolean hidePinnedMessageView(boolean animated) { if (pinnedMessageView != null && pinnedMessageView.getTag() == null) { for (int a = 0; a < pinnedNextAnimation.length; a++) { if (pinnedNextAnimation[a] != null) { pinnedNextAnimation[a].cancel(); pinnedNextAnimation[a] = null; } } setPinnedTextTranslationX = false; pinnedMessageView.setTag(1); if (pinnedMessageViewAnimator != null) { pinnedMessageViewAnimator.cancel(); pinnedMessageViewAnimator = null; } if (animated) { pinnedMessageViewAnimator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(pinnedMessageEnterOffset, -AndroidUtilities.dp(50)); animator.addUpdateListener(animation -> { pinnedMessageEnterOffset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); chatListView.invalidate(); }); pinnedMessageViewAnimator.playTogether(animator); pinnedMessageViewAnimator.setDuration(200); pinnedMessageViewAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (pinnedMessageViewAnimator != null && pinnedMessageViewAnimator.equals(animation)) { pinnedMessageView.setVisibility(View.GONE); pinnedMessageViewAnimator = null; } } @Override public void onAnimationCancel(Animator animation) { if (pinnedMessageViewAnimator != null && pinnedMessageViewAnimator.equals(animation)) { pinnedMessageViewAnimator = null; } } }); pinnedMessageViewAnimator.start(); } else { pinnedMessageEnterOffset = -AndroidUtilities.dp(50); pinnedMessageView.setVisibility(View.GONE); chatListView.invalidate(); } return true; } return false; } private void updatePinnedMessageView(boolean animated) { updatePinnedMessageView(animated, 0); } private void updatePinnedListButton(boolean animated) { if (isThreadChat() || pinnedListButton == null) { return; } boolean show = pinnedMessageIds.size() > 1 && !pinnedMessageButtonShown; boolean visible = pinnedListButton.getTag() != null; boolean progressIsVisible = pinnedProgress.getTag() != null; boolean closeIsVisible = closePinned.getTag() != null; boolean showClosed = !show && !pinnedProgressIsShowing && !pinnedMessageButtonShown; boolean showPinned = show && !pinnedProgressIsShowing && !pinnedMessageButtonShown; boolean showProgress = pinnedProgressIsShowing && !pinnedMessageButtonShown; if (visible != show || progressIsVisible != showProgress || closeIsVisible != showClosed) { if (pinnedListAnimator != null) { pinnedListAnimator.cancel(); pinnedListAnimator = null; } if (animated) { if (show) { pinnedListButton.setVisibility(View.VISIBLE); } else if (showClosed) { closePinned.setVisibility(View.VISIBLE); } if (showProgress) { pinnedProgress.setVisibility(View.VISIBLE); pinnedProgress.setAlpha(0); pinnedProgress.setScaleX(0.4f); pinnedProgress.setScaleY(0.4f); } pinnedListAnimator = new AnimatorSet(); pinnedListAnimator.playTogether( ObjectAnimator.ofFloat(pinnedListButton, View.ALPHA, showPinned ? 1.0f : 0.0f), ObjectAnimator.ofFloat(pinnedListButton, View.SCALE_X, showPinned ? 1.0f : 0.4f), ObjectAnimator.ofFloat(pinnedListButton, View.SCALE_Y, showPinned ? 1.0f : 0.4f), ObjectAnimator.ofFloat(closePinned, View.ALPHA, showClosed ? 1.0f : 0.0f), ObjectAnimator.ofFloat(closePinned, View.SCALE_X, showClosed ? 1.0f : 0.4f), ObjectAnimator.ofFloat(closePinned, View.SCALE_Y, showClosed ? 1.0f : 0.4f), ObjectAnimator.ofFloat(pinnedProgress, View.ALPHA, !showProgress ? 0.0f : 1.0f), ObjectAnimator.ofFloat(pinnedProgress, View.SCALE_X, !showProgress ? 0.4f : 1.0f), ObjectAnimator.ofFloat(pinnedProgress, View.SCALE_Y, !showProgress ? 0.4f : 1.0f) ); pinnedListAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); pinnedListAnimator.setDuration(180 * 2); pinnedListAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { pinnedListAnimator = null; closePinned.setVisibility(showClosed ? View.VISIBLE : View.INVISIBLE); pinnedListButton.setVisibility(showPinned ? View.VISIBLE : View.INVISIBLE); pinnedProgress.setVisibility(showProgress ? View.VISIBLE : View.INVISIBLE); } }); pinnedListAnimator.start(); } else { closePinned.setAlpha(showClosed ? 1.0f : 0.0f); closePinned.setScaleX(showClosed ? 1.0f : 0.4f); closePinned.setScaleY(showClosed ? 1.0f : 0.4f); closePinned.setVisibility(showClosed ? View.VISIBLE : View.INVISIBLE); pinnedListButton.setAlpha(showPinned ? 1.0f : 0.0f); pinnedListButton.setScaleX(showPinned ? 1.0f : 0.4f); pinnedListButton.setScaleY(showPinned ? 1.0f : 0.4f); pinnedListButton.setVisibility(showPinned ? View.VISIBLE : View.INVISIBLE); pinnedProgress.setAlpha(showProgress ? 1.0f : 0.0f); pinnedProgress.setScaleX(showProgress ? 1.0f : 0.4f); pinnedProgress.setScaleY(showProgress ? 1.0f : 0.4f); pinnedProgress.setVisibility(showProgress ? View.VISIBLE : View.GONE); } closePinned.setTag(showClosed ? 1 : null); pinnedListButton.setTag(show ? 1 : null); pinnedProgress.setTag(showProgress ? 1 : null); } if (pinnedLineView != null) { if (isThreadChat()) { pinnedLineView.set(0, 1, false); } else { int position = Collections.binarySearch(pinnedMessageIds, currentPinnedMessageId, Comparator.reverseOrder()); pinnedLineView.set(pinnedMessageIds.size() - 1 - position, pinnedMessageIds.size(), animated); } } } private TLRPC.KeyboardButton pinnedButton(MessageObject message) { return (message != null && message.messageOwner != null && message.messageOwner.reply_markup != null && message.messageOwner.reply_markup.rows != null && message.messageOwner.reply_markup.rows.size() == 1 && message.messageOwner.reply_markup.rows.get(0) != null && message.messageOwner.reply_markup.rows.get(0).buttons != null && message.messageOwner.reply_markup.rows.get(0).buttons.size() == 1 ? message.messageOwner.reply_markup.rows.get(0).buttons.get(0) : null ); } private void updatePinnedMessageView(boolean animated, int animateToNext) { if (pinnedMessageView == null || chatMode != 0) { return; } int pinned_msg_id; boolean changed = false; MessageObject pinnedMessageObject; if (isThreadChat()) { if (!threadMessageVisible) { pinnedMessageObject = threadMessageObject; pinned_msg_id = threadMessageId; } else { pinnedMessageObject = null; pinned_msg_id = 0; } } else if (currentPinnedMessageId != 0 && !pinnedMessageIds.isEmpty()) { pinnedMessageObject = pinnedMessageObjects.get(currentPinnedMessageId); if (pinnedMessageObject == null) { pinnedMessageObject = messagesDict[0].get(currentPinnedMessageId); } pinned_msg_id = currentPinnedMessageId; } else { pinnedMessageObject = null; pinned_msg_id = 0; } TLRPC.KeyboardButton botButton = pinnedButton(pinnedMessageObject); pinnedMessageButtonShown = botButton != null; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (threadMessageObject == null && (chatInfo == null && userInfo == null || pinned_msg_id == 0 || !pinnedMessageIds.isEmpty() && pinnedMessageIds.get(0) == preferences.getInt("pin_" + dialog_id, 0)) || reportType >= 0 || actionBar != null && (actionBar.isActionModeShowed() || actionBar.isSearchFieldVisible())) { changed = hidePinnedMessageView(animated); } else { updatePinnedListButton(animated); if (pinnedMessageObject != null) { if (pinnedMessageView.getTag() != null) { pinnedMessageView.setTag(null); changed = true; if (pinnedMessageViewAnimator != null) { pinnedMessageViewAnimator.cancel(); pinnedMessageViewAnimator = null; } if (animated) { ValueAnimator animator = ValueAnimator.ofFloat(pinnedMessageEnterOffset, 0); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { int position = -1; @Override public void onAnimationUpdate(ValueAnimator animation) { pinnedMessageEnterOffset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } }); pinnedMessageView.setVisibility(View.VISIBLE); pinnedMessageViewAnimator = new AnimatorSet(); pinnedMessageViewAnimator.playTogether(animator); pinnedMessageViewAnimator.setDuration(200); pinnedMessageViewAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (pinnedMessageViewAnimator != null && pinnedMessageViewAnimator.equals(animation)) { pinnedMessageViewAnimator = null; } } @Override public void onAnimationCancel(Animator animation) { if (pinnedMessageViewAnimator != null && pinnedMessageViewAnimator.equals(animation)) { pinnedMessageViewAnimator = null; } } }); pinnedMessageViewAnimator.start(); } else { pinnedMessageEnterOffset = 0; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); pinnedMessageView.setVisibility(View.VISIBLE); } } for (int a = 0; a < pinnedNextAnimation.length; a++) { if (pinnedNextAnimation[a] != null) { pinnedNextAnimation[a].cancel(); pinnedNextAnimation[a] = null; } } setPinnedTextTranslationX = false; TrackingWidthSimpleTextView nameTextView = pinnedNameTextView[animateToNext != 0 ? 1 : 0]; SimpleTextView messageTextView = pinnedMessageTextView[animateToNext != 0 ? 1 : 0]; PinnedMessageButton buttonTextView = pinnedMessageButton[animateToNext != 0 ? 1 : 0]; buttonTextView.setVisibility(botButton != null ? View.VISIBLE : View.GONE); pinnedMessageButton[animateToNext != 0 ? 0 : 1].setOnClickListener(null); pinnedMessageButton[animateToNext != 0 ? 0 : 1].setOnLongClickListener(null); if (botButton == null) { buttonTextView.setText(null); buttonTextView.setOnClickListener(null); } else { SpannableString string = new SpannableString(botButton.text); Emoji.replaceEmoji(string, buttonTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); buttonTextView.setText(string); final MessageObject buttonMessage = pinnedMessageObject; buttonTextView.setOnClickListener(e -> { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && !(botButton instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(botButton instanceof TLRPC.TL_keyboardButtonCallback) && !(botButton instanceof TLRPC.TL_keyboardButtonGame) && !(botButton instanceof TLRPC.TL_keyboardButtonUrl) && !(botButton instanceof TLRPC.TL_keyboardButtonBuy) && !(botButton instanceof TLRPC.TL_keyboardButtonUrlAuth) && !(botButton instanceof TLRPC.TL_keyboardButtonUserProfile)) { return; } chatActivityEnterView.didPressedBotButton(botButton, buttonMessage, buttonMessage); }); buttonTextView.setOnLongClickListener(e -> { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && !(botButton instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(botButton instanceof TLRPC.TL_keyboardButtonCallback) && !(botButton instanceof TLRPC.TL_keyboardButtonGame) && !(botButton instanceof TLRPC.TL_keyboardButtonUrl) && !(botButton instanceof TLRPC.TL_keyboardButtonBuy) && !(botButton instanceof TLRPC.TL_keyboardButtonUrlAuth) && !(botButton instanceof TLRPC.TL_keyboardButtonUserProfile)) { return false; } if (botButton instanceof TLRPC.TL_keyboardButtonUrl) { openClickableLink(null, botButton.url, true, null, buttonMessage); try { buttonTextView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} return true; } return false; }); } buttonTextView.measure(View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(28), View.MeasureSpec.EXACTLY)); if (messageTextView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ((ViewGroup.MarginLayoutParams) messageTextView.getLayoutParams()).rightMargin = ( (botButton == null ? AndroidUtilities.dp(44) : buttonTextView.getMeasuredWidth() + AndroidUtilities.dp(14 + 8)) ); } if (nameTextView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ((ViewGroup.MarginLayoutParams) nameTextView.getLayoutParams()).rightMargin = ( (botButton == null ? AndroidUtilities.dp(44) : buttonTextView.getMeasuredWidth() + AndroidUtilities.dp(14 + 8)) ); } FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) pinnedNameTextView[0].getLayoutParams(); FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) pinnedNameTextView[1].getLayoutParams(); FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) pinnedCounterTextView.getLayoutParams(); FrameLayout.LayoutParams layoutParams4 = (FrameLayout.LayoutParams) pinnedMessageTextView[0].getLayoutParams(); FrameLayout.LayoutParams layoutParams5 = (FrameLayout.LayoutParams) pinnedMessageTextView[1].getLayoutParams(); int cacheType = 1; int size = 0; TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs2, AndroidUtilities.dp(320)); TLRPC.PhotoSize thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs2, AndroidUtilities.dp(40)); TLObject photoSizeObject = pinnedMessageObject.photoThumbsObject2; if (photoSize == null) { if (pinnedMessageObject.mediaExists) { photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); if (photoSize != null) { size = photoSize.size; } cacheType = 0; } else { photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.dp(320)); } thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.dp(40)); photoSizeObject = pinnedMessageObject.photoThumbsObject; } if (photoSize == thumbPhotoSize) { thumbPhotoSize = null; } boolean noImage; int prevMargin = layoutParams1.leftMargin; if (noImage = (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || pinnedMessageObject.isAnyKindOfSticker() || pinnedMessageObject.isSecretMedia())) { pinnedImageLocation = null; pinnedImageLocationObject = null; if (animateToNext == 0) { pinnedMessageImageView[0].setImageBitmap(null); pinnedMessageImageView[0].setVisibility(View.INVISIBLE); } layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = layoutParams4.leftMargin = layoutParams5.leftMargin = AndroidUtilities.dp(18); } else { if (pinnedMessageObject.isRoundVideo()) { pinnedMessageImageView[1].setRoundRadius(AndroidUtilities.dp(16)); } else { pinnedMessageImageView[1].setRoundRadius(AndroidUtilities.dp(2)); } pinnedImageSize = size; pinnedImageCacheType = cacheType; pinnedImageLocation = photoSize; pinnedImageThumbLocation = thumbPhotoSize; pinnedImageLocationObject = photoSizeObject; pinnedMessageImageView[1].setImage(ImageLocation.getForObject(pinnedImageLocation, photoSizeObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), "50_50_b", null, size, cacheType, pinnedMessageObject); pinnedMessageImageView[1].setVisibility(View.VISIBLE); if (animateToNext != 0) { pinnedMessageImageView[1].setAlpha(0.0f); } layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = layoutParams4.leftMargin = layoutParams5.leftMargin = AndroidUtilities.dp(55); } pinnedNameTextView[0].setLayoutParams(layoutParams1); pinnedNameTextView[1].setLayoutParams(layoutParams2); pinnedCounterTextView.setLayoutParams(layoutParams3); pinnedMessageTextView[0].setLayoutParams(layoutParams4); pinnedMessageTextView[1].setLayoutParams(layoutParams5); boolean showCounter = false; boolean shouldAnimateName = loadedPinnedMessagesCount == 2 || !pinnedNameTextView[animateToNext != 0 ? 0 : 1].getTrackWidth(); pinnedNameTextView[animateToNext != 0 ? 0 : 1].setTrackWidth(false); nameTextView.setTrackWidth(true); nameTextView.setVisibility(View.VISIBLE); if (threadMessageId != 0) { MessagesController messagesController = getMessagesController(); TLRPC.MessageFwdHeader fwd_from = threadMessageObject.messageOwner.fwd_from; TLRPC.User user = null; TLRPC.Chat chat = null; if (fwd_from != null && fwd_from.saved_from_peer != null) { if (fwd_from.saved_from_peer.user_id != 0) { if (fwd_from.from_id instanceof TLRPC.TL_peerUser) { user = messagesController.getUser(fwd_from.from_id.user_id); } else { user = messagesController.getUser(fwd_from.saved_from_peer.user_id); } } else if (fwd_from.saved_from_peer.channel_id != 0) { if (threadMessageObject.isSavedFromMegagroup() && fwd_from.from_id instanceof TLRPC.TL_peerUser) { user = messagesController.getUser(fwd_from.from_id.user_id); } else { chat = messagesController.getChat(fwd_from.saved_from_peer.channel_id); } } else if (fwd_from.saved_from_peer.chat_id != 0) { if (fwd_from.from_id instanceof TLRPC.TL_peerUser) { user = messagesController.getUser(fwd_from.from_id.user_id); } else if (fwd_from.from_id instanceof TLRPC.TL_peerChat) { chat = messagesController.getChat(fwd_from.from_id.chat_id); } else if (fwd_from.from_id instanceof TLRPC.TL_peerChannel) { chat = messagesController.getChat(fwd_from.from_id.channel_id); } else { chat = messagesController.getChat(fwd_from.saved_from_peer.chat_id); } } } else if (threadMessageObject.isFromUser()) { user = messagesController.getUser(threadMessageObject.messageOwner.from_id.user_id); } else if (threadMessageObject.messageOwner.from_id instanceof TLRPC.TL_peerChannel) { chat = messagesController.getChat(threadMessageObject.messageOwner.from_id.channel_id); } else if (threadMessageObject.messageOwner.from_id instanceof TLRPC.TL_peerChat) { chat = messagesController.getChat(threadMessageObject.messageOwner.from_id.chat_id); } else if (threadMessageObject.messageOwner.post) { chat = messagesController.getChat(threadMessageObject.messageOwner.peer_id.channel_id); } if (user != null) { nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); } else if (chat != null) { nameTextView.setText(chat.title); } } else { if (pinnedMessageObject.isInvoice() && pinnedMessageObject.messageOwner != null && pinnedMessageObject.messageOwner.media != null && pinnedMessageObject.messageOwner.media.title != null) { nameTextView.setTrackWidth(false); nameTextView.setText(pinnedMessageObject.messageOwner.media.title); shouldAnimateName = true; showCounter = false; } else { if (currentPinnedMessageIndex[0] == 0 || loadedPinnedMessagesCount != 2) { nameTextView.setText(LocaleController.getString("PinnedMessage", R.string.PinnedMessage), true); } else { nameTextView.setText(LocaleController.getString("PreviousPinnedMessage", R.string.PreviousPinnedMessage), true); } if (currentPinnedMessageIndex[0] != 0) { int total = getPinnedMessagesCount(); pinnedCounterTextView.setNumber(Math.min(total - 1, Math.max(1, total - currentPinnedMessageIndex[0])), animated && pinnedCounterTextView.getTag() == null); showCounter = true; } } } CharSequence pinnedText = null; if (pinnedMessageObject.type == 14) { pinnedText = String.format("%s - %s", pinnedMessageObject.getMusicAuthor(), pinnedMessageObject.getMusicTitle()); } else if (pinnedMessageObject.type == MessageObject.TYPE_POLL) { TLRPC.TL_messageMediaPoll poll = (TLRPC.TL_messageMediaPoll) pinnedMessageObject.messageOwner.media; String mess = poll.poll.question; if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); pinnedText = mess; } else if (pinnedMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { pinnedText = Emoji.replaceEmoji(pinnedMessageObject.messageOwner.media.game.title, messageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); } else if (!TextUtils.isEmpty(pinnedMessageObject.caption)) { String mess = pinnedMessageObject.caption.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); CharSequence message = mess; if (pinnedMessageObject != null && pinnedMessageObject.messageOwner != null) { message = MessageObject.replaceAnimatedEmoji(mess, pinnedMessageObject.messageOwner.entities, messageTextView.getPaint().getFontMetricsInt()); } pinnedText = Emoji.replaceEmoji(message, messageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); } else if (pinnedMessageObject.messageText != null) { String mess = pinnedMessageObject.messageText.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); CharSequence message = mess; if (pinnedMessageObject != null && pinnedMessageObject.messageOwner != null) { message = MessageObject.replaceAnimatedEmoji(mess, pinnedMessageObject.messageOwner.entities, messageTextView.getPaint().getFontMetricsInt()); } pinnedText = Emoji.replaceEmoji(message, messageTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); } if (pinnedText != null) { if (pinnedText instanceof Spannable) { MediaDataController.addTextStyleRuns(pinnedMessageObject, (Spannable) pinnedText, TextStyleSpan.FLAG_STYLE_SPOILER | TextStyleSpan.FLAG_STYLE_STRIKE); } messageTextView.setText(AnimatedEmojiSpan.cloneSpans(pinnedText)); } if (animateToNext != 0) { pinnedNextAnimation[0] = new AnimatorSet(); pinnedNextAnimation[1] = new AnimatorSet(); ArrayList animators = new ArrayList<>(); ArrayList animators2 = new ArrayList<>(); messageTextView.setVisibility(View.VISIBLE); nameTextView.setVisibility(View.VISIBLE); if (botButton != null) { buttonTextView.setVisibility(View.VISIBLE); } if (!showCounter) { if (pinnedCounterTextView.getTag() == null) { animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.ALPHA, 1.0f, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_Y, 0.0f, -AndroidUtilities.dp(4))); pinnedCounterTextView.setTag(1); } } else { if (pinnedCounterTextView.getTag() != null) { pinnedCounterTextView.setVisibility(View.VISIBLE); pinnedCounterTextView.setAlpha(0.0f); animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.ALPHA, 0.0f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_Y, -AndroidUtilities.dp(4), 0)); pinnedCounterTextView.setTag(null); } } boolean animateName; if (shouldAnimateName && !TextUtils.equals(nameTextView.getText(), pinnedNameTextView[0].getText())) { nameTextView.setAlpha(0); animators.add(ObjectAnimator.ofFloat(nameTextView, View.ALPHA, 0.0f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.ALPHA, 1.0f, 0.0f)); animators.add(ObjectAnimator.ofFloat(nameTextView, View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 4 : -4), 0.0f)); if (animateName = forceScrollToFirst && loadedPinnedMessagesCount > 5) { animators2.add(ObjectAnimator.ofFloat(nameTextView, View.TRANSLATION_Y, AndroidUtilities.dp(4), AndroidUtilities.dp(-2))); } else { animators.add(ObjectAnimator.ofFloat(nameTextView, View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 4 : -4), 0.0f)); } animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -4 : 4))); } else { animateName = false; if (nameTextView != pinnedNameTextView[0]) { nameTextView.setAlpha(1.0f); pinnedNameTextView[0].setAlpha(0.0f); nameTextView.setTranslationY(0.0f); pinnedNameTextView[0].setTranslationY(0.0f); } else { nameTextView.setAlpha(1.0f); nameTextView.setTranslationY(0.0f); pinnedNameTextView[1].setTranslationY(0.0f); pinnedNameTextView[1].setAlpha(0.0f); } } boolean animateText; if (!TextUtils.equals(messageTextView.getText(), pinnedMessageTextView[0].getText())) { messageTextView.setAlpha(0); animators.add(ObjectAnimator.ofFloat(messageTextView, View.ALPHA, 0.0f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.ALPHA, 1.0f, 0.0f)); if (animateText = forceScrollToFirst && loadedPinnedMessagesCount > 5) { animators2.add(ObjectAnimator.ofFloat(messageTextView, View.TRANSLATION_Y, AndroidUtilities.dp(4), AndroidUtilities.dp(-2))); } else { animators.add(ObjectAnimator.ofFloat(messageTextView, View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 4 : -4), 0.0f)); } animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -4 : 4))); } else { animateText = false; messageTextView.setAlpha(1.0f); pinnedMessageTextView[0].setAlpha(0.0f); messageTextView.setTranslationY(0.0f); pinnedMessageTextView[0].setTranslationY(0.0f); } boolean animateButton; if (!TextUtils.equals(buttonTextView.getText(), pinnedMessageButton[0].getText())) { buttonTextView.setAlpha(0); animators.add(ObjectAnimator.ofFloat(buttonTextView, View.ALPHA, 0.0f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[0], View.ALPHA, 1.0f, 0.0f)); if (animateButton = forceScrollToFirst && loadedPinnedMessagesCount > 5) { animators2.add(ObjectAnimator.ofFloat(buttonTextView, View.TRANSLATION_Y, AndroidUtilities.dp(4), AndroidUtilities.dp(-2))); } else { animators.add(ObjectAnimator.ofFloat(buttonTextView, View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 4 : -4), 0.0f)); } animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -4 : 4))); } else { animateButton = false; buttonTextView.setAlpha(1.0f); pinnedMessageButton[0].setAlpha(0.0f); buttonTextView.setTranslationY(0.0f); pinnedMessageButton[0].setTranslationY(0.0f); } BackupImageView animateImage; if (layoutParams1.leftMargin != prevMargin) { animateImage = null; setPinnedTextTranslationX = true; int diff = prevMargin - layoutParams1.leftMargin; animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[1], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[1], View.TRANSLATION_X, diff, 0.0f)); // animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[0], View.TRANSLATION_X, diff, 0.0f)); // animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[1], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_X, pinnedCounterTextViewX + diff, pinnedCounterTextViewX)); if (diff > 0) { pinnedMessageImageView[0].setAlpha(1f); animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.ALPHA, 1.0f, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.SCALE_X, 1.0f, 0.7f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.SCALE_Y, 1.0f, 0.7f)); } else { animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.ALPHA, 0.0f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.SCALE_X, 0.7f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.SCALE_Y, 0.7f, 1.0f)); } } else { setPinnedTextTranslationX = false; messageTextView.setTranslationX(0); pinnedMessageTextView[0].setTranslationX(0); nameTextView.setTranslationX(0); pinnedNameTextView[0].setTranslationX(0); buttonTextView.setTranslationX(0); pinnedMessageButton[0].setTranslationX(0); pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); pinnedMessageImageView[1].setAlpha(1.0f); if (!noImage) { animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.ALPHA, 0.0f, 1.0f)); animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.ALPHA, 1.0f, 0.0f)); if (forceScrollToFirst && loadedPinnedMessagesCount > 5) { animateImage = pinnedMessageImageView[1]; animators2.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.TRANSLATION_Y, AndroidUtilities.dp(3), AndroidUtilities.dp(-2))); } else { animateImage = null; animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[1], View.TRANSLATION_Y, AndroidUtilities.dp(animateToNext == 2 ? 3 : -3), 0.0f)); } animators.add(ObjectAnimator.ofFloat(pinnedMessageImageView[0], View.TRANSLATION_Y, 0.0f, AndroidUtilities.dp(animateToNext == 2 ? -3 : 3))); } else { animateImage = null; } } pinnedNextAnimation[1].addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { pinnedNextAnimation[1] = null; pinnedMessageImageView[1].setTranslationY(0); } @Override public void onAnimationEnd(Animator animation) { if (animation.equals(pinnedNextAnimation[1])) { if (animateName || animateText || animateImage != null) { pinnedNextAnimation[1] = new AnimatorSet(); pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); pinnedNextAnimation[1].setDuration(180 * 2); ArrayList animators1 = new ArrayList<>(); if (animateName) { animators1.add(ObjectAnimator.ofFloat(nameTextView, View.TRANSLATION_Y, 0.0f)); } if (animateText) { animators1.add(ObjectAnimator.ofFloat(messageTextView, View.TRANSLATION_Y, 0.0f)); } if (animateButton) { animators1.add(ObjectAnimator.ofFloat(buttonTextView, View.TRANSLATION_Y, 0.0f)); } if (animateImage != null) { animators1.add(ObjectAnimator.ofFloat(animateImage, View.TRANSLATION_Y, 0.0f)); } pinnedNextAnimation[1].addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animateName) { nameTextView.setTranslationY(0.0f); } if (animateText) { messageTextView.setTranslationY(0.0f); } if (animateButton) { buttonTextView.setTranslationY(0.0f); } if (animateImage != null) { animateImage.setTranslationY(0.0f); } pinnedNextAnimation[1] = null; } }); pinnedNextAnimation[1].playTogether(animators1); pinnedNextAnimation[1].start(); } else { pinnedNextAnimation[1] = null; } } } }); pinnedNextAnimation[1].setDuration(180 * 2); // if (forceScrollToFirst && loadedPinnedMessagesCount > 5) { pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); // } pinnedNextAnimation[1].playTogether(animators2); pinnedNextAnimation[0].playTogether(animators); pinnedNextAnimation[0].addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (pinnedCounterTextView.getTag() != null) { pinnedCounterTextView.setVisibility(View.INVISIBLE); int total = getPinnedMessagesCount(); pinnedCounterTextView.setNumber(Math.min(total - 1, Math.max(1, total - currentPinnedMessageIndex[0])), false); } else { pinnedCounterTextView.setAlpha(1.0f); } pinnedCounterTextView.setTranslationY(0.0f); pinnedMessageTextView[0].setTranslationX(0); pinnedMessageTextView[1].setTranslationX(0); pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); nameTextView.setTranslationY(0.0f); if (!animateText) { nameTextView.setTranslationY(0.0f); } if (!animateText) { messageTextView.setTranslationY(0.0f); } if (!animateButton) { buttonTextView.setTranslationY(0.0f); } pinnedNameTextView[0].setTranslationX(0); pinnedNameTextView[1].setTranslationX(0); pinnedMessageImageView[1].setAlpha(1.0f); pinnedMessageImageView[1].setScaleX(1f); pinnedMessageImageView[1].setScaleY(1f); pinnedMessageImageView[0].setAlpha(1.0f); pinnedMessageImageView[0].setScaleX(1f); pinnedMessageImageView[0].setScaleY(1f); pinnedMessageTextView[1] = pinnedMessageTextView[0]; pinnedMessageTextView[0] = messageTextView; pinnedMessageTextView[1].setVisibility(View.INVISIBLE); pinnedMessageButton[1] = pinnedMessageButton[0]; pinnedMessageButton[0] = buttonTextView; pinnedMessageButton[1].setVisibility(View.INVISIBLE); if (nameTextView != pinnedNameTextView[0]) { pinnedNameTextView[1] = pinnedNameTextView[0]; pinnedNameTextView[0] = nameTextView; pinnedNameTextView[1].setVisibility(View.INVISIBLE); } if (noImage) { pinnedMessageImageView[1].setImageBitmap(null); pinnedMessageImageView[1].setVisibility(View.INVISIBLE); } BackupImageView backupImageView = pinnedMessageImageView[1]; pinnedMessageImageView[1] = pinnedMessageImageView[0]; pinnedMessageImageView[0] = backupImageView; pinnedMessageImageView[1].setAlpha(1.0f); pinnedMessageImageView[1].setScaleX(1f); pinnedMessageImageView[1].setScaleY(1f); pinnedMessageImageView[1].setVisibility(View.INVISIBLE); pinnedNextAnimation[0] = null; setPinnedTextTranslationX = false; } }); pinnedNextAnimation[0].setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); pinnedNextAnimation[0].setDuration(180 * 2); if (!setPinnedTextTranslationX) { pinnedNextAnimation[0].start(); pinnedNextAnimation[1].start(); } } else { if (!showCounter || currentPinnedMessageIndex[0] == 0) { if (pinnedCounterTextView.getTag() == null) { pinnedCounterTextView.setAlpha(0.0f); pinnedCounterTextView.setVisibility(View.INVISIBLE); pinnedCounterTextView.setTag(1); } } else { if (pinnedCounterTextView.getTag() != null) { pinnedCounterTextView.setVisibility(View.VISIBLE); pinnedCounterTextView.setAlpha(1.0f); pinnedCounterTextView.setTag(null); } } pinnedCounterTextView.setTranslationY(0.0f); pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); pinnedCounterTextView.setAlpha(shouldAnimateName || currentPinnedMessageIndex[0] == 0 ? 0.0f : 1.0f); messageTextView.setVisibility(View.VISIBLE); messageTextView.setAlpha(1.0f); messageTextView.setTranslationX(0); messageTextView.setTranslationY(0); nameTextView.setVisibility(View.VISIBLE); nameTextView.setAlpha(1.0f); nameTextView.setTranslationX(0); nameTextView.setTranslationY(0); pinnedMessageTextView[1].setVisibility(View.INVISIBLE); pinnedMessageTextView[1].setTranslationX(0); pinnedMessageTextView[1].setTranslationY(0); pinnedMessageButton[1].setVisibility(View.INVISIBLE); pinnedMessageButton[1].setTranslationX(0); pinnedMessageButton[1].setTranslationY(0); pinnedNameTextView[1].setVisibility(View.INVISIBLE); pinnedNameTextView[1].setTranslationX(0); pinnedNameTextView[1].setTranslationY(0); pinnedMessageImageView[0].setVisibility(View.INVISIBLE); BackupImageView backupImageView = pinnedMessageImageView[1]; pinnedMessageImageView[1] = pinnedMessageImageView[0]; pinnedMessageImageView[0] = backupImageView; pinnedMessageImageView[0].setAlpha(1.0f); pinnedMessageImageView[0].setScaleX(1f); pinnedMessageImageView[0].setScaleY(1f); pinnedMessageImageView[0].setTranslationY(0); pinnedMessageImageView[1].setAlpha(1.0f); pinnedMessageImageView[1].setScaleX(1f); pinnedMessageImageView[1].setScaleY(1f); pinnedMessageImageView[1].setTranslationY(0); } if (isThreadChat()) { pinnedLineView.set(0, 1, false); } else { int position = Collections.binarySearch(pinnedMessageIds, currentPinnedMessageId, Comparator.reverseOrder()); pinnedLineView.set(pinnedMessageIds.size() - 1 - position, pinnedMessageIds.size(), animated); } } else { pinnedCounterTextView.setVisibility(loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0 ? View.INVISIBLE : View.VISIBLE); pinnedCounterTextView.setAlpha(loadedPinnedMessagesCount == 2 || currentPinnedMessageIndex[0] == 0 ? 0.0f : 1.0f); pinnedImageLocation = null; pinnedImageLocationObject = null; changed = hidePinnedMessageView(animated); if (loadingPinnedMessages.indexOfKey(pinned_msg_id) < 0) { loadingPinnedMessages.put(pinned_msg_id, true); ArrayList ids = new ArrayList<>(); ids.add(pinned_msg_id); getMediaDataController().loadPinnedMessages(dialog_id, ChatObject.isChannel(currentChat) ? currentChat.id : 0, ids, true); } } } if (changed) { checkListViewPaddings(); } } private class TrackingWidthSimpleTextView extends SimpleTextView { public TrackingWidthSimpleTextView(Context context) { super(context); } private boolean trackWidth = true; public void setTrackWidth(boolean value) { this.trackWidth = value; } public boolean getTrackWidth() { return this.trackWidth; } @Override protected boolean createLayout(int width) { boolean result = super.createLayout(width); if (trackWidth && getVisibility() == View.VISIBLE) { pinnedCounterTextViewX = getTextWidth() + AndroidUtilities.dp(4); if (pinnedCounterTextView != null) { pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); } } return result; } } private void updateTopPanel(boolean animated) { if (topChatPanelView == null || chatMode != 0) { return; } SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); boolean show; long did = dialog_id; if (currentEncryptedChat != null) { show = !(currentEncryptedChat.admin_id == getUserConfig().getClientUserId() || getContactsController().isLoadingContacts()) && getContactsController().contactsDict.get(currentUser.id) == null; did = currentUser.id; int vis = preferences.getInt("dialog_bar_vis3" + did, 0); if (show && (vis == 1 || vis == 3)) { show = false; } } else { show = preferences.getInt("dialog_bar_vis3" + did, 0) == 2; } boolean showShare = preferences.getBoolean("dialog_bar_share" + did, false); boolean showReport = preferences.getBoolean("dialog_bar_report" + did, false); boolean showBlock = preferences.getBoolean("dialog_bar_block" + did, false); boolean showAdd = preferences.getBoolean("dialog_bar_add" + did, false); boolean showArchive = preferences.getBoolean("dialog_bar_archived" + dialog_id, false); boolean showGeo = preferences.getBoolean("dialog_bar_location" + did, false); String chatWithAdmin = preferences.getString("dialog_bar_chat_with_admin_title" + did, null); boolean chatWithAdminChannel = preferences.getBoolean("dialog_bar_chat_with_channel" + did, false); int chatWithAdminDate = preferences.getInt("dialog_bar_chat_with_date" + did, 0); boolean showAddMembersToGroup = preferences.getBoolean("dialog_bar_invite" + did, false); if (showAddMembersToGroup) { show = true; } if (showReport || showBlock || showGeo) { reportSpamButton.setVisibility(View.VISIBLE); } else { reportSpamButton.setVisibility(View.GONE); } addToContactsButtonArchive = false; TLRPC.User user = currentUser != null ? getMessagesController().getUser(currentUser.id) : null; boolean isChatWithAdmin = false; if (user != null && !TextUtils.isEmpty(chatWithAdmin)) { isChatWithAdmin = true; if (chatWithAdminTextView == null) { chatWithAdminTextView = new TextView(topChatPanelView.getContext()); chatWithAdminTextView.setGravity(Gravity.CENTER_VERTICAL); chatWithAdminTextView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(46), 0); chatWithAdminTextView.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), 2)); topChatPanelView.addView(chatWithAdminTextView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 0, 1)); chatWithAdminTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); chatWithAdminTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); chatWithAdminTextView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AlertsCreator.showChatWithAdmin(ChatActivity.this, user, chatWithAdmin, chatWithAdminChannel, chatWithAdminDate); } }); } String str; if (chatWithAdminChannel) { str = LocaleController.formatString("ChatWithGroupAdmin", R.string.ChatWithGroupAdmin, user.first_name, chatWithAdmin); } else { str = LocaleController.formatString("ChatWithChannelAdmin", R.string.ChatWithChannelAdmin, user.first_name, chatWithAdmin); } reportSpamButton.setVisibility(View.GONE); addToContactsButton.setVisibility(View.GONE); chatWithAdminTextView.setText(AndroidUtilities.replaceTags(str)); } else if (showAddMembersToGroup) { String str = LocaleController.getString("GroupAddMembers", R.string.GroupAddMembers); if (str != null) { str = str.toUpperCase(); } addToContactsButton.setVisibility(View.VISIBLE); addToContactsButton.setText(str); addToContactsButton.setTag(4); addToContactsButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); if (Build.VERSION.SDK_INT >= 21) { Theme.setSelectorDrawableColor(addToContactsButton.getBackground(), getThemedColor(Theme.key_chat_addContact) & 0x19ffffff, true); } reportSpamButton.setTag(Theme.key_chat_addContact); } else if (user != null) { if (UserObject.isReplyUser(user)) { addToContactsButton.setVisibility(View.GONE); } else if (!user.contact && !user.self && showAdd) { addContactItem.setVisibility(View.VISIBLE); addContactItem.setText(LocaleController.getString("AddToContacts", R.string.AddToContacts)); addToContactsButton.setVisibility(View.VISIBLE); if (showArchive) { addToContactsButtonArchive = true; addToContactsButton.setText(LocaleController.getString("Unarchive", R.string.Unarchive).toUpperCase()); addToContactsButton.setTag(3); } else { if (reportSpamButton.getVisibility() == View.VISIBLE) { addToContactsButton.setText(LocaleController.getString("AddContactChat", R.string.AddContactChat)); } else { addToContactsButton.setText(LocaleController.formatString("AddContactFullChat", R.string.AddContactFullChat, UserObject.getFirstName(user)).toUpperCase()); } } addToContactsButton.setTag(null); addToContactsButton.setVisibility(View.VISIBLE); } else if (showShare && !user.self) { addContactItem.setVisibility(View.VISIBLE); addToContactsButton.setVisibility(View.VISIBLE); addContactItem.setText(LocaleController.getString("ShareMyContactInfo", R.string.ShareMyContactInfo)); addToContactsButton.setText(LocaleController.getString("ShareMyPhone", R.string.ShareMyPhone).toUpperCase()); addToContactsButton.setTag(1); addToContactsButton.setVisibility(View.VISIBLE); } else { if (!user.contact && !user.self && !show) { addContactItem.setVisibility(View.VISIBLE); addContactItem.setText(LocaleController.getString("ShareMyContactInfo", R.string.ShareMyContactInfo)); addToContactsButton.setTag(2); } else { addContactItem.setVisibility(View.GONE); } addToContactsButton.setVisibility(View.GONE); } reportSpamButton.setText(LocaleController.getString("ReportSpamUser", R.string.ReportSpamUser)); } else { if (showGeo) { reportSpamButton.setText(LocaleController.getString("ReportSpamLocation", R.string.ReportSpamLocation)); reportSpamButton.setTag(R.id.object_tag, 1); reportSpamButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); if (Build.VERSION.SDK_INT >= 21) { Theme.setSelectorDrawableColor(reportSpamButton.getBackground(), getThemedColor(Theme.key_chat_addContact) & 0x19ffffff, true); } reportSpamButton.setTag(Theme.key_chat_addContact); } else { if (showArchive) { addToContactsButtonArchive = true; addToContactsButton.setText(LocaleController.getString("Unarchive", R.string.Unarchive).toUpperCase()); addToContactsButton.setTag(3); addToContactsButton.setVisibility(View.VISIBLE); reportSpamButton.setText(LocaleController.getString("ReportSpam", R.string.ReportSpam)); } else { addToContactsButton.setVisibility(View.GONE); reportSpamButton.setText(LocaleController.getString("ReportSpamAndLeave", R.string.ReportSpamAndLeave)); } reportSpamButton.setTag(R.id.object_tag, null); reportSpamButton.setTextColor(getThemedColor(Theme.key_chat_reportSpam)); if (Build.VERSION.SDK_INT >= 21) { Theme.setSelectorDrawableColor(reportSpamButton.getBackground(), getThemedColor(Theme.key_chat_reportSpam) & 0x19ffffff, true); } reportSpamButton.setTag(Theme.key_chat_reportSpam); } if (addContactItem != null) { addContactItem.setVisibility(View.GONE); } } if (chatWithAdminTextView != null) { chatWithAdminTextView.setVisibility(isChatWithAdmin ? View.VISIBLE : View.GONE); } if (userBlocked || (addToContactsButton.getVisibility() == View.GONE && reportSpamButton.getVisibility() == View.GONE && (chatWithAdminTextView == null || chatWithAdminTextView.getVisibility() == View.GONE))) { show = false; } if (show) { if (topChatPanelView.getTag() != null) { if (BuildVars.LOGS_ENABLED) { FileLog.d("show spam button"); } topChatPanelView.setTag(null); topChatPanelView.setVisibility(View.VISIBLE); if (reportSpamViewAnimator != null) { reportSpamViewAnimator.cancel(); reportSpamViewAnimator = null; } if (animated) { reportSpamViewAnimator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(topChatPanelViewOffset, 0); animator.addUpdateListener(animation -> { topChatPanelViewOffset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); }); reportSpamViewAnimator.playTogether(animator); reportSpamViewAnimator.setDuration(200); reportSpamViewAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (reportSpamViewAnimator != null && reportSpamViewAnimator.equals(animation)) { reportSpamViewAnimator = null; } } @Override public void onAnimationCancel(Animator animation) { if (reportSpamViewAnimator != null && reportSpamViewAnimator.equals(animation)) { reportSpamViewAnimator = null; } } }); reportSpamViewAnimator.start(); } else { topChatPanelViewOffset = 0; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } } } else { if (topChatPanelView.getTag() == null) { if (BuildVars.LOGS_ENABLED) { FileLog.d("hide spam button"); } topChatPanelView.setTag(1); if (reportSpamViewAnimator != null) { reportSpamViewAnimator.cancel(); reportSpamViewAnimator = null; } if (animated) { reportSpamViewAnimator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(topChatPanelViewOffset, -AndroidUtilities.dp(50)); animator.addUpdateListener(animation -> { topChatPanelViewOffset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); }); reportSpamViewAnimator.playTogether(animator); reportSpamViewAnimator.setDuration(200); reportSpamViewAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (reportSpamViewAnimator != null && reportSpamViewAnimator.equals(animation)) { topChatPanelView.setVisibility(View.GONE); reportSpamViewAnimator = null; } } @Override public void onAnimationCancel(Animator animation) { if (reportSpamViewAnimator != null && reportSpamViewAnimator.equals(animation)) { reportSpamViewAnimator = null; } } }); reportSpamViewAnimator.start(); } else { topChatPanelViewOffset = -AndroidUtilities.dp(50); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } } } checkListViewPaddings(); } private void checkListViewPaddings() { if (!wasManualScroll && unreadMessageObject != null) { int pos = messages.indexOf(unreadMessageObject); if (pos >= 0) { fixPaddingsInLayout = true; if (fragmentView != null) { fragmentView.requestLayout(); } } } else { if (checkPaddingsRunnable != null) { return; } AndroidUtilities.runOnUIThread(checkPaddingsRunnable = () -> { checkPaddingsRunnable = null; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); }); } } private void checkRaiseSensors() { if (chatActivityEnterView != null && chatActivityEnterView.isStickersExpanded()) { MediaController.getInstance().setAllowStartRecord(false); } else if (currentChat != null && !ChatObject.canSendMedia(currentChat)) { MediaController.getInstance().setAllowStartRecord(false); } else if (!ApplicationLoader.mainInterfacePaused && (bottomOverlayChat == null || bottomOverlayChat.getVisibility() != View.VISIBLE) && (bottomOverlay == null || bottomOverlay.getVisibility() != View.VISIBLE) && (searchContainer == null || searchContainer.getVisibility() != View.VISIBLE)) { MediaController.getInstance().setAllowStartRecord(true); } else { MediaController.getInstance().setAllowStartRecord(false); } } @Override public void dismissCurrentDialog() { if (chatAttachAlert != null && visibleDialog == chatAttachAlert) { chatAttachAlert.getPhotoLayout().closeCamera(false); chatAttachAlert.dismissInternal(); chatAttachAlert.getPhotoLayout().hideCamera(true); return; } super.dismissCurrentDialog(); } @Override protected void setInPreviewMode(boolean value) { super.setInPreviewMode(value); if (currentUser != null && audioCallIconItem != null) { TLRPC.UserFull userFull = getMessagesController().getUserFull(currentUser.id); if (userFull != null && userFull.phone_calls_available) { showAudioCallAsIcon = !inPreviewMode; audioCallIconItem.setVisibility(View.VISIBLE); } else { showAudioCallAsIcon = false; audioCallIconItem.setVisibility(View.GONE); } } if (avatarContainer != null) { avatarContainer.setOccupyStatusBar(!value); avatarContainer.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !value ? 56 : (chatMode == MODE_PINNED ? 10 : 0), 0, 40, 0)); } if (chatActivityEnterView != null) { chatActivityEnterView.setVisibility(!value ? View.VISIBLE : View.INVISIBLE); } if (actionBar != null) { actionBar.setBackButtonDrawable(!value ? new BackDrawable(false) : null); if (headerItem != null) { headerItem.setAlpha(!value ? 1.0f : 0.0f); } if (attachItem != null) { attachItem.setAlpha(!value ? 1.0f : 0.0f); } } if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); MessageObject message = null; if (view instanceof ChatMessageCell) { message = ((ChatMessageCell) view).getMessageObject(); } else if (view instanceof ChatActionCell) { message = ((ChatActionCell) view).getMessageObject(); } if (message != null && message.messageOwner != null && message.messageOwner.media_unread && message.messageOwner.mentioned) { if (!message.isVoice() && !message.isRoundVideo()) { newMentionsCount--; if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } getMessagesController().markMentionMessageAsRead(message.getId(), ChatObject.isChannel(currentChat) ? currentChat.id : 0, dialog_id); message.setContentIsRead(); } if (view instanceof ChatMessageCell) { ((ChatMessageCell) view).setHighlighted(false); ((ChatMessageCell) view).setHighlightedAnimated(); } } } chatListView.setItemAnimator(null); } updateBottomOverlay(); updateSecretStatus(); if (fragmentContextView != null) { fragmentContextView.setEnabled(!value); } if (fragmentLocationContextView != null) { fragmentLocationContextView.setEnabled(!value); } if (pinnedMessageView != null) { pinnedMessageView.setEnabled(!isInPreviewMode()); } } Bulletin.Delegate bulletinDelegate; @Override public void onResume() { super.onResume(); checkShowBlur(false); activityResumeTime = System.currentTimeMillis(); if (openImport && getSendMessagesHelper().getImportingHistory(dialog_id) != null) { ImportingAlert alert = new ImportingAlert(getParentActivity(), null, this, themeDelegate); alert.setOnHideListener(dialog -> { if (fragmentContextView != null) { fragmentContextView.checkImport(false); } }); showDialog(alert); openImport = false; } checkAdjustResize(); MediaController.getInstance().startRaiseToEarSensors(this); checkRaiseSensors(); if (chatAttachAlert != null) { chatAttachAlert.onResume(); } if (contentView != null) { contentView.onResume(); } checkChecksHint(); Bulletin.addDelegate(this, bulletinDelegate = new Bulletin.Delegate() { @Override public int getBottomOffset(int tag) { if (tag == 1) { return 0; } int height; if (chatActivityEnterView != null && chatActivityEnterView.getVisibility() == View.VISIBLE) { if (contentView.getKeyboardHeight() < AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing() || chatActivityEnterView.panelAnimationInProgress()) { height = chatActivityEnterView.getHeight() + chatActivityEnterView.getEmojiPadding(); } else { height = chatActivityEnterView.getHeight(); } } else { height = AndroidUtilities.dp(51); } if (chatActivityEnterView.panelAnimationInProgress()) { float translationY = bottomPanelTranslationY - chatActivityEnterView.getEmojiPadding(); height += translationY; } height += contentPanTranslation; return height - AndroidUtilities.dp(1.5f); } }); checkActionBarMenu(false); if (replyImageLocation != null && replyImageView != null) { replyImageView.setImage(ImageLocation.getForObject(replyImageLocation, replyImageLocationObject), "50_50", ImageLocation.getForObject(replyImageThumbLocation, replyImageLocationObject), "50_50_b", null, replyImageSize, replyImageCacheType, replyingMessageObject); } if (pinnedImageLocation != null && pinnedMessageImageView != null) { MessageObject pinnedMessageObject = pinnedMessageObjects.get(currentPinnedMessageId); pinnedMessageImageView[0].setImage(ImageLocation.getForObject(pinnedImageLocation, pinnedImageLocationObject), "50_50", ImageLocation.getForObject(pinnedImageThumbLocation, pinnedImageLocationObject), "50_50_b", null, pinnedImageSize, pinnedImageCacheType, pinnedMessageObject); } if (chatMode == 0) { getNotificationsController().setOpenedDialogId(dialog_id); } getMessagesController().setLastVisibleDialogId(dialog_id, chatMode == MODE_SCHEDULED, true); if (scrollToTopOnResume) { if (scrollToTopUnReadOnResume && scrollToMessage != null) { if (chatListView != null) { int yOffset; boolean bottom = true; if (scrollToMessagePosition == -9000) { yOffset = getScrollOffsetForMessage(scrollToMessage); bottom = false; } else if (scrollToMessagePosition == -10000) { yOffset = -AndroidUtilities.dp(11); bottom = false; } else { yOffset = scrollToMessagePosition; } chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messages.indexOf(scrollToMessage), yOffset, bottom); } } else { moveScrollToLastMessage(false); } scrollToTopUnReadOnResume = false; scrollToTopOnResume = false; scrollToMessage = null; } paused = false; pausedOnLastMessage = false; checkScrollForLoad(false); if (wasPaused) { wasPaused = false; if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(false); } } fixLayout(); applyDraftMaybe(false); if (bottomOverlayChat != null && bottomOverlayChat.getVisibility() != View.VISIBLE && !actionBar.isSearchFieldVisible()) { chatActivityEnterView.setFieldFocused(true); } if (chatActivityEnterView != null) { chatActivityEnterView.onResume(); } if (currentUser != null) { chatEnterTime = System.currentTimeMillis(); chatLeaveTime = 0; } if (startVideoEdit != null) { AndroidUtilities.runOnUIThread(() -> { openVideoEditor(startVideoEdit, null); startVideoEdit = null; }); } if (chatListView != null && (chatActivityEnterView == null || !chatActivityEnterView.isEditingMessage())) { chatListView.setOnItemLongClickListener(onItemLongClickListener); chatListView.setOnItemClickListener(onItemClickListener); chatListView.setLongClickable(true); } checkBotCommands(); updateTitle(); showGigagroupConvertAlert(); if (pullingDownOffset != 0) { pullingDownOffset = 0; chatListView.invalidate(); } } public void checkAdjustResize() { if (reportType >= 0) { AndroidUtilities.requestAdjustNothing(getParentActivity(), classGuid); } else { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } @Override public void finishFragment() { super.finishFragment(); if (scrimPopupWindow != null) { scrimPopupWindow.setPauseNotifications(false); closeMenu(); } } @Override public void onPause() { super.onPause(); if (scrimPopupWindow != null) { scrimPopupWindow.setPauseNotifications(false); closeMenu(); } int replyId = threadMessageId; getMessagesController().markDialogAsReadNow(dialog_id, replyId); MediaController.getInstance().stopRaiseToEarSensors(this, true); paused = true; wasPaused = true; if (chatMode == 0) { getNotificationsController().setOpenedDialogId(0); } Bulletin.removeDelegate(this); getMessagesController().setLastVisibleDialogId(dialog_id, chatMode == MODE_SCHEDULED, false); CharSequence draftMessage = null; MessageObject replyMessage = null; boolean searchWebpage = true; if (!ignoreAttachOnPause && chatActivityEnterView != null && bottomOverlayChat != null && bottomOverlayChat.getVisibility() != View.VISIBLE) { chatActivityEnterView.onPause(); replyMessage = replyingMessageObject; draftMessage = AndroidUtilities.getTrimmedString(chatActivityEnterView.getDraftMessage()); searchWebpage = chatActivityEnterView.isMessageWebPageSearchEnabled(); chatActivityEnterView.setFieldFocused(false); } if (chatAttachAlert != null) { if (!ignoreAttachOnPause) { chatAttachAlert.onPause(); } else { ignoreAttachOnPause = false; } } if (contentView != null) { contentView.onPause(); } if (chatMode == 0) { CharSequence[] message = new CharSequence[]{draftMessage}; ArrayList entities = getMediaDataController().getEntities(message, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101); getMediaDataController().saveDraft(dialog_id, threadMessageId, message[0], entities, replyMessage != null ? replyMessage.messageOwner : null, !searchWebpage); getMessagesController().cancelTyping(0, dialog_id, threadMessageId); if (!pausedOnLastMessage && !firstLoading) { SharedPreferences.Editor editor = MessagesController.getNotificationsSettings(currentAccount).edit(); int messageId = 0; int offset = 0; if (chatLayoutManager != null) { boolean sponsoredMessageFound = false; for (int i = 0; i < chatListView.getChildCount(); i++) { if (chatListView.getChildAt(i) instanceof ChatMessageCell && ((ChatMessageCell) chatListView.getChildAt(i)).getMessageObject().isSponsored()) { sponsoredMessageFound = true; break; } } int position = chatLayoutManager.findFirstVisibleItemPosition(); if (position != 0 && !sponsoredMessageFound) { RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(position); if (holder != null) { int mid = 0; if (holder.itemView instanceof ChatMessageCell) { mid = ((ChatMessageCell) holder.itemView).getMessageObject().getId(); } else if (holder.itemView instanceof ChatActionCell) { mid = ((ChatActionCell) holder.itemView).getMessageObject().getId(); } if (mid == 0) { holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(position + 1); } boolean ignore = false; int count = 0; for (int a = position - 1; a >= chatAdapter.messagesStartRow; a--) { int num = a - chatAdapter.messagesStartRow; if (num < 0 || num >= messages.size()) { continue; } MessageObject messageObject = messages.get(num); if (messageObject.getId() == 0) { continue; } if ((!messageObject.isOut() || messageObject.messageOwner.from_scheduled) && messageObject.isUnread()) { ignore = true; messageId = 0; } if (count > 2) { break; } count++; } if (holder != null && !ignore) { if (holder.itemView instanceof ChatMessageCell) { messageId = ((ChatMessageCell) holder.itemView).getMessageObject().getId(); } else if (holder.itemView instanceof ChatActionCell) { messageId = ((ChatActionCell) holder.itemView).getMessageObject().getId(); } if (messageId > 0 && currentEncryptedChat == null || messageId < 0 && currentEncryptedChat != null) { offset = holder.itemView.getBottom() - chatListView.getMeasuredHeight(); if (BuildVars.LOGS_ENABLED) { FileLog.d("save offset = " + offset + " for mid " + messageId); } } else { messageId = 0; } } } } } if (messageId != 0) { editor.putInt("diditem" + dialog_id, messageId); editor.putInt("diditemo" + dialog_id, offset); } else { pausedOnLastMessage = true; editor.remove("diditem" + dialog_id); editor.remove("diditemo" + dialog_id); } editor.commit(); } if (currentUser != null) { chatLeaveTime = System.currentTimeMillis(); updateInformationForScreenshotDetector(); } hideUndoViews(); } if (chatListItemAnimator != null) { chatListItemAnimator.endAnimations(); } if (chatScrollHelper != null) { chatScrollHelper.cancel(); } if (AvatarPreviewer.hasVisibleInstance()) { AvatarPreviewer.getInstance().close(); } } private void applyDraftMaybe(boolean canClear) { if (chatActivityEnterView == null || chatMode != 0) { return; } TLRPC.DraftMessage draftMessage = getMediaDataController().getDraft(dialog_id, threadMessageId); TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, threadMessageId) : null; if (chatActivityEnterView.getFieldText() == null) { if (draftMessage != null) { chatActivityEnterView.setWebPage(null, !draftMessage.no_webpage); CharSequence message; if (!draftMessage.entities.isEmpty()) { SpannableStringBuilder stringBuilder = SpannableStringBuilder.valueOf(draftMessage.message); MediaDataController.sortEntities(draftMessage.entities); for (int a = 0; a < draftMessage.entities.size(); a++) { TLRPC.MessageEntity entity = draftMessage.entities.get(a); if (entity instanceof TLRPC.TL_inputMessageEntityMentionName || entity instanceof TLRPC.TL_messageEntityMentionName) { long user_id; if (entity instanceof TLRPC.TL_inputMessageEntityMentionName) { user_id = ((TLRPC.TL_inputMessageEntityMentionName) entity).user_id.user_id; } else { user_id = ((TLRPC.TL_messageEntityMentionName) entity).user_id; } if (entity.offset + entity.length < stringBuilder.length() && stringBuilder.charAt(entity.offset + entity.length) == ' ') { entity.length++; } stringBuilder.setSpan(new URLSpanUserMention("" + user_id, 3), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (entity instanceof TLRPC.TL_messageEntityCode || entity instanceof TLRPC.TL_messageEntityPre) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_MONO; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); } else if (entity instanceof TLRPC.TL_messageEntityBold) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_BOLD; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); } else if (entity instanceof TLRPC.TL_messageEntityItalic) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_ITALIC; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); } else if (entity instanceof TLRPC.TL_messageEntityStrike) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); } else if (entity instanceof TLRPC.TL_messageEntityUnderline) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); } else if (entity instanceof TLRPC.TL_messageEntityTextUrl) { stringBuilder.setSpan(new URLSpanReplacement(entity.url), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (entity instanceof TLRPC.TL_messageEntitySpoiler) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_SPOILER; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); } else if (entity instanceof TLRPC.TL_messageEntityCustomEmoji) { Paint.FontMetricsInt fontMetrics = null; try { fontMetrics = chatActivityEnterView.getEditField().getPaint().getFontMetricsInt(); } catch (Exception e) { FileLog.e(e); } TLRPC.TL_messageEntityCustomEmoji e = (TLRPC.TL_messageEntityCustomEmoji) entity; AnimatedEmojiSpan span; if (e.document != null) { span = new AnimatedEmojiSpan(e.document, fontMetrics); } else { span = new AnimatedEmojiSpan(e.document_id, fontMetrics); } stringBuilder.setSpan(span, entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } message = stringBuilder; } else { message = draftMessage.message; } chatActivityEnterView.setFieldText(message); if (getArguments().getBoolean("hasUrl", false)) { chatActivityEnterView.setSelection(draftMessage.message.indexOf('\n') + 1); AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null) { chatActivityEnterView.setFieldFocused(true); chatActivityEnterView.openKeyboard(); } }, 700); } } } else if (canClear && draftMessage == null) { chatActivityEnterView.setFieldText(""); hideFieldPanel(true); } if (replyingMessageObject == null && draftReplyMessage != null) { replyingMessageObject = new MessageObject(currentAccount, draftReplyMessage, getMessagesController().getUsers(), false, false); showFieldPanelForReply(replyingMessageObject); } } private void updateInformationForScreenshotDetector() { if (currentUser == null) { return; } ArrayList visibleMessages; int messageId = 0; if (currentEncryptedChat != null) { visibleMessages = new ArrayList<>(); if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); MessageObject object = null; if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; object = cell.getMessageObject(); } if (object != null && object.getId() < 0 && object.messageOwner.random_id != 0) { visibleMessages.add(object.messageOwner.random_id); } } } MediaController.getInstance().setLastVisibleMessageIds(currentAccount, chatEnterTime, chatLeaveTime, currentUser, currentEncryptedChat, visibleMessages, messageId); } else { SecretMediaViewer viewer = SecretMediaViewer.getInstance(); MessageObject messageObject = viewer.getCurrentMessageObject(); if (messageObject != null && !messageObject.isOut()) { MediaController.getInstance().setLastVisibleMessageIds(currentAccount, viewer.getOpenTime(), viewer.getCloseTime(), currentUser, null, null, messageObject.getId()); } } } private boolean fixLayoutInternal() { if (!AndroidUtilities.isTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { selectedMessagesCountTextView.setTextSize(18); } else { selectedMessagesCountTextView.setTextSize(20); } HashMap newGroups = null; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (child instanceof ChatMessageCell) { MessageObject.GroupedMessages groupedMessages = ((ChatMessageCell) child).getCurrentMessagesGroup(); if (groupedMessages != null && groupedMessages.hasSibling && !groupedMessages.messages.isEmpty()) { if (newGroups == null) { newGroups = new HashMap<>(); } if (!newGroups.containsKey(groupedMessages.groupId)) { newGroups.put(groupedMessages.groupId, groupedMessages); MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int idx = messages.indexOf(messageObject); if (idx >= 0) { chatAdapter.notifyItemRangeChanged(idx + chatAdapter.messagesStartRow, groupedMessages.messages.size()); chatListView.setItemAnimator(null); } } } } } if (AndroidUtilities.isTablet()) { if (AndroidUtilities.isSmallTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { actionBar.setBackButtonDrawable(new BackDrawable(false)); } else { actionBar.setBackButtonDrawable(new BackDrawable(parentLayout == null || parentLayout.fragmentsStack.isEmpty() || parentLayout.fragmentsStack.get(0) == ChatActivity.this || parentLayout.fragmentsStack.size() == 1)); } return false; } return true; } private void fixLayout() { if (avatarContainer != null) { avatarContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (avatarContainer != null) { avatarContainer.getViewTreeObserver().removeOnPreDrawListener(this); } return fixLayoutInternal(); } }); } } public boolean maybePlayVisibleVideo() { if (chatListView == null) { return false; } MessageObject playingMessage = MediaController.getInstance().getPlayingMessageObject(); if (playingMessage != null && !playingMessage.isVideo()) { return false; } MessageObject visibleMessage = null; AnimatedFileDrawable visibleAnimation = null; if (noSoundHintView != null && noSoundHintView.getTag() != null) { ChatMessageCell cell = noSoundHintView.getMessageCell(); if (cell != null) { ImageReceiver imageReceiver = cell.getPhotoImage(); visibleAnimation = imageReceiver.getAnimation(); if (visibleAnimation != null) { visibleMessage = cell.getMessageObject(); scrollToVideo = cell.getTop() + imageReceiver.getImageY2() > chatListView.getMeasuredHeight(); } } } if (visibleMessage == null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (!(child instanceof ChatMessageCell)) { continue; } ChatMessageCell messageCell = (ChatMessageCell) child; MessageObject messageObject = messageCell.getMessageObject(); boolean isRoundVideo = messageObject.isRoundVideo(); if ((!messageObject.isVideo() && !isRoundVideo) || messageObject.videoEditedInfo != null) { continue; } ImageReceiver imageReceiver = messageCell.getPhotoImage(); AnimatedFileDrawable animation = imageReceiver.getAnimation(); if (animation == null) { continue; } float top = child.getTop() + imageReceiver.getImageY(); float bottom = top + imageReceiver.getImageHeight(); if (bottom < 0 || top > chatListView.getMeasuredHeight()) { continue; } if (visibleMessage != null && top < 0) { break; } visibleMessage = messageObject; visibleAnimation = animation; scrollToVideo = top < 0 || bottom > chatListView.getMeasuredHeight(); if (top >= 0 && bottom <= chatListView.getMeasuredHeight()) { break; } } } if (visibleMessage != null) { if (MediaController.getInstance().isPlayingMessage(visibleMessage)) { return false; } hideHints(true); if (visibleMessage.isRoundVideo()) { boolean result = MediaController.getInstance().playMessage(visibleMessage); MediaController.getInstance().setVoiceMessagesPlaylist(result ? createVoiceMessagesPlaylist(visibleMessage, false) : null, false); return result; } else { SharedConfig.setNoSoundHintShowed(true); visibleMessage.audioProgress = visibleAnimation.getCurrentProgress(); visibleMessage.audioProgressMs = visibleAnimation.getCurrentProgressMs(); visibleAnimation.stop(); if (PhotoViewer.isPlayingMessageInPip(visibleMessage)) { PhotoViewer.getPipInstance().destroyPhotoViewer(); } return MediaController.getInstance().playMessage(visibleMessage); } } return false; } @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { fixLayout(); if (visibleDialog instanceof DatePickerDialog) { visibleDialog.dismiss(); } closeMenu(); if (!AndroidUtilities.isTablet()) { if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { return; } MessageObject message = MediaController.getInstance().getPlayingMessageObject(); if (message != null && message.isVideo()) { PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); getFileLoader().setLoadingVideoForPlayer(message.getDocument(), false); MediaController.getInstance().cleanupPlayer(true, true, false, true); if (PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider, false)) { PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); } hideHints(false); MediaController.getInstance().resetGoingToShowMessageObject(); } } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isOpenedFullScreenVideo()) { PhotoViewer.getInstance().injectVideoPlayerToMediaController(); PhotoViewer.getInstance().closePhoto(false, true); } } } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages selectedGroup) { createDeleteMessagesAlert(finalSelectedObject, selectedGroup, 1); } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant) { createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, loadParticipant, false); } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant, boolean hideDimAfter) { if (finalSelectedObject == null && (selectedMessagesIds[0].size() + selectedMessagesIds[1].size()) == 0) { return; } AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, chatMode == MODE_SCHEDULED, loadParticipant, () -> { hideActionMode(); updatePinnedMessageView(true); }, hideDimAfter ? () -> dimBehindView(false) : null, themeDelegate); } private void hideActionMode() { if (actionBar != null) { if (!actionBar.isActionModeShowed()) { return; } actionBar.hideActionMode(); } cantDeleteMessagesCount = 0; canEditMessagesCount = 0; cantForwardMessagesCount = 0; canSaveMusicCount = 0; canSaveDocumentsCount = 0; cantSaveMessagesCount = 0; if (chatActivityEnterView != null) { EditTextCaption editTextCaption = chatActivityEnterView.getEditField(); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { editTextCaption.requestFocus(); } editTextCaption.setAllowDrawCursor(true); } if (textSelectionHelper != null) { textSelectionHelper.clear(true); textSelectionHelper.cancelAllAnimators(); } if (textSelectionHint != null) { textSelectionHint.hide(); } if (chatActivityEnterView != null) { chatActivityEnterView.preventInput = false; } textSelectionHintWasShowed = false; } private boolean createMenu(View v, boolean single, boolean listView, float x, float y) { return createMenu(v, single, listView, x, y, true); } private CharSequence getMessageCaption(MessageObject messageObject, MessageObject.GroupedMessages group) { String restrictionReason = MessagesController.getRestrictionReason(messageObject.messageOwner.restriction_reason); if (!TextUtils.isEmpty(restrictionReason)) { return restrictionReason; } if (messageObject.isVoiceTranscriptionOpen() && !TranscribeButton.isTranscribing(messageObject)) { return messageObject.getVoiceTranscription(); } if (messageObject.caption != null) { return messageObject.caption; } if (group == null) { return null; } CharSequence caption = null; for (int a = 0, N = group.messages.size(); a < N; a++) { MessageObject message = group.messages.get(a); if (message.caption != null) { if (caption != null) { return null; } caption = message.caption; } } return caption; } @SuppressLint("ClickableViewAccessibility") private boolean createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup) { if (actionBar.isActionModeShowed() || reportType >= 0) { return false; } MessageObject message; MessageObject primaryMessage; if (v instanceof ChatMessageCell) { message = ((ChatMessageCell) v).getMessageObject(); primaryMessage = ((ChatMessageCell) v).getPrimaryMessageObject(); } else if (v instanceof ChatActionCell) { message = ((ChatActionCell) v).getMessageObject(); primaryMessage = message; } else { primaryMessage = null; message = null; } if (message == null) { return false; } if (!single && message.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { return false; } final int type = getMessageType(message); if (single) { if (message.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { if (message.getReplyMsgId() != 0) { scrollToMessageId(message.getReplyMsgId(), message.messageOwner.id, true, message.getDialogId() == mergeDialogId ? 1 : 0, false, 0); } else { Toast.makeText(getParentActivity(), LocaleController.getString("MessageNotFound", R.string.MessageNotFound), Toast.LENGTH_SHORT).show(); } return true; } else if (message.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent && message.replyMessageObject != null && message.replyMessageObject.isInvoice()) { TLRPC.TL_payments_getPaymentReceipt req = new TLRPC.TL_payments_getPaymentReceipt(); req.msg_id = message.getId(); req.peer = getMessagesController().getInputPeer(message.messageOwner.peer_id); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_payments_paymentReceipt) { presentFragment(new PaymentFormActivity((TLRPC.TL_payments_paymentReceipt) response)); } }), ConnectionsManager.RequestFlagFailOnServerErrors); return true; } else if (message.messageOwner.action instanceof TLRPC.TL_messageActionGroupCall || message.messageOwner.action instanceof TLRPC.TL_messageActionInviteToGroupCall || message.messageOwner.action instanceof TLRPC.TL_messageActionGroupCallScheduled) { if (getParentActivity() == null) { return false; } VoIPService sharedInstance = VoIPService.getSharedInstance(); if (sharedInstance != null) { if (sharedInstance.groupCall != null && message.messageOwner.action.call.id == sharedInstance.groupCall.call.id) { if (getParentActivity() instanceof LaunchActivity) { GroupCallActivity.create((LaunchActivity) getParentActivity(), AccountInstance.getInstance(currentAccount), null, null, false, null); } else { Intent intent = new Intent(getParentActivity(), LaunchActivity.class).setAction("voip_chat"); intent.putExtra("currentAccount", VoIPService.getSharedInstance().getAccount()); getParentActivity().startActivity(intent); } } else { createGroupCall = getGroupCall() == null; VoIPHelper.startCall(currentChat, null, null, createGroupCall, getParentActivity(), ChatActivity.this, getAccountInstance()); } return true; } else if (fragmentContextView != null && getGroupCall() != null) { if (VoIPService.getSharedInstance() != null) { GroupCallActivity.create((LaunchActivity) getParentActivity(), AccountInstance.getInstance(VoIPService.getSharedInstance().getAccount()), null, null, false, null); } else { ChatObject.Call call = getGroupCall(); if (call == null) { return false; } VoIPHelper.startCall(getMessagesController().getChat(call.chatId), null, null, false, getParentActivity(), ChatActivity.this, getAccountInstance()); } return true; } else if (ChatObject.canManageCalls(currentChat)) { VoIPHelper.showGroupCallAlert(ChatActivity.this, currentChat, null, true, getAccountInstance()); return true; } } else if (message.messageOwner.action instanceof TLRPC.TL_messageActionSetChatTheme) { showChatThemeBottomSheet(); return true; } } if (message.isSponsored() || threadMessageObjects != null && threadMessageObjects.contains(message)) { single = true; } selectedObject = null; selectedObjectGroup = null; forwardingMessage = null; forwardingMessageGroup = null; selectedObjectToEditCaption = null; for (int a = 1; a >= 0; a--) { selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); selectedMessagesIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); MessageObject.GroupedMessages groupedMessages; if (searchGroup) { groupedMessages = getValidGroupedMessage(message); } else { groupedMessages = null; } boolean allowChatActions = true; boolean allowPin; if (chatMode == MODE_SCHEDULED || isThreadChat()) { allowPin = false; } else if (currentChat != null) { allowPin = message.getDialogId() != mergeDialogId && ChatObject.canPinMessages(currentChat); } else if (currentEncryptedChat == null) { if (UserObject.isDeleted(currentUser)) { allowPin = false; } else if (userInfo != null) { allowPin = userInfo.can_pin_message; } else { allowPin = false; } } else { allowPin = false; } allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty); boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards; boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())); boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId; if (allowEdit && groupedMessages != null) { int captionsCount = 0; for (int a = 0, N = groupedMessages.messages.size(); a < N; a++) { MessageObject messageObject = groupedMessages.messages.get(a); if (a == 0 || !TextUtils.isEmpty(messageObject.caption)) { selectedObjectToEditCaption = messageObject; if (!TextUtils.isEmpty(messageObject.caption)) { captionsCount++; } } } allowEdit = captionsCount < 2; } if (chatMode == MODE_SCHEDULED || threadMessageObjects != null && threadMessageObjects.contains(message) || message.isSponsored() || type == 1 && message.getDialogId() == mergeDialogId || message.messageOwner.action instanceof TLRPC.TL_messageActionSecureValuesSent || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { allowChatActions = false; } if (single || type < 2 || type == 20) { if (getParentActivity() == null) { return false; } ArrayList icons = new ArrayList<>(); ArrayList items = new ArrayList<>(); final ArrayList options = new ArrayList<>(); View optionsView = null; CharSequence messageTextToTranslate = null; if (message.messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL && single && (dialog_id >= 0 || (currentChat != null && ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_DELETE_MESSAGES)))) { AutoDeletePopupWrapper autoDeletePopupWrapper = new AutoDeletePopupWrapper(contentView.getContext(), null, new AutoDeletePopupWrapper.Callback() { @Override public void dismiss() { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } } @Override public void setAutoDeleteHistory(int time, int action) { getMessagesController().setDialogHistoryTTL(dialog_id, time); if (userInfo != null || chatInfo != null) { undoView.showWithAction(dialog_id, action, currentUser, userInfo != null ? userInfo.ttl_period : chatInfo.ttl_period, null, null); } } }, true, getResourceProvider()); autoDeletePopupWrapper.updateItems(userInfo != null ? userInfo.ttl_period : chatInfo.ttl_period); optionsView = autoDeletePopupWrapper.windowLayout; } else if (type >= 0 || type == -1 && single && (message.isSending() || message.isEditing()) && currentEncryptedChat == null) { selectedObject = message; selectedObjectGroup = groupedMessages; messageTextToTranslate = getMessageCaption(selectedObject, selectedObjectGroup); if (messageTextToTranslate == null && selectedObject.isPoll()) { try { TLRPC.Poll poll = ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll; StringBuilder pollText = new StringBuilder(); pollText = new StringBuilder(poll.question).append("\n"); for (TLRPC.TL_pollAnswer answer : poll.answers) pollText.append("\n\uD83D\uDD18 ").append(answer.text); messageTextToTranslate = pollText.toString(); } catch (Exception e) {} } if (messageTextToTranslate == null) { messageTextToTranslate = getMessageContent(selectedObject, 0, false); } if (messageTextToTranslate != null && Emoji.fullyConsistsOfEmojis(messageTextToTranslate)) { messageTextToTranslate = null; // message fully consists of emojis, do not translate } if (message.isSponsored() && !getMessagesController().premiumLocked) { items.add(LocaleController.getString("HideAd", R.string.HideAd)); options.add(OPTION_HIDE_SPONSORED_MESSAGE); icons.add(R.drawable.msg_block2); } if (type == -1) { if ((selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || selectedObject.isAnimatedEmojiStickers() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwards) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString("CancelSending", R.string.CancelSending)); options.add(OPTION_CANCEL_SENDING); icons.add(R.drawable.msg_delete); } else if (type == 0) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(OPTION_RETRY); icons.add(R.drawable.msg_retry); items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } else if (type == 1) { if (currentChat != null) { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.msg_reply); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && message.hasReplies() && currentChat.megagroup && message.canViewThread()) { items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.msg_viewreplies); } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(OPTION_UNPIN); icons.add(R.drawable.msg_unpin); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); options.add(OPTION_PIN); icons.add(R.drawable.msg_pin); } if (selectedObject != null && selectedObject.contentType == 0 && (messageTextToTranslate != null && messageTextToTranslate.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { items.add(LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); options.add(OPTION_TRANSLATE); icons.add(R.drawable.msg_translate); } if (message.canEditMessage(currentChat)) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(OPTION_EDIT); icons.add(R.drawable.msg_edit); } if (selectedObject.contentType == 0 && !selectedObject.isMediaEmptyWebpage() && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { items.add(LocaleController.getString("ReportChat", R.string.ReportChat)); options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.msg_report); } } else { if (selectedObject.getId() > 0 && allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.msg_reply); } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } } else if (type == 20) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(OPTION_RETRY); icons.add(R.drawable.msg_retry); if (!noforwards) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } else { if (currentEncryptedChat == null) { if (chatMode == MODE_SCHEDULED) { items.add(LocaleController.getString("MessageScheduleSend", R.string.MessageScheduleSend)); options.add(OPTION_SEND_NOW); icons.add(R.drawable.msg_send); } if (selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { TLRPC.TL_messageActionPhoneCall call = (TLRPC.TL_messageActionPhoneCall) message.messageOwner.action; items.add((call.reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || call.reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy) && !message.isOutOwner() ? LocaleController.getString("CallBack", R.string.CallBack) : LocaleController.getString("CallAgain", R.string.CallAgain)); options.add(OPTION_CALL_AGAIN); icons.add(R.drawable.msg_callback); if (VoIPHelper.canRateCall(call)) { items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem)); options.add(OPTION_RATE_CALL); icons.add(R.drawable.msg_fave); } } if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.msg_reply); } if ((selectedObject.type == 0 || selectedObject.isDice() || selectedObject.isAnimatedEmoji() || selectedObject.isAnimatedEmojiStickers() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwards) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && (currentChat.has_link || message.hasReplies()) && currentChat.megagroup && message.canViewThread()) { if (message.hasReplies()) { items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); } else { items.add(LocaleController.getString("ViewThread", R.string.ViewThread)); } options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.msg_viewreplies); } if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && ChatObject.isChannel(currentChat) && selectedObject.getDialogId() != mergeDialogId) { items.add(LocaleController.getString("CopyLink", R.string.CopyLink)); options.add(OPTION_COPY_LINK); icons.add(R.drawable.msg_link); } if (type == 2) { if (chatMode != MODE_SCHEDULED) { if (selectedObject.type == MessageObject.TYPE_POLL && !message.isPollClosed()) { if (message.canUnvote()) { items.add(LocaleController.getString("Unvote", R.string.Unvote)); options.add(OPTION_UNVOTE); icons.add(R.drawable.msg_unvote); } if (!message.isForwarded() && ( message.isOut() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) || ChatObject.isChannel(currentChat) && !currentChat.megagroup && (currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.edit_messages))) { if (message.isQuiz()) { items.add(LocaleController.getString("StopQuiz", R.string.StopQuiz)); } else { items.add(LocaleController.getString("StopPoll", R.string.StopPoll)); } options.add(OPTION_STOP_POLL_OR_QUIZ); icons.add(R.drawable.msg_pollstop); } } else if (selectedObject.isMusic() && !noforwards) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); } else if (selectedObject.isDocument() && !noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); } } } else if (type == 3 && !noforwards) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(OPTION_ADD_TO_GIFS); icons.add(R.drawable.msg_gif); } } else if (type == 4) { if (!noforwards) { if (selectedObject.isVideo()) { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (selectedObject.getDocument() != null) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(OPTION_ADD_TO_GIFS); icons.add(R.drawable.msg_gif); } items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); } } } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_language); if (!noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_theme); if (!noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (type == 6 && !noforwards) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY2); icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (type == 7) { if (selectedObject.isMask()) { items.add(LocaleController.getString("AddToMasks", R.string.AddToMasks)); options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.msg_sticker); } else { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.msg_sticker); TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { if (getMediaDataController().canAddStickerToFavorites() && MessageObject.isStickerHasSet(document)) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); } } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(OPTION_DELETE_STICKER_FROM_FAVORITES); icons.add(R.drawable.msg_unfave); } } } else if (type == 8) { long uid = selectedObject.messageOwner.media.user_id; TLRPC.User user = null; if (uid != 0) { user = MessagesController.getInstance(currentAccount).getUser(uid); } if (user != null && user.id != getUserConfig().getClientUserId() && getContactsController().contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); options.add(OPTION_ADD_CONTACT); icons.add(R.drawable.msg_addcontact); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { if (!noforwards) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(OPTION_COPY_PHONE_NUMBER); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString("Call", R.string.Call)); options.add(OPTION_CALL); icons.add(R.drawable.msg_callback); } } else if (type == 9) { TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { if (MessageObject.isStickerHasSet(document)) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); } } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(OPTION_DELETE_STICKER_FROM_FAVORITES); icons.add(R.drawable.msg_unfave); } } if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16 && !noforwards && selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(OPTION_FORWARD); icons.add(R.drawable.msg_forward); } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(OPTION_UNPIN); icons.add(R.drawable.msg_unpin); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); options.add(OPTION_PIN); icons.add(R.drawable.msg_pin); } if (selectedObject != null && selectedObject.contentType == 0 && (messageTextToTranslate != null && messageTextToTranslate.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { items.add(LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); options.add(OPTION_TRANSLATE); icons.add(R.drawable.msg_translate); } if (allowEdit) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(OPTION_EDIT); icons.add(R.drawable.msg_edit); } if (chatMode == MODE_SCHEDULED && selectedObject.canEditMessageScheduleTime(currentChat)) { items.add(LocaleController.getString("MessageScheduleEditTime", R.string.MessageScheduleEditTime)); options.add(OPTION_EDIT_SCHEDULE_TIME); icons.add(R.drawable.msg_calendar2); } if (chatMode != MODE_SCHEDULED && selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { if (UserObject.isReplyUser(currentUser)) { items.add(LocaleController.getString("BlockContact", R.string.BlockContact)); options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.msg_block2); } else { items.add(LocaleController.getString("ReportChat", R.string.ReportChat)); options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.msg_report); } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } } else { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.msg_reply); } if ((selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || selectedObject.isAnimatedEmojiStickers() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwards) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && (currentChat.has_link || message.hasReplies()) && currentChat.megagroup && message.canViewThread()) { if (message.hasReplies()) { items.add(LocaleController.formatPluralString("ViewReplies", message.getRepliesCount())); } else { items.add(LocaleController.getString("ViewThread", R.string.ViewThread)); } options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.msg_viewreplies); } if (type == 4 && !noforwards) { if (selectedObject.isVideo()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_language); } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_theme); } else if (type == 7) { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.msg_sticker); } else if (type == 8) { long uid = selectedObject.messageOwner.media.user_id; TLRPC.User user = null; if (uid != 0) { user = MessagesController.getInstance(currentAccount).getUser(uid); } if (user != null && user.id != getUserConfig().getClientUserId() && getContactsController().contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); options.add(OPTION_ADD_CONTACT); icons.add(R.drawable.msg_addcontact); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { if (!noforwards) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(OPTION_COPY_PHONE_NUMBER); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString("Call", R.string.Call)); options.add(OPTION_CALL); icons.add(R.drawable.msg_callback); } } items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.msg_delete); } } } if (options.isEmpty() && optionsView == null) { return false; } if (scrimPopupWindow != null) { closeMenu(); menuDeleteItem = null; scrimPopupWindowItems = null; return false; } final AtomicBoolean waitForLangDetection = new AtomicBoolean(false); final AtomicReference onLangDetectionDone = new AtomicReference(null); Rect rect = new Rect(); List availableReacts = getMediaDataController().getEnabledReactionsList(); boolean isReactionsViewAvailable = !isSecretChat() && !isInScheduleMode() && currentUser == null && message.hasReactions() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && !availableReacts.isEmpty() && message.messageOwner.reactions.can_see_list; boolean isReactionsAvailable; if (message.isForwardedChannelPost()) { TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(-message.getFromChatId()); if (chatInfo == null) { isReactionsAvailable = true; } else { isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty()) && !availableReacts.isEmpty(); } } else { isReactionsAvailable = !isSecretChat() && !isInScheduleMode() && message.isReactionsAvailable() && (chatInfo != null && !chatInfo.available_reactions.isEmpty() || (chatInfo == null && !ChatObject.isChannel(currentChat)) || currentUser != null) && !availableReacts.isEmpty(); } boolean showMessageSeen = !isReactionsViewAvailable && !isInScheduleMode() && currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().chatReadMarkExpirePeriod) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count <= getMessagesController().chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell); int flags = 0; if (isReactionsViewAvailable || showMessageSeen) { flags |= ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_USE_SWIPEBACK; } ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, themeDelegate, flags); popupLayout.setMinimumWidth(AndroidUtilities.dp(200)); Rect backgroundPaddings = new Rect(); Drawable shadowDrawable = getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); shadowDrawable.getPadding(backgroundPaddings); popupLayout.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); MessageSeenView messageSeenView = null; boolean addGap = false; if (optionsView == null) { if (isReactionsViewAvailable) { ReactedHeaderView reactedView = new ReactedHeaderView(contentView.getContext(), currentAccount, message, dialog_id); int count = 0; if (message.messageOwner.reactions != null) { for (TLRPC.TL_reactionCount r : message.messageOwner.reactions.results) { count += r.count; } } boolean hasHeader = count > 10 && message.messageOwner.reactions.results.size() > 1; ReactedUsersListView.ContainerLinerLayout linearLayout = new ReactedUsersListView.ContainerLinerLayout(contentView.getContext()); linearLayout.hasHeader = hasHeader; linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setLayoutParams(new FrameLayout.LayoutParams(AndroidUtilities.dp(200), AndroidUtilities.dp(6 * 48 + (hasHeader ? 44 * 2 + 8 : 44)) + (!hasHeader ? 1 : 0))); ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); backCell.setItemHeight(44); backCell.setTextAndIcon(LocaleController.getString("Back", R.string.Back), R.drawable.msg_arrow_back); backCell.getTextView().setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(40), 0, LocaleController.isRTL ? AndroidUtilities.dp(40) : 0, 0); backCell.setOnClickListener(v1 -> popupLayout.getSwipeBack().closeForeground()); linearLayout.addView(backCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); int[] foregroundIndex = new int[1]; ReactedUsersListView reactedUsersListView = null; if (hasHeader) { List counters = message.messageOwner.reactions.results; LinearLayout tabsView = new LinearLayout(contentView.getContext()); tabsView.setOrientation(LinearLayout.HORIZONTAL); ViewPager pager = new ViewPager(contentView.getContext()); HorizontalScrollView tabsScrollView = new HorizontalScrollView(contentView.getContext()); AtomicBoolean suppressTabsScroll = new AtomicBoolean(); boolean showAllReactionsTab = counters.size() > 1; int size = counters.size() + (showAllReactionsTab ? 1 : 0); for (int i = 0; i < size; i++) { ReactionTabHolderView hv = new ReactionTabHolderView(contentView.getContext()); int index = i; if (showAllReactionsTab) { index--; } if (index < 0) { hv.setCounter(count); } else { hv.setCounter(currentAccount, counters.get(index)); } int finalI = i; hv.setOnClickListener(v1 -> { int from = pager.getCurrentItem(); if (finalI == from) return; ReactionTabHolderView fv = (ReactionTabHolderView) tabsView.getChildAt(from); suppressTabsScroll.set(true); pager.setCurrentItem(finalI, true); float fSX = tabsScrollView.getScrollX(), tSX = hv.getX() - (tabsScrollView.getWidth() - hv.getWidth()) / 2f; ValueAnimator a = ValueAnimator.ofFloat(0, 1).setDuration(150); a.setInterpolator(CubicBezierInterpolator.DEFAULT); a.addUpdateListener(animation -> { float f = (float) animation.getAnimatedValue(); tabsScrollView.setScrollX((int) (fSX + (tSX - fSX) * f)); fv.setOutlineProgress(1f - f); hv.setOutlineProgress(f); }); a.start(); }); tabsView.addView(hv, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL, i == 0 ? 6 : 0, 6, 6, 6)); } tabsScrollView.setHorizontalScrollBarEnabled(false); tabsScrollView.addView(tabsView); linearLayout.addView(tabsScrollView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44)); View divider = new FrameLayout(contentView.getContext()); divider.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuSeparator)); linearLayout.addView(divider, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) Theme.dividerPaint.getStrokeWidth())); int head = AndroidUtilities.dp(44 * 2) + 1; SparseArray cachedViews = new SparseArray<>(); SparseIntArray cachedHeights = new SparseIntArray(); for (int i = 0; i < counters.size() + 1; i++) { cachedHeights.put(i, head + AndroidUtilities.dp(ReactedUsersListView.ITEM_HEIGHT_DP * ReactedUsersListView.VISIBLE_ITEMS)); } int finalCount = count; pager.setAdapter(new PagerAdapter() { @Override public int getCount() { return size; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { View cached = cachedViews.get(position); if (cached != null) { container.addView(cached); return cached; } int index = position; if (showAllReactionsTab) { index--; } TLRPC.TL_reactionCount reactionCount = null; if (index >= 0) { reactionCount = counters.get(index); } ReactedUsersListView v = new ReactedUsersListView(container.getContext(), themeDelegate, currentAccount, message, reactionCount, true) .setSeenUsers(reactedView.getSeenUsers()) .setOnProfileSelectedListener((view, userId) -> { Bundle args = new Bundle(); args.putLong("user_id", userId); ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); }).setOnHeightChangedListener((view, newHeight) -> { cachedHeights.put(position, head + newHeight); if (pager.getCurrentItem() == position) popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], head + newHeight, true); }); if (index < 0) { v.setPredictiveCount(finalCount); reactedView.setSeenCallback(v::setSeenUsers); } container.addView(v); cachedViews.put(position, v); return v; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } }); pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (!suppressTabsScroll.get()) { float fX = -1, tX = -1; for (int i = 0; i < tabsView.getChildCount(); i++) { ReactionTabHolderView ch = (ReactionTabHolderView) tabsView.getChildAt(i); ch.setOutlineProgress(i == position ? 1f - positionOffset : i == (position + 1) % size ? positionOffset : 0); if (i == position) { fX = ch.getX() - (tabsScrollView.getWidth() - ch.getWidth()) / 2f; } if (i == position + 1) { tX = ch.getX() - (tabsScrollView.getWidth() - ch.getWidth()) / 2f; } } if (fX != -1 && tX != -1) { tabsScrollView.setScrollX((int) (fX + (tX - fX) * positionOffset)); } int fromHeight = cachedHeights.get(position, 0); int toHeight = cachedHeights.get(position + 1, 0); popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], (int) (fromHeight * (1f - positionOffset) + toHeight * positionOffset), false); } } @Override public void onPageSelected(int position) { int h = cachedHeights.get(position); popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], h, true); } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { suppressTabsScroll.set(false); } } }); linearLayout.addView(pager, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1f)); } else { View gap = new FrameLayout(contentView.getContext()); gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); linearLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); reactedUsersListView = new ReactedUsersListView(contentView.getContext(), themeDelegate, currentAccount, message, null, true) .setSeenUsers(reactedView.getSeenUsers()) .setOnProfileSelectedListener((view, userId) -> { Bundle args = new Bundle(); args.putLong("user_id", userId); ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); }).setOnHeightChangedListener((view, newHeight) -> popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], AndroidUtilities.dp(44 + 8) + newHeight, true)); reactedView.setSeenCallback(reactedUsersListView::setSeenUsers); linearLayout.addView(reactedUsersListView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1f)); } foregroundIndex[0] = popupLayout.addViewToSwipeBack(linearLayout); ReactedUsersListView finalReactedUsersListView = reactedUsersListView; reactedView.setOnClickListener(v1 -> { if (finalReactedUsersListView == null || finalReactedUsersListView.isLoaded) { popupLayout.getSwipeBack().openForeground(foregroundIndex[0]); } }); popupLayout.addView(reactedView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); addGap = true; } if (showMessageSeen) { messageSeenView = new MessageSeenView(contentView.getContext(), currentAccount, message, currentChat); FrameLayout messageSeenLayout = new FrameLayout(contentView.getContext()); messageSeenLayout.addView(messageSeenView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); MessageSeenView finalMessageSeenView = messageSeenView; ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); cell.setItemHeight(44); cell.setTextAndIcon(LocaleController.getString("Back", R.string.Back), R.drawable.msg_arrow_back); cell.getTextView().setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(40), 0, LocaleController.isRTL ? AndroidUtilities.dp(40) : 0, 0); FrameLayout backContainer = new FrameLayout(contentView.getContext()); LinearLayout linearLayout = new LinearLayout(contentView.getContext()); linearLayout.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); linearLayout.setOrientation(LinearLayout.VERTICAL); RecyclerListView listView2 = finalMessageSeenView.createListView(); backContainer.addView(cell); linearLayout.addView(backContainer); backContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { popupLayout.getSwipeBack().closeForeground(); } }); int[] foregroundIndex = new int[1]; messageSeenView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (scrimPopupWindow == null || finalMessageSeenView.users.isEmpty()) { return; } if (finalMessageSeenView.users.size() == 1) { TLRPC.User user = finalMessageSeenView.users.get(0); if (user == null) { return; } Bundle args = new Bundle(); args.putLong("user_id", user.id); ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); return; } int totalHeight = contentView.getHeightWithKeyboard(); int availableHeight = totalHeight - scrimPopupY - AndroidUtilities.dp(46 + 16) - (isReactionsAvailable ? AndroidUtilities.dp(52) : 0); if (SharedConfig.messageSeenHintCount > 0 && contentView.getKeyboardHeight() < AndroidUtilities.dp(20)) { availableHeight -= AndroidUtilities.dp(52); Bulletin bulletin = BulletinFactory.of(ChatActivity.this).createErrorBulletin(AndroidUtilities.replaceTags(LocaleController.getString("MessageSeenTooltipMessage", R.string.MessageSeenTooltipMessage))); bulletin.tag = 1; bulletin.setDuration(4000); bulletin.show(); SharedConfig.updateMessageSeenHintCount(SharedConfig.messageSeenHintCount - 1); } else if (contentView.getKeyboardHeight() > AndroidUtilities.dp(20)) { availableHeight -= contentView.getKeyboardHeight() / 3f; } listView2.requestLayout(); linearLayout.requestLayout(); listView2.getAdapter().notifyDataSetChanged(); popupLayout.getSwipeBack().openForeground(foregroundIndex[0]); } }); linearLayout.addView(listView2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); listView2.setOnItemClickListener((view1, position) -> { TLRPC.User user = finalMessageSeenView.users.get(position); if (user == null) { return; } Bundle args = new Bundle(); args.putLong("user_id", user.id); ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); }); foregroundIndex[0] = popupLayout.addViewToSwipeBack(linearLayout); popupLayout.addView(messageSeenLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44)); addGap = true; } boolean showRateTranscription = selectedObject != null && selectedObject.isVoice() && selectedObject.messageOwner != null && getUserConfig().isPremium() && !TextUtils.isEmpty(selectedObject.messageOwner.voiceTranscription) && selectedObject.messageOwner != null && !selectedObject.messageOwner.voiceTranscriptionRated && selectedObject.messageOwner.voiceTranscriptionId != 0 && selectedObject.messageOwner.voiceTranscriptionOpen; if (!showRateTranscription && message.probablyRingtone() && currentEncryptedChat == null) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); cell.setMinimumWidth(AndroidUtilities.dp(200)); cell.setTextAndIcon(LocaleController.getString("SaveForNotifications", R.string.SaveForNotifications), R.drawable.msg_tone_add); popupLayout.addView(cell); cell.setOnClickListener(v1 -> { if (getMediaDataController().saveToRingtones(message.getDocument())) { getUndoView().showWithAction(dialog_id, UndoView.ACTION_RINGTONE_ADDED, new Runnable() { boolean clicked; @Override public void run() { if (clicked) { return; } clicked = true; presentFragment(new NotificationsSettingsActivity()); } }); } closeMenu(true); }); addGap = true; } if (addGap) { View gap = new FrameLayout(contentView.getContext()); gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } if (popupLayout.getSwipeBack() != null) { popupLayout.getSwipeBack().setOnClickListener(e -> closeMenu()); } if (showRateTranscription) { final LinearLayout rateTranscriptionLayout = new LinearLayout(contentView.getContext()); rateTranscriptionLayout.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams rateTranscriptionLayoutParams = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 89); final FrameLayout rateTranscription = new FrameLayout(contentView.getContext()); final View gap = new FrameLayout(contentView.getContext()); gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); TextView textView = new TextView(contentView.getContext()); textView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); textView.setGravity(Gravity.CENTER_HORIZONTAL); textView.setText(LocaleController.getString("RateTranscription", R.string.RateTranscription)); rateTranscription.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 0, 12, 0, 0)); boolean[] ratePositively = new boolean[1]; boolean[] loading = new boolean[1]; Drawable drawable; ImageView rateUp = new ImageView(contentView.getContext()); rateUp.setBackground(Theme.createCircleSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, 0)); drawable = contentView.getContext().getResources().getDrawable(R.drawable.msg_rate_up).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); drawable = new CrossfadeDrawable(drawable, new CircularProgressDrawable(AndroidUtilities.dp(12f), AndroidUtilities.dp(1.5f), getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon))); rateUp.setImageDrawable(drawable); rateTranscription.addView(rateUp, LayoutHelper.createFrame(33, 33, Gravity.CENTER_HORIZONTAL | Gravity.TOP, -42, 39, 0, 0)); ImageView rateDown = new ImageView(contentView.getContext()); rateDown.setBackground(Theme.createCircleSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, 0)); drawable = contentView.getContext().getResources().getDrawable(R.drawable.msg_rate_down).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); drawable = new CrossfadeDrawable(drawable, new CircularProgressDrawable(AndroidUtilities.dp(12f), AndroidUtilities.dp(1.5f), getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon))); rateDown.setImageDrawable(drawable); rateTranscription.addView(rateDown, LayoutHelper.createFrame(33, 33, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 42, 39, 0, 0)); Runnable rate = () -> { if (loading[0]) { return; } loading[0] = true; long[] progressShown = new long[1]; progressShown[0] = -1; Runnable showProgress = () -> { progressShown[0] = SystemClock.elapsedRealtime(); CrossfadeDrawable ldrawable = ((CrossfadeDrawable) (ratePositively[0] ? rateUp : rateDown).getDrawable()); ValueAnimator lva = ValueAnimator.ofFloat(0f, 1f); lva.addUpdateListener(a -> { ldrawable.setProgress((float) a.getAnimatedValue()); }); lva.setDuration(150); lva.setInterpolator(CubicBezierInterpolator.DEFAULT); lva.start(); }; TLRPC.TL_messages_rateTranscribedAudio req = new TLRPC.TL_messages_rateTranscribedAudio(); req.msg_id = selectedObject.getId(); req.peer = getMessagesController().getInputPeer(selectedObject.messageOwner.peer_id); req.transcription_id = selectedObject.messageOwner.voiceTranscriptionId; req.good = ratePositively[0]; getConnectionsManager().sendRequest(req, (res, err) -> { AndroidUtilities.cancelRunOnUIThread(showProgress); selectedObject.messageOwner.voiceTranscriptionRated = true; getMessagesStorage().updateMessageVoiceTranscriptionOpen(selectedObject.getDialogId(), selectedObject.getId(), selectedObject.messageOwner); AndroidUtilities.runOnUIThread(() -> { closeMenu(); BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.chats_infotip, LocaleController.getString("TranscriptionReportSent", R.string.TranscriptionReportSent)).show(); }, progressShown[0] > 0 ? Math.max(0, 300 - (SystemClock.elapsedRealtime() - progressShown[0])) : 0); }); AndroidUtilities.runOnUIThread(showProgress, 150); }; rateUp.setOnClickListener(e -> { ratePositively[0] = true; rate.run(); }); rateDown.setOnClickListener(e -> { ratePositively[0] = false; rate.run(); }); rateTranscriptionLayout.addView(rateTranscription, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 81)); rateTranscriptionLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); popupLayout.addView(rateTranscriptionLayout, rateTranscriptionLayoutParams); } final boolean translateButtonEnabled = MessagesController.getGlobalMainSettings().getBoolean("translate_button", false); scrimPopupWindowItems = new ActionBarMenuSubItem[items.size() + (selectedObject.isSponsored() ? 1 : 0)]; for (int a = 0, N = items.size(); a < N; a++) { if (a == 0 && selectedObject.isSponsored()) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); cell.setTextAndIcon(LocaleController.getString("SponsoredMessageInfo", R.string.SponsoredMessageInfo), R.drawable.msg_info); cell.setItemHeight(56); cell.setTag(R.id.width_tag, 240); cell.setMultiline(); scrimPopupWindowItems[scrimPopupWindowItems.length - 1] = cell; popupLayout.addView(cell); cell.setOnClickListener(v1 -> { if (contentView == null || getParentActivity() == null) { return; } BottomSheet.Builder builder = new BottomSheet.Builder(contentView.getContext()); builder.setCustomView(new SponsoredMessageInfoView(getParentActivity(), themeDelegate)); builder.show(); }); View gap = new View(getParentActivity()); gap.setMinimumWidth(AndroidUtilities.dp(196)); gap.setTag(1000); gap.setTag(R.id.object_tag, 1); popupLayout.addView(gap); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) cell.getLayoutParams(); if (LocaleController.isRTL) { layoutParams.gravity = Gravity.RIGHT; } layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = AndroidUtilities.dp(6); gap.setLayoutParams(layoutParams); } ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1, themeDelegate); cell.setMinimumWidth(AndroidUtilities.dp(200)); cell.setTextAndIcon(items.get(a), icons.get(a)); Integer option = options.get(a); if (option == 1 && selectedObject.messageOwner.ttl_period != 0) { menuDeleteItem = cell; updateDeleteItemRunnable.run(); cell.setSubtextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText6)); } scrimPopupWindowItems[a] = cell; popupLayout.addView(cell); final int i = a; cell.setOnClickListener(v1 -> { if (selectedObject == null || i >= options.size()) { return; } processSelectedOption(options.get(i)); }); if (option == OPTION_TRANSLATE) { String toLang = LocaleController.getInstance().getCurrentLocale().getLanguage(); final CharSequence finalMessageText = messageTextToTranslate; TranslateAlert.OnLinkPress onLinkPress = (link) -> { didPressMessageUrl(link, false, selectedObject, v instanceof ChatMessageCell ? (ChatMessageCell) v : null); return true; }; TLRPC.InputPeer inputPeer = getMessagesController().getInputPeer(dialog_id); int messageId = selectedObject.messageOwner.id; if (LanguageDetector.hasSupport()) { final String[] fromLang = {null}; cell.setVisibility(View.GONE); waitForLangDetection.set(true); LanguageDetector.detectLanguage( finalMessageText.toString(), (String lang) -> { fromLang[0] = lang; if (fromLang[0] != null && (!fromLang[0].equals(toLang) || fromLang[0].equals("und")) && ( translateButtonEnabled && !RestrictedLanguagesSelectActivity.getRestrictedLanguages().contains(fromLang[0]) || (currentChat != null && (currentChat.has_link || currentChat.username != null)) && ("uk".equals(fromLang[0]) || "ru".equals(fromLang[0])) )) { cell.setVisibility(View.VISIBLE); } waitForLangDetection.set(false); if (onLangDetectionDone.get() != null) { onLangDetectionDone.get().run(); onLangDetectionDone.set(null); } }, (Exception e) -> { FileLog.e("mlkit: failed to detect language in message"); waitForLangDetection.set(false); if (onLangDetectionDone.get() != null) { onLangDetectionDone.get().run(); onLangDetectionDone.set(null); } } ); cell.setOnClickListener(e -> { if (selectedObject == null || i >= options.size() || getParentActivity() == null) { return; } TranslateAlert alert = TranslateAlert.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageId, fromLang[0], toLang, finalMessageText, noforwards, onLinkPress, () -> dimBehindView(false)); alert.showDim(false); closeMenu(false); }); cell.postDelayed(() -> { if (onLangDetectionDone.get() != null) { onLangDetectionDone.getAndSet(null).run(); } }, 250); } else if (translateButtonEnabled) { cell.setOnClickListener(e -> { if (selectedObject == null || i >= options.size() || getParentActivity() == null) { return; } TranslateAlert alert = TranslateAlert.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageId, "und", toLang, finalMessageText, noforwards, onLinkPress, () -> dimBehindView(false)); alert.showDim(false); closeMenu(false); }); } else { cell.setVisibility(View.GONE); } } } } ChatScrimPopupContainerLayout scrimPopupContainerLayout = new ChatScrimPopupContainerLayout(contentView.getContext()) { @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { closeMenu(); } return super.dispatchKeyEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean b = super.dispatchTouchEvent(ev); if (ev.getAction() == MotionEvent.ACTION_DOWN && !b) { closeMenu(); } return b; } }; scrimPopupContainerLayout.setOnTouchListener(new View.OnTouchListener() { private int[] pos = new int[2]; @Override public boolean onTouch(View v, MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { if (scrimPopupWindow != null && scrimPopupWindow.isShowing()) { View contentView = scrimPopupWindow.getContentView(); contentView.getLocationInWindow(pos); rect.set(pos[0], pos[1], pos[0] + contentView.getMeasuredWidth(), pos[1] + contentView.getMeasuredHeight()); if (!rect.contains((int) event.getX(), (int) event.getY())) { closeMenu(); } } } else if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) { closeMenu(); } return false; } }); ReactionsContainerLayout reactionsLayout = null; if (optionsView != null) { scrimPopupContainerLayout.addView(optionsView); } else { reactionsLayout = new ReactionsContainerLayout(ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); if (isReactionsAvailable) { int pad = 22; int sPad = 24; reactionsLayout.setPadding(AndroidUtilities.dp(4) + (LocaleController.isRTL ? 0 : sPad), AndroidUtilities.dp(4), AndroidUtilities.dp(4) + (LocaleController.isRTL ? sPad : 0), AndroidUtilities.dp(pad)); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; reactionsLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View v, TLRPC.TL_availableReaction reaction, boolean longpress) { selectReaction(primaryMessage, finalReactionsLayout, 0, 0, reaction, false, longpress); } @Override public void hideMenu() { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(false); } } }); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 50, 0, -20); scrimPopupContainerLayout.addView(reactionsLayout, params); scrimPopupContainerLayout.setReactionsLayout(reactionsLayout); scrimPopupContainerLayout.setClipChildren(false); reactionsLayout.setMessage(message, chatInfo); reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { popupLayout.getSwipeBack().addOnSwipeBackProgressListener(new PopupSwipeBackLayout.OnSwipeBackProgressListener() { boolean isEnter = true; @Override public void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, float progress) { if (toProgress == 0 && !isEnter) { finalReactionsLayout.startEnterAnimation(); isEnter = true; } else if (toProgress == 1 && isEnter) { finalReactionsLayout.setAlpha(1f - progress); if (progress == 1f) { isEnter = false; } } } }); } } boolean showNoForwards = noforwards && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED; scrimPopupContainerLayout.addView(popupLayout, LayoutHelper.createLinearRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, 0, isReactionsAvailable ? 36 : 0, 0)); scrimPopupContainerLayout.setPopupWindowLayout(popupLayout); if (showNoForwards) { popupLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); boolean isChannel = ChatObject.isChannel(currentChat) && !currentChat.megagroup; TextView tv = new TextView(contentView.getContext()); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); tv.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); if (getMessagesController().isChatNoForwards(currentChat)) { tv.setText(isChannel ? LocaleController.getString("ForwardsRestrictedInfoChannel", R.string.ForwardsRestrictedInfoChannel) : LocaleController.getString("ForwardsRestrictedInfoGroup", R.string.ForwardsRestrictedInfoGroup)); } else { tv.setText(LocaleController.getString("ForwardsRestrictedInfoBot", R.string.ForwardsRestrictedInfoBot)); } tv.setMaxWidth(popupLayout.getMeasuredWidth() - AndroidUtilities.dp(38)); Drawable shadowDrawable2 = ContextCompat.getDrawable(contentView.getContext(), R.drawable.popup_fixed_alert).mutate(); shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); FrameLayout fl = new FrameLayout(contentView.getContext()); fl.setBackground(shadowDrawable2); fl.addView(tv, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 11, 11, 11, 11)); scrimPopupContainerLayout.addView(fl, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, -8, isReactionsAvailable ? 36 : 0, 0)); scrimPopupContainerLayout.applyViewBottom(fl); } if (message.contentType == 0) { AnimatedEmojiSpan[] animatedEmojiSpans1 = message.messageText instanceof Spanned ? ((Spanned) message.messageText).getSpans(0, message.messageText.length(), AnimatedEmojiSpan.class) : null; CharSequence caption = getMessageCaption(selectedObject, selectedObjectGroup); AnimatedEmojiSpan[] animatedEmojiSpans2 = caption instanceof Spanned ? ((Spanned) caption).getSpans(0, caption.length(), AnimatedEmojiSpan.class) : null; int animatedEmojiCount = (animatedEmojiSpans1 == null ? 0 : animatedEmojiSpans1.length) + (animatedEmojiSpans2 == null ? 0 : animatedEmojiSpans2.length); if (animatedEmojiCount > 0) { ArrayList stickerSets = new ArrayList<>(); int firstCount = (animatedEmojiSpans1 == null ? 0 : animatedEmojiSpans1.length); for (int i = 0; i < animatedEmojiCount; ++i) { AnimatedEmojiSpan span = i < firstCount ? animatedEmojiSpans1[i] : animatedEmojiSpans2[i - firstCount]; if (span == null || span.standard) { continue; } TLRPC.Document document = span.document == null ? AnimatedEmojiDrawable.findDocument(currentAccount, span.documentId) : span.document; TLRPC.InputStickerSet stickerSet = MessageObject.getInputStickerSet(document); if (stickerSet == null) { continue; } boolean found = false; for (int j = 0; j < stickerSets.size(); ++j) { if (stickerSets.get(j).id == stickerSet.id) { found = true; break; } } if (!found) { stickerSets.add(stickerSet); } } if (stickerSets.size() > 0) { View gap = new FrameLayout(contentView.getContext()); gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); View button = new MessageContainsEmojiButton(currentAccount, contentView.getContext(), themeDelegate, stickerSets); button.setOnClickListener(e -> { EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, stickerSets) { @Override public void dismiss() { super.dismiss(); dimBehindView(false); } }; alert.setCalcMandatoryInsets(isKeyboardVisible()); alert.setDimBehind(false); closeMenu(false); showDialog(alert); }); popupLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } } } } scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @Override public void dismiss() { super.dismiss(); if (scrimPopupWindow != this) { return; } scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); if (scrimPopupWindowHideDimOnDismiss) { dimBehindView(false); } else { scrimPopupWindowHideDimOnDismiss = true; } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } } }; scrimPopupWindow.setPauseNotifications(true); scrimPopupWindow.setDismissAnimationDuration(220); scrimPopupWindow.setOutsideTouchable(true); scrimPopupWindow.setClippingEnabled(true); scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); scrimPopupWindow.setFocusable(true); scrimPopupContainerLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); scrimPopupWindow.getContentView().setFocusableInTouchMode(true); popupLayout.setFitItems(true); int popupX = v.getLeft() + (int) x - scrimPopupContainerLayout.getMeasuredWidth() + backgroundPaddings.left - AndroidUtilities.dp(28); if (popupX < AndroidUtilities.dp(6)) { popupX = AndroidUtilities.dp(6); } else if (popupX > chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth()) { popupX = chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth(); } if (AndroidUtilities.isTablet()) { int[] location = new int[2]; fragmentView.getLocationInWindow(location); popupX += location[0]; } int totalHeight = contentView.getHeight(); int height = scrimPopupContainerLayout.getMeasuredHeight() + AndroidUtilities.dp(48); int keyboardHeight = contentView.measureKeyboardHeight(); if (keyboardHeight > AndroidUtilities.dp(20)) { totalHeight += keyboardHeight; } int popupY; if (height < totalHeight) { popupY = (int) (chatListView.getY() + v.getTop() + y); if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { popupY += AndroidUtilities.dp(240) - height; } if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { popupY = totalHeight - height - AndroidUtilities.dp(8); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } final int finalPopupX = scrimPopupX = popupX; final int finalPopupY = scrimPopupY = popupY; scrimPopupContainerLayout.setMaxHeight(totalHeight - popupY); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; Runnable showMenu = () -> { if (scrimPopupWindow == null || fragmentView == null || scrimPopupWindow.isShowing()) { return; } scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); if (isReactionsAvailable && finalReactionsLayout != null) { finalReactionsLayout.startEnterAnimation(); } AndroidUtilities.runOnUIThread(() -> { if (scrimPopupWindowItems != null && scrimPopupWindowItems.length > 0 && scrimPopupWindowItems[0] != null) { scrimPopupWindowItems[0].requestFocus(); scrimPopupWindowItems[0].performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); scrimPopupWindowItems[0].sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } }, 420); }; if (waitForLangDetection.get()) { onLangDetectionDone.set(showMenu); } else { showMenu.run(); } chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); dimBehindView(v, true); hideHints(false); if (topUndoView != null) { topUndoView.hide(true, 1); } if (undoView != null) { undoView.hide(true, 1); } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } return true; } if (chatActivityEnterView != null && (chatActivityEnterView.isRecordingAudioVideo() || chatActivityEnterView.isRecordLocked())) { return false; } final ActionBarMenu actionMode = actionBar.createActionMode(); View item = actionMode.getItem(delete); if (item != null) { item.setVisibility(View.VISIBLE); } bottomMessagesActionContainer.setVisibility(View.VISIBLE); int translationY = chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(51); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { ArrayList views = new ArrayList<>(); views.add(chatActivityEnterView); if (mentionContainer != null && mentionContainer.getVisibility() == View.VISIBLE) { views.add(mentionContainer); } if (suggestEmojiPanel != null && suggestEmojiPanel.getVisibility() == View.VISIBLE) { views.add(suggestEmojiPanel); } actionBar.showActionMode(true, bottomMessagesActionContainer, null, views.toArray(new View[0]), new boolean[]{false, true, true}, chatListView, translationY); if (getParentActivity() instanceof LaunchActivity) { ((LaunchActivity) getParentActivity()).hideVisibleActionMode(); } chatActivityEnterView.getEditField().setAllowDrawCursor(false); } else if (bottomOverlayChat.getVisibility() == View.VISIBLE) { actionBar.showActionMode(true, bottomMessagesActionContainer, null, new View[]{bottomOverlayChat}, new boolean[]{true}, chatListView, translationY); } else { actionBar.showActionMode(true, bottomMessagesActionContainer, null, null, null, chatListView, translationY); } closeMenu(); chatLayoutManager.setCanScrollVertically(true); updatePinnedMessageView(true); AnimatorSet animatorSet = new AnimatorSet(); ArrayList animators = new ArrayList<>(); for (int a = 0; a < actionModeViews.size(); a++) { View view = actionModeViews.get(a); view.setPivotY(ActionBar.getCurrentActionBarHeight() / 2); AndroidUtilities.clearDrawableAnimation(view); animators.add(ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.1f, 1.0f)); } animatorSet.playTogether(animators); animatorSet.setDuration(250); animatorSet.start(); addToSelectedMessages(message, listView); if (chatActivityEnterView != null) { chatActivityEnterView.preventInput = true; } selectedMessagesCountTextView.setNumber(selectedMessagesIds[0].size() + selectedMessagesIds[1].size(), false); updateVisibleRows(); if (chatActivityEnterView != null) { chatActivityEnterView.hideBotCommands(); } return false; } public void closeMenu() { closeMenu(true); } private ValueAnimator scrimViewAlphaAnimator; private void closeMenu(boolean hideDim) { scrimPopupWindowHideDimOnDismiss = hideDim; if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } if (!hideDim) { if (scrimViewAlphaAnimator != null) { scrimViewAlphaAnimator.removeAllListeners(); scrimViewAlphaAnimator.cancel(); } scrimViewAlphaAnimator = ValueAnimator.ofFloat(1f, 0f); scrimViewAlphaAnimator.addUpdateListener(a -> { scrimViewAlpha = (float) a.getAnimatedValue(); if (contentView != null) { contentView.invalidate(); chatListView.invalidate(); } }); scrimViewAlphaAnimator.setDuration(150); scrimViewAlphaAnimator.start(); } } Runnable updateReactionRunnable; private void selectReaction(MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, float x, float y, TLRPC.TL_availableReaction reaction, boolean fromDoubleTap, boolean bigEmoji) { if (isInScheduleMode()) { return; } ReactionsEffectOverlay.removeCurrent(false); boolean added = primaryMessage.selectReaction(reaction.reaction, bigEmoji, fromDoubleTap); int messageIdForCell = primaryMessage.getId(); if (groupedMessagesMap.get(primaryMessage.getGroupId()) != null) { int flags = primaryMessage.shouldDrawReactionsInLayout() ? MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_LEFT : MessageObject.POSITION_FLAG_BOTTOM | MessageObject.POSITION_FLAG_RIGHT; MessageObject messageObject = groupedMessagesMap.get(primaryMessage.getGroupId()).findMessageWithFlags(flags); if (messageObject != null) { messageIdForCell = messageObject.getId(); } } int finalMessageIdForCell = messageIdForCell; if (added && !fromDoubleTap) { ChatMessageCell cell = findMessageCell(finalMessageIdForCell, true); ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount, reactionsLayout != null ? (bigEmoji ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.ONLY_MOVE_ANIMATION) : ReactionsEffectOverlay.SHORT_ANIMATION); } if (added) { AndroidUtilities.makeAccessibilityAnnouncement(LocaleController.formatString("AccDescrYouReactedWith", R.string.AccDescrYouReactedWith, reaction.reaction)); } getSendMessagesHelper().sendReaction(primaryMessage, added ? reaction.reaction : null, bigEmoji, ChatActivity.this, updateReactionRunnable = new Runnable() { @Override public void run() { if (updateReactionRunnable != null) { updateReactionRunnable = null; if (fromDoubleTap) { doOnIdle(() -> { AndroidUtilities.runOnUIThread(() -> { ChatMessageCell cell = findMessageCell(finalMessageIdForCell, true); if (added) { ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount, ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } }, 50); }); } else { updateMessageAnimated(primaryMessage, true); ReactionsEffectOverlay.startAnimation(); } closeMenu(); } } }); if (fromDoubleTap) { updateMessageAnimated(primaryMessage, true); updateReactionRunnable.run(); } AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); } @SuppressLint("NotifyDataSetChanged") private void updateMessageAnimated(MessageObject message, boolean updateReactions) { if (chatAdapter == null) { return; } getNotificationCenter().doOnIdle(() -> { if (fragmentView == null) { return; } MessageObject.GroupedMessages group = groupedMessagesMap.get(message.getGroupId()); if (group != null) { if (chatListItemAnimator != null) { chatListItemAnimator.groupWillChanged(group); } for (int i = 0; i < group.messages.size(); i++) { group.messages.get(i).forceUpdate = true; if (updateReactions) { group.messages.get(i).reactionsChanged = true; } } chatAdapter.notifyDataSetChanged(true); } else { int index = messages.indexOf(message); if (index >= 0) { chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); } } }); } public ChatMessageCell findMessageCell(int id, boolean visibleForUser) { if (chatListView == null) { return null; } for (int i = 0, n = chatListView.getChildCount(); i < n; i++) { View child = chatListView.getChildAt(i); if (chatListView.getChildAt(i) instanceof ChatMessageCell && ((ChatMessageCell) chatListView.getChildAt(i)).getMessageObject().getId() == id) { if (visibleForUser) { float clipTop = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4); if (child.getY() + child.getMeasuredHeight() < clipTop || child.getY() > chatListView.getMeasuredHeight() - blurredViewBottomOffset) { return null; } } return (ChatMessageCell) chatListView.getChildAt(i); } } return null; } private void startEditingMessageObject(MessageObject messageObject) { if (messageObject == null || getParentActivity() == null) { return; } if (searchItem != null && actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(); chatActivityEnterView.setFieldFocused(); } mentionContainer.getAdapter().setNeedBotContext(false); chatActivityEnterView.setVisibility(View.VISIBLE); showFieldPanelForEdit(true, messageObject); updateBottomOverlay(); checkEditTimer(); chatActivityEnterView.setAllowStickersAndGifs(true, false, false, true); updatePinnedMessageView(true); updateVisibleRows(); if (!messageObject.scheduled) { TLRPC.TL_messages_getMessageEditData req = new TLRPC.TL_messages_getMessageEditData(); req.peer = getMessagesController().getInputPeer(dialog_id); req.id = messageObject.getId(); editingMessageObjectReqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { editingMessageObjectReqId = 0; if (response == null) { if (getParentActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("EditMessageError", R.string.EditMessageError)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); if (chatActivityEnterView != null) { chatActivityEnterView.setEditingMessageObject(null, false); hideFieldPanel(true); } } })); } else { chatActivityEnterView.showEditDoneProgress(false, true); } } public void setupStickerVibrationAndSound(ChatMessageCell cell) { MessageObject message = cell.getMessageObject(); TLRPC.Document document = message.getDocument(); boolean isEmoji; if ((isEmoji = message.isAnimatedEmoji()) || MessageObject.isAnimatedStickerDocument(document, currentEncryptedChat == null || message.isOut()) && !SharedConfig.loopStickers) { ImageReceiver imageReceiver = cell.getPhotoImage(); RLottieDrawable drawable = imageReceiver.getLottieAnimation(); if (drawable != null) { if (isEmoji) { String emoji = message.getStickerEmoji(); emoji = EmojiAnimationsOverlay.unwrapEmoji(emoji); if (EmojiData.isHeartEmoji(emoji)) { HashMap pattern = new HashMap<>(); pattern.put(1, 1); pattern.put(13, 0); pattern.put(59, 1); pattern.put(71, 0); pattern.put(128, 1); pattern.put(140, 0); drawable.setVibrationPattern(pattern); } else if (EmojiData.isPeachEmoji(emoji)) { HashMap pattern = new HashMap<>(); pattern.put(34, 1); drawable.setVibrationPattern(pattern); } else if (EmojiData.isCofinEmoji(emoji)) { HashMap pattern = new HashMap<>(); pattern.put(24, 0); pattern.put(36, 0); drawable.setVibrationPattern(pattern); } if (message.isAnimatedAnimatedEmoji()) { drawable.resetVibrationAfterRestart(true); } if (!drawable.isRunning() && emoji != null) { MessagesController.EmojiSound sound = getMessagesController().emojiSounds.get(emoji.replace("\uFE0F", "")); if (sound != null) { getMediaController().playEmojiSound(getAccountInstance(), emoji, sound, false); } } } } } } public void restartSticker(ChatMessageCell cell) { MessageObject message = cell.getMessageObject(); TLRPC.Document document = message.getDocument(); if (!message.isAnimatedAnimatedEmoji()) { setupStickerVibrationAndSound(cell); } if ((message.isAnimatedEmoji()) || MessageObject.isAnimatedStickerDocument(document, currentEncryptedChat == null || message.isOut()) && !SharedConfig.loopStickers) { ImageReceiver imageReceiver = cell.getPhotoImage(); RLottieDrawable drawable = imageReceiver.getLottieAnimation(); if (drawable != null) { drawable.restart(); } } } private CharSequence getMessageContent(MessageObject messageObject, long previousUid, boolean name) { SpannableStringBuilder str = new SpannableStringBuilder(); if (name) { long fromId = messageObject.getFromChatId(); if (previousUid != fromId) { if (fromId > 0) { TLRPC.User user = getMessagesController().getUser(fromId); if (user != null) { str.append(ContactsController.formatName(user.first_name, user.last_name)).append(":\n"); } } else if (fromId < 0) { TLRPC.Chat chat = getMessagesController().getChat(-fromId); if (chat != null) { str.append(chat.title).append(":\n"); } } } } String restrictionReason = MessagesController.getRestrictionReason(messageObject.messageOwner.restriction_reason); if (!TextUtils.isEmpty(restrictionReason)) { str.append(restrictionReason); } else if (messageObject.caption != null){ str.append(messageObject.caption); } else { str.append(messageObject.messageText); } return str; } private void unpinMessage(MessageObject messageObject) { if (messageObject == null) { return; } if (pinBulletin != null) { pinBulletin.hide(false, 0); } ArrayList objects = new ArrayList<>(); objects.add(selectedObject); ArrayList ids = new ArrayList<>(); ids.add(messageObject.getId()); int oldTotalPinnedCount = totalPinnedMessagesCount; getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, false, null, null, 0, totalPinnedMessagesCount - 1, pinnedEndReached); pinBulletin = BulletinFactory.createUnpinMessageBulletin(this, () -> { getNotificationCenter().postNotificationName(NotificationCenter.didLoadPinnedMessages, dialog_id, ids, true, objects, null, 0, oldTotalPinnedCount, pinnedEndReached); pinBulletin = null; }, () -> { getMessagesController().pinMessage(currentChat, currentUser, messageObject.getId(), true, false, false); pinBulletin = null; }, themeDelegate).show(); } public void openReportChat(int type) { Bundle args = new Bundle(); if (DialogObject.isUserDialog(dialog_id)) { args.putLong("user_id", dialog_id); } else { args.putLong("chat_id", -dialog_id); } args.putInt("report", type); ChatActivity fragment = new ChatActivity(args); presentFragment(fragment); fragment.chatActivityDelegate = new ChatActivityDelegate() { @Override public void onReport() { undoView.showWithAction(0, UndoView.ACTION_REPORT_SENT, null); } }; } private void saveMessageToGallery(MessageObject messageObject) { String path = messageObject.messageOwner.attachPath; if (!TextUtils.isEmpty(path)) { File temp = new File(path); if (!temp.exists()) { path = null; } } if (TextUtils.isEmpty(path)) { path = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner).toString(); } MediaController.saveFile(path, getParentActivity(), messageObject.isVideo() ? 1 : 0, null, null); } private void processSelectedOption(int option) { if (selectedObject == null || getParentActivity() == null) { return; } boolean preserveDim = false; switch (option) { case OPTION_RETRY: { if (selectedObjectGroup != null) { boolean success = true; for (int a = 0; a < selectedObjectGroup.messages.size(); a++) { if (!getSendMessagesHelper().retrySendMessage(selectedObjectGroup.messages.get(a), false)) { success = false; } } if (success && chatMode == 0) { moveScrollToLastMessage(false); } } else { if (getSendMessagesHelper().retrySendMessage(selectedObject, false)) { updateVisibleRows(); if (chatMode == 0) { moveScrollToLastMessage(false); } } } break; } case OPTION_DELETE: { if (getParentActivity() == null) { selectedObject = null; selectedObjectToEditCaption = null; selectedObjectGroup = null; return; } preserveDim = true; createDeleteMessagesAlert(selectedObject, selectedObjectGroup, 1,true); break; } case OPTION_FORWARD: { forwardingMessage = selectedObject; forwardingMessageGroup = selectedObjectGroup; Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 3); args.putInt("messagesCount", forwardingMessageGroup == null ? 1 : forwardingMessageGroup.messages.size()); args.putInt("hasPoll", forwardingMessage.isPoll() ? (forwardingMessage.isPublicPoll() ? 2 : 1) : 0); args.putBoolean("hasInvoice", forwardingMessage.isInvoice()); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(this); presentFragment(fragment); break; } case OPTION_COPY: { if (selectedObject.isDice()) { AndroidUtilities.addToClipboard(selectedObject.getDiceEmoji()); } else { CharSequence caption = getMessageCaption(selectedObject, selectedObjectGroup); if (caption != null) { AndroidUtilities.addToClipboard(caption); } else { AndroidUtilities.addToClipboard(getMessageContent(selectedObject, 0, false)); } } undoView.showWithAction(0, UndoView.ACTION_MESSAGE_COPIED, null); break; } case OPTION_SAVE_TO_GALLERY: { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; return; } if (selectedObjectGroup != null) { int filesAmount = selectedObjectGroup.messages.size(); boolean allPhotos = true, allVideos = true; for (int a = 0; a < filesAmount; a++) { MessageObject messageObject = selectedObjectGroup.messages.get(a); saveMessageToGallery(messageObject); allPhotos &= messageObject.isPhoto(); allVideos &= messageObject.isVideo(); } final BulletinFactory.FileType fileType; if (allPhotos) { fileType = BulletinFactory.FileType.PHOTOS; } else if (allVideos) { fileType = BulletinFactory.FileType.VIDEOS; } else { fileType = BulletinFactory.FileType.MEDIA; } BulletinFactory.of(this).createDownloadBulletin(fileType, filesAmount, themeDelegate).show(); } else { saveMessageToGallery(selectedObject); if (getParentActivity() != null) { BulletinFactory.createSaveToGalleryBulletin(this, selectedObject.isVideo(), themeDelegate).show(); } } break; } case OPTION_APPLY_LOCALIZATION_OR_THEME: { File locFile = null; if (!TextUtils.isEmpty(selectedObject.messageOwner.attachPath)) { File f = new File(selectedObject.messageOwner.attachPath); if (f.exists()) { locFile = f; } } if (locFile == null) { File f = getFileLoader().getPathToMessage(selectedObject.messageOwner); if (f.exists()) { locFile = f; } } if (locFile != null) { if (locFile.getName().toLowerCase().endsWith("attheme")) { Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, selectedObject.getDocumentName(), null, true); if (themeInfo != null) { presentFragment(new ThemePreviewActivity(themeInfo)); } else { scrollToPositionOnRecreate = -1; if (getParentActivity() == null) { selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("IncorrectTheme", R.string.IncorrectTheme)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); preserveDim = true; builder.setDimEnabled(false); builder.setOnPreDismissListener(di -> dimBehindView(false)); showDialog(builder.create()); } } else { if (LocaleController.getInstance().applyLanguageFile(locFile, currentAccount)) { presentFragment(new LanguageSelectActivity()); } else { if (getParentActivity() == null) { selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("IncorrectLocalization", R.string.IncorrectLocalization)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); preserveDim = true; builder.setDimEnabled(false); builder.setOnPreDismissListener(di -> dimBehindView(false)); showDialog(builder.create()); } } } break; } case OPTION_SHARE: { String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); if (!temp.exists()) { path = null; } } if (path == null || path.length() == 0) { path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(selectedObject.getDocument().mime_type); File f = new File(path); if (Build.VERSION.SDK_INT >= 24) { try { intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(getParentActivity(), ApplicationLoader.getApplicationId() + ".provider", f)); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } catch (Exception ignore) { intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); } } else { intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f)); } try { getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("ShareFile", R.string.ShareFile)), 500); } catch (Throwable ignore) { } break; } case OPTION_SAVE_TO_GALLERY2: { String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); if (!temp.exists()) { path = null; } } if (path == null || path.length() == 0) { path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; return; } MediaController.saveFile(path, getParentActivity(), 0, null, null); BulletinFactory.createSaveToGalleryBulletin(this, selectedObject.isVideo(), themeDelegate).show(); break; } case OPTION_REPLY: { showFieldPanelForReply(selectedObject); break; } case OPTION_ADD_TO_STICKERS_OR_MASKS: { StickersAlert alert = new StickersAlert(getParentActivity(), this, selectedObject.getInputStickerSet(), null, bottomOverlayChat.getVisibility() != View.VISIBLE && (currentChat == null || ChatObject.canSendStickers(currentChat)) ? chatActivityEnterView : null, themeDelegate); alert.setCalcMandatoryInsets(isKeyboardVisible()); preserveDim = true; alert.setDimBehind(false); alert.setOnDismissListener(() -> dimBehindView(false)); showDialog(alert); break; } case OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC: { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; return; } boolean isMusic = selectedObject.isMusic(); boolean isDocument = selectedObject.isDocument(); if (isMusic || isDocument) { ArrayList messageObjects; if (selectedObjectGroup != null) { messageObjects = new ArrayList<>(selectedObjectGroup.messages); } else { messageObjects = new ArrayList<>(); messageObjects.add(selectedObject); } MediaController.saveFilesFromMessages(getParentActivity(), getAccountInstance(), messageObjects, (count) -> { if (getParentActivity() == null || fragmentView == null) { return; } if (count > 0) { BulletinFactory.of(this).createDownloadBulletin(isMusic ? BulletinFactory.FileType.AUDIOS : BulletinFactory.FileType.UNKNOWNS, count, themeDelegate).show(); } }); } else { boolean video = selectedObject.isVideo(); boolean photo = selectedObject.isPhoto(); boolean gif = selectedObject.isGif(); String fileName = FileLoader.getDocumentFileName(selectedObject.getDocument()); if (TextUtils.isEmpty(fileName)) { fileName = selectedObject.getFileName(); } String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); if (!temp.exists()) { path = null; } } if (path == null || path.length() == 0) { path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } MediaController.saveFile(path, getParentActivity(), 2, fileName, selectedObject.getDocument() != null ? selectedObject.getDocument().mime_type : "", () -> { if (getParentActivity() == null) { return; } final BulletinFactory.FileType fileType; if (photo) { fileType = BulletinFactory.FileType.PHOTO_TO_DOWNLOADS; } else if (video) { fileType = BulletinFactory.FileType.VIDEO_TO_DOWNLOADS; } else if (gif) { fileType = BulletinFactory.FileType.GIF_TO_DOWNLOADS; } else { fileType = BulletinFactory.FileType.UNKNOWN; } BulletinFactory.of(this).createDownloadBulletin(fileType, themeDelegate).show(); }); } break; } case OPTION_ADD_TO_GIFS: { TLRPC.Document document = selectedObject.getDocument(); getMessagesController().saveGif(selectedObject, document); if (!showGifHint() && getParentActivity() != null) { BulletinFactory.of(this).createDownloadBulletin(BulletinFactory.FileType.GIF, themeDelegate).show(); } chatActivityEnterView.addRecentGif(document); break; } case OPTION_EDIT: { if (selectedObjectToEditCaption != null) { startEditingMessageObject(selectedObjectToEditCaption); } else { startEditingMessageObject(selectedObject); } selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; break; } case OPTION_PIN: { final int mid; if (selectedObjectGroup != null && !selectedObjectGroup.messages.isEmpty()) { mid = selectedObjectGroup.messages.get(0).getId(); } else { mid = selectedObject.getId(); } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("PinMessageAlertTitle", R.string.PinMessageAlertTitle)); preserveDim = true; builder.setDimAlpha(.5f); builder.setOnPreDismissListener(di -> dimBehindView(false)); final boolean[] checks; if (currentUser != null) { if (currentPinnedMessageId != 0 && mid < currentPinnedMessageId) { builder.setMessage(LocaleController.getString("PinOldMessageAlert", R.string.PinOldMessageAlert)); } else { builder.setMessage(LocaleController.getString("PinMessageAlertChat", R.string.PinMessageAlertChat)); } checks = new boolean[]{false, false}; if (!UserObject.isUserSelf(currentUser)) { FrameLayout frameLayout = new FrameLayout(getParentActivity()); CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1, themeDelegate); cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); cell.setText(LocaleController.formatString("PinAlsoFor", R.string.PinAlsoFor, UserObject.getFirstName(currentUser)), "", false, false); cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(8) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(8), 0); frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 8, 0, 8, 0)); cell.setOnClickListener(v -> { CheckBoxCell cell1 = (CheckBoxCell) v; checks[1] = !checks[1]; cell1.setChecked(checks[1], true); }); builder.setView(frameLayout); } } else if (ChatObject.isChannel(currentChat) && currentChat.megagroup || currentChat != null && !ChatObject.isChannel(currentChat)) { if (!pinnedMessageIds.isEmpty() && mid < pinnedMessageIds.get(0)) { builder.setMessage(LocaleController.getString("PinOldMessageAlert", R.string.PinOldMessageAlert)); checks = new boolean[]{false, true}; } else { builder.setMessage(LocaleController.getString("PinMessageAlert", R.string.PinMessageAlert)); checks = new boolean[]{true, true}; FrameLayout frameLayout = new FrameLayout(getParentActivity()); CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1, themeDelegate); cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); cell.setText(LocaleController.getString("PinNotify", R.string.PinNotify), "", true, false); cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(8) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(8), 0); frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 8, 0, 8, 0)); cell.setOnClickListener(v -> { CheckBoxCell cell1 = (CheckBoxCell) v; checks[0] = !checks[0]; cell1.setChecked(checks[0], true); }); builder.setView(frameLayout); } } else { if (currentPinnedMessageId != 0 && mid < currentPinnedMessageId) { builder.setMessage(LocaleController.getString("PinOldMessageAlert", R.string.PinOldMessageAlert)); } else { builder.setMessage(LocaleController.getString("PinMessageAlertChannel", R.string.PinMessageAlertChannel)); } checks = new boolean[]{false, true}; } builder.setPositiveButton(LocaleController.getString("PinMessage", R.string.PinMessage), (dialogInterface, i) -> { getMessagesController().pinMessage(currentChat, currentUser, mid, false, !checks[1], checks[0]); Bulletin bulletin = BulletinFactory.createPinMessageBulletin(this, themeDelegate); bulletin.show(); View view = bulletin.getLayout(); view.postDelayed(() -> { view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); }, 550); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); break; } case OPTION_UNPIN: { MessageObject messageObject; if (pinnedMessageObjects.containsKey(selectedObject.getId())) { messageObject = selectedObject; } else if (selectedObjectGroup != null && !selectedObjectGroup.messages.isEmpty()) { messageObject = selectedObjectGroup.messages.get(0); } else { messageObject = selectedObject; } if (chatMode == MODE_PINNED && messages.size() == 2) { finishFragment(); chatActivityDelegate.onUnpin(false, false); } else { unpinMessage(messageObject); } break; } case OPTION_ADD_CONTACT: { Bundle args = new Bundle(); args.putLong("user_id", selectedObject.messageOwner.media.user_id); args.putString("phone", selectedObject.messageOwner.media.phone_number); args.putBoolean("addContact", true); presentFragment(new ContactAddActivity(args)); break; } case OPTION_COPY_PHONE_NUMBER: { AndroidUtilities.addToClipboard(selectedObject.messageOwner.media.phone_number); break; } case OPTION_CALL: { try { Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + selectedObject.messageOwner.media.phone_number)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getParentActivity().startActivityForResult(intent, 500); } catch (Exception e) { FileLog.e(e); } break; } case OPTION_CALL_AGAIN: { if (currentUser != null) { VoIPHelper.startCall(currentUser, selectedObject.isVideoCall(), userInfo != null && userInfo.video_calls_available, getParentActivity(), getMessagesController().getUserFull(currentUser.id), getAccountInstance()); } break; } case OPTION_RATE_CALL: { VoIPHelper.showRateAlert(getParentActivity(), (TLRPC.TL_messageActionPhoneCall) selectedObject.messageOwner.action); break; } case OPTION_ADD_STICKER_TO_FAVORITES: { getMediaDataController().addRecentSticker(MediaDataController.TYPE_FAVE, selectedObject, selectedObject.getDocument(), (int) (System.currentTimeMillis() / 1000), false); break; } case OPTION_DELETE_STICKER_FROM_FAVORITES: { getMediaDataController().addRecentSticker(MediaDataController.TYPE_FAVE, selectedObject, selectedObject.getDocument(), (int) (System.currentTimeMillis() / 1000), true); break; } case OPTION_COPY_LINK: { TLRPC.TL_channels_exportMessageLink req = new TLRPC.TL_channels_exportMessageLink(); if (selectedObject == replyingMessageObject && isComments) { req.id = replyOriginalMessageId; req.channel = MessagesController.getInputChannel(replyOriginalChat); } else { req.id = selectedObject.getId(); req.channel = MessagesController.getInputChannel(currentChat); req.thread = isReplyChatComment(); } getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response != null) { TLRPC.TL_exportedMessageLink exportedMessageLink = (TLRPC.TL_exportedMessageLink) response; try { android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("label", exportedMessageLink.link); clipboard.setPrimaryClip(clip); if (BulletinFactory.canShowBulletin(ChatActivity.this)) { BulletinFactory.of(ChatActivity.this).createCopyLinkBulletin(!isThreadChat() && exportedMessageLink.link.contains("/c/"), themeDelegate).show(); } } catch (Exception e) { FileLog.e(e); } } })); break; } case OPTION_REPORT_CHAT: { if (UserObject.isReplyUser(currentUser)) { if (selectedObject.messageOwner.fwd_from != null) { preserveDim = true; AlertsCreator.showBlockReportSpamReplyAlert(ChatActivity.this, selectedObject, MessageObject.getPeerId(selectedObject.messageOwner.fwd_from.from_id), themeDelegate, () -> dimBehindView(false)); } } else { preserveDim = true; AlertsCreator.createReportAlert(getParentActivity(), dialog_id, selectedObject.getId(), ChatActivity.this, themeDelegate, () -> dimBehindView(false)); } break; } case OPTION_CANCEL_SENDING: { if (selectedObject.isEditing() || selectedObject.isSending() && selectedObjectGroup == null) { getSendMessagesHelper().cancelSendingMessage(selectedObject); } else if (selectedObject.isSending() && selectedObjectGroup != null) { for (int a = 0; a < selectedObjectGroup.messages.size(); a++) { getSendMessagesHelper().cancelSendingMessage(new ArrayList<>(selectedObjectGroup.messages)); } } break; } case OPTION_UNVOTE: { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3, themeDelegate)}; int requestId = getSendMessagesHelper().sendVote(selectedObject, null, () -> { try { progressDialog[0].dismiss(); } catch (Throwable ignore) { } progressDialog[0] = null; }); if (requestId != 0) { AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } progressDialog[0].setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(requestId, true)); showDialog(progressDialog[0]); }, 500); } break; } case OPTION_STOP_POLL_OR_QUIZ: { MessageObject object = selectedObject; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); preserveDim = true; builder.setDimEnabled(false); builder.setOnPreDismissListener(di -> dimBehindView(false)); if (object.isQuiz()) { builder.setTitle(LocaleController.getString("StopQuizAlertTitle", R.string.StopQuizAlertTitle)); builder.setMessage(LocaleController.getString("StopQuizAlertText", R.string.StopQuizAlertText)); } else { builder.setTitle(LocaleController.getString("StopPollAlertTitle", R.string.StopPollAlertTitle)); builder.setMessage(LocaleController.getString("StopPollAlertText", R.string.StopPollAlertText)); } builder.setPositiveButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3, themeDelegate)}; TLRPC.TL_messages_editMessage req = new TLRPC.TL_messages_editMessage(); TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; TLRPC.TL_inputMediaPoll poll = new TLRPC.TL_inputMediaPoll(); poll.poll = new TLRPC.TL_poll(); poll.poll.id = mediaPoll.poll.id; poll.poll.question = mediaPoll.poll.question; poll.poll.answers = mediaPoll.poll.answers; poll.poll.closed = true; req.media = poll; req.peer = getMessagesController().getInputPeer(dialog_id); req.id = object.getId(); req.flags |= 16384; int requestId = getConnectionsManager().sendRequest(req, (response, error) -> { AndroidUtilities.runOnUIThread(() -> { try { progressDialog[0].dismiss(); } catch (Throwable ignore) { } progressDialog[0] = null; }); if (error == null) { getMessagesController().processUpdates((TLRPC.Updates) response, false); } else { AndroidUtilities.runOnUIThread(() -> AlertsCreator.processError(currentAccount, error, ChatActivity.this, req)); } }); AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } progressDialog[0].setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(requestId, true)); showDialog(progressDialog[0]); }, 500); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); break; } case OPTION_VIEW_REPLIES_OR_THREAD: { openDiscussionMessageChat(currentChat.id, null, selectedObject.getId(), 0, -1, 0, null); break; } case OPTION_STATISTICS: { presentFragment(new MessageStatisticActivity(selectedObject)); break; } case OPTION_SEND_NOW: { if (!checkSlowMode(chatActivityEnterView.getSendButton())) { if (getMediaController().isPlayingMessage(selectedObject)) { getMediaController().cleanupPlayer(true, true); } TLRPC.TL_messages_sendScheduledMessages req = new TLRPC.TL_messages_sendScheduledMessages(); req.peer = getMessagesController().getInputPeer(dialog_id); if (selectedObjectGroup != null) { for (int a = 0; a < selectedObjectGroup.messages.size(); a++) { req.id.add(selectedObjectGroup.messages.get(a).getId()); } } else { req.id.add(selectedObject.getId()); } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (error == null) { TLRPC.Updates updates = (TLRPC.Updates) response; getMessagesController().processUpdates(updates, false); AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messagesDeleted, req.id, -dialog_id, true, dialog_id)); } else if (error.text != null) { AndroidUtilities.runOnUIThread(() -> { if (error.text.startsWith("SLOWMODE_WAIT_")) { AlertsCreator.showSimpleToast(ChatActivity.this, LocaleController.getString("SlowmodeSendError", R.string.SlowmodeSendError)); } else if (error.text.equals("CHAT_SEND_MEDIA_FORBIDDEN")) { AlertsCreator.showSimpleToast(ChatActivity.this, LocaleController.getString("AttachMediaRestrictedForever", R.string.AttachMediaRestrictedForever)); } else { AlertsCreator.showSimpleToast(ChatActivity.this, error.text); } }); } }); break; } } case OPTION_EDIT_SCHEDULE_TIME: { MessageObject message = selectedObject; MessageObject.GroupedMessages group = selectedObjectGroup; AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, message.messageOwner.date, (notify, scheduleDate) -> { if (group != null && !group.messages.isEmpty()) { SendMessagesHelper.getInstance(currentAccount).editMessage(group.messages.get(0), null, false, ChatActivity.this, null, scheduleDate); } else { SendMessagesHelper.getInstance(currentAccount).editMessage(message, null, false, ChatActivity.this, null, scheduleDate); } }, null, themeDelegate) .setOnPreDismissListener(di -> dimBehindView(false)) .setDimBehind(false); preserveDim = true; break; } case OPTION_HIDE_SPONSORED_MESSAGE: { MessageObject message = selectedObject; showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); break; } } selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; closeMenu(!preserveDim); } @Override public void didSelectDialogs(DialogsActivity fragment, ArrayList dids, CharSequence message, boolean param) { if (forwardingMessage == null && selectedMessagesIds[0].size() == 0 && selectedMessagesIds[1].size() == 0) { return; } ArrayList fmessages = new ArrayList<>(); if (forwardingMessage != null) { if (forwardingMessageGroup != null) { fmessages.addAll(forwardingMessageGroup.messages); } else { fmessages.add(forwardingMessage); } forwardingMessage = null; forwardingMessageGroup = null; } else { for (int a = 1; a >= 0; a--) { ArrayList ids = new ArrayList<>(); for (int b = 0; b < selectedMessagesIds[a].size(); b++) { ids.add(selectedMessagesIds[a].keyAt(b)); } Collections.sort(ids); for (int b = 0; b < ids.size(); b++) { Integer id = ids.get(b); MessageObject messageObject = selectedMessagesIds[a].get(id); if (messageObject != null) { fmessages.add(messageObject); } } selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); selectedMessagesIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } if (dids.size() > 1 || dids.get(0) == getUserConfig().getClientUserId() || message != null) { forwardingMessages = null; hideFieldPanel(false); for (int a = 0; a < dids.size(); a++) { long did = dids.get(a); if (message != null) { getSendMessagesHelper().sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null); } getSendMessagesHelper().sendMessage(fmessages, did, false, false,true, 0); } fragment.finishFragment(); if (dids.size() == 1) { undoView.showWithAction(dids.get(0), UndoView.ACTION_FWD_MESSAGES, fmessages.size()); } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, fmessages.size(), dids.size(), null, null); } } else { long did = dids.get(0); if (did != dialog_id || chatMode == MODE_PINNED) { Bundle args = new Bundle(); args.putBoolean("scrollToTopOnResume", scrollToTopOnResume); if (DialogObject.isEncryptedDialog(did)) { args.putInt("enc_id", DialogObject.getEncryptedChatId(did)); } else { if (DialogObject.isUserDialog(did)) { args.putLong("user_id", did); } else { args.putLong("chat_id", -did); } if (!getMessagesController().checkCanOpenChat(args, fragment)) { return; } } addToPulledDialogsMyself(); ChatActivity chatActivity = new ChatActivity(args); if (presentFragment(chatActivity, true)) { chatActivity.showFieldPanelForForward(true, fmessages); if (!AndroidUtilities.isTablet()) { removeSelfFromStack(); } } else { fragment.finishFragment(); } } else { fragment.finishFragment(); moveScrollToLastMessage(false); showFieldPanelForForward(true, fmessages); if (AndroidUtilities.isTablet()) { hideActionMode(); updatePinnedMessageView(true); } updateVisibleRows(); } } } public boolean checkRecordLocked(boolean forceCloseOnDiscard) { if (chatActivityEnterView != null && chatActivityEnterView.isRecordLocked()) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); if (chatActivityEnterView.isInVideoMode()) { builder.setTitle(LocaleController.getString("DiscardVideoMessageTitle", R.string.DiscardVideoMessageTitle)); builder.setMessage(LocaleController.getString("DiscardVideoMessageDescription", R.string.DiscardVideoMessageDescription)); } else { builder.setTitle(LocaleController.getString("DiscardVoiceMessageTitle", R.string.DiscardVoiceMessageTitle)); builder.setMessage(LocaleController.getString("DiscardVoiceMessageDescription", R.string.DiscardVoiceMessageDescription)); } builder.setPositiveButton(LocaleController.getString("DiscardVoiceMessageAction", R.string.DiscardVoiceMessageAction), (dialog, which) -> { if (chatActivityEnterView != null) { if (forceCloseOnDiscard) { finishFragment(); } else { chatActivityEnterView.cancelRecordingAudioVideo(); } } }); builder.setNegativeButton(LocaleController.getString("Continue", R.string.Continue), null); showDialog(builder.create()); return true; } return false; } @Override public boolean onBackPressed() { if (ContentPreviewViewer.getInstance().isVisible()) { ContentPreviewViewer.getInstance().closeWithMenu(); return false; } else if (forwardingPreviewView != null && forwardingPreviewView.isShowing()) { forwardingPreviewView.dismiss(true); return false; } else if (messagesSearchListView.getTag() != null) { showMessagesSearchListView(false); return false; } else if (scrimPopupWindow != null) { closeMenu(); return false; } else if (checkRecordLocked(false)) { return false; } else if (textSelectionHelper.isSelectionMode()) { textSelectionHelper.clear(); return false; } else if (actionBar != null && actionBar.isActionModeShowed()) { clearSelectionMode(); return false; } else if (chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) { return !chatActivityEnterView.hidePopup(true); } else if (chatActivityEnterView != null && chatActivityEnterView.hasBotWebView() && chatActivityEnterView.botCommandsMenuIsShowing() && chatActivityEnterView.onBotWebViewBackPressed()) { return false; } else if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuIsShowing()) { chatActivityEnterView.hideBotCommands(); return false; } if (backToPreviousFragment != null) { parentLayout.fragmentsStack.add(parentLayout.fragmentsStack.size() - 1, backToPreviousFragment); backToPreviousFragment = null; } return true; } private void clearSelectionMode() { for (int a = 1; a >= 0; a--) { selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } public void onListItemAnimatorTick() { invalidateMessagesVisiblePart(); if (scrimView != null) { fragmentView.invalidate(); } } public void setThreadMessages(ArrayList messageObjects, TLRPC.Chat originalChat, int originalMessage, int maxInboxReadId, int maxOutboxReadId) { threadMessageObjects = messageObjects; replyingMessageObject = threadMessageObject = threadMessageObjects.get(threadMessageObjects.size() - 1); threadMaxInboxReadId = maxInboxReadId; threadMaxOutboxReadId = maxOutboxReadId; replyMaxReadId = Math.max(1, maxInboxReadId); threadMessageId = threadMessageObject.getId(); replyOriginalMessageId = originalMessage; replyOriginalChat = originalChat; isComments = replyingMessageObject.messageOwner.fwd_from != null && replyingMessageObject.messageOwner.fwd_from.channel_post != 0; } public void setHighlightMessageId(int id) { highlightMessageId = id; } public boolean isThreadChat() { return threadMessageObject != null; } public boolean isReplyChatComment() { return threadMessageObject != null && isComments; } private void updateVisibleRows() { if (chatListView == null) { return; } int lastVisibleItem = RecyclerView.NO_POSITION; int top = 0; if (!wasManualScroll && unreadMessageObject != null) { int n = chatListView.getChildCount(); for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == unreadMessageObject) { int unreadMessageIndex = messages.indexOf(unreadMessageObject); if (unreadMessageIndex >= 0) { lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject); top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom(); } break; } } } int count = chatListView.getChildCount(); MessageObject editingMessageObject = chatActivityEnterView != null ? chatActivityEnterView.getEditingMessageObject() : null; long linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) view; MessageObject messageObject = cell.getMessageObject(); boolean disableSelection = false; boolean selected = false; if (actionBar.isActionModeShowed() || reportType >= 0) { cell.setCheckBoxVisible(threadMessageObjects == null || !threadMessageObjects.contains(messageObject), true); int idx = messageObject.getDialogId() == dialog_id ? 0 : 1; if (selectedMessagesIds[idx].indexOfKey(messageObject.getId()) >= 0) { setCellSelectionBackground(messageObject, cell, idx, true); selected = true; } else { cell.setDrawSelectionBackground(false); cell.setChecked(false, false, true); } disableSelection = true; } else { cell.setDrawSelectionBackground(false); cell.setCheckBoxVisible(false, true); cell.setChecked(false, false, true); } if (!cell.getMessageObject().deleted || cell.linkedChatId != linkedChatId) { cell.setIsUpdating(true); cell.linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; cell.setMessageObject(cell.getMessageObject(), cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop()); cell.setIsUpdating(false); } if (cell != scrimView) { cell.setCheckPressed(!disableSelection, disableSelection && selected); } cell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageObject != null && messageObject.getId() == highlightMessageId); if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && getMediaDataController().isMessageFound(messageObject.getId(), messageObject.getDialogId() == mergeDialogId) && getMediaDataController().getLastSearchQuery() != null) { cell.setHighlightedText(getMediaDataController().getLastSearchQuery()); } else { cell.setHighlightedText(null); } cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) view; cell.setMessageObject(cell.getMessageObject()); cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } } if (lastVisibleItem != RecyclerView.NO_POSITION) { // chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top); } } private void checkEditTimer() { if (chatActivityEnterView == null) { return; } MessageObject messageObject = chatActivityEnterView.getEditingMessageObject(); if (messageObject == null || messageObject.scheduled) { return; } if (currentUser != null && currentUser.self) { return; } int dt = messageObject.canEditMessageAnytime(currentChat) ? 6 * 60 : getMessagesController().maxEditTime + 5 * 60 - Math.abs(getConnectionsManager().getCurrentTime() - messageObject.messageOwner.date); if (dt > 0) { if (dt <= 5 * 60) { replyObjectTextView.setText(LocaleController.formatString("TimeToEdit", R.string.TimeToEdit, AndroidUtilities.formatShortDuration(dt))); } AndroidUtilities.runOnUIThread(this::checkEditTimer, 1000); } else { chatActivityEnterView.onEditTimeExpired(); replyObjectTextView.setText(LocaleController.formatString("TimeToEditExpired", R.string.TimeToEditExpired)); } } private ArrayList createVoiceMessagesPlaylist(MessageObject startMessageObject, boolean playingUnreadMedia) { ArrayList messageObjects = new ArrayList<>(); messageObjects.add(startMessageObject); int messageId = startMessageObject.getId(); long startDialogId = startMessageObject.getDialogId(); if (messageId != 0) { boolean started = false; for (int a = messages.size() - 1; a >= 0; a--) { MessageObject messageObject = messages.get(a); if (messageObject.getDialogId() == mergeDialogId && startMessageObject.getDialogId() != mergeDialogId) { continue; } if ((currentEncryptedChat == null && messageObject.getId() > messageId || currentEncryptedChat != null && messageObject.getId() < messageId) && (messageObject.isVoice() || messageObject.isRoundVideo()) && (!playingUnreadMedia || messageObject.isContentUnread() && !messageObject.isOut())) { messageObjects.add(messageObject); } } } return messageObjects; } private void alertUserOpenError(MessageObject message) { if (getParentActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); if (message.type == 3) { builder.setMessage(LocaleController.getString("NoPlayerInstalled", R.string.NoPlayerInstalled)); } else { builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type)); } showDialog(builder.create()); } private void openSearchWithText(String text) { if (!actionBar.isSearchFieldVisible()) { AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, false, 0.95f, true); if (headerItem != null) { headerItem.setVisibility(View.GONE); } if (attachItem != null) { attachItem.setVisibility(View.GONE); } if (editTextItem != null) { editTextItem.setVisibility(View.GONE); } if (threadMessageId == 0 && searchItem != null) { searchItem.setVisibility(View.VISIBLE); } if (searchIconItem != null && showSearchAsIcon) { searchIconItem.setVisibility(View.GONE); } if (audioCallIconItem != null && showAudioCallAsIcon) { audioCallIconItem.setVisibility(View.GONE); } searchItemVisible = true; updateSearchButtons(0, 0, -1); updateBottomOverlay(); } if (threadMessageId == 0 && !UserObject.isReplyUser(currentUser)) { openSearchKeyboard = text == null; if (searchItem != null) { searchItem.openSearch(openSearchKeyboard); } } if (text != null) { if (searchItem != null) { searchItem.setSearchFieldText(text, false); } getMediaDataController().searchMessagesInChat(text, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); } updatePinnedMessageView(true); } @Override public void didSelectLocation(TLRPC.MessageMedia location, int locationType, boolean notify, int scheduleDate) { getSendMessagesHelper().sendMessage(location, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate); if (chatMode == 0) { moveScrollToLastMessage(false); } if (locationType == LocationActivity.LOCATION_TYPE_SEND || locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { afterMessageSend(); } if (paused) { scrollToTopOnResume = true; } } public boolean isEditingMessageMedia() { return chatAttachAlert != null && chatAttachAlert.getEditingMessageObject() != null; } public boolean isSecretChat() { return currentEncryptedChat != null; } public boolean canScheduleMessage() { return currentEncryptedChat == null && (bottomOverlayChat == null || bottomOverlayChat.getVisibility() != View.VISIBLE) && !isThreadChat(); } public boolean isInScheduleMode() { return chatMode == MODE_SCHEDULED; } public int getChatMode() { return chatMode; } public MessageObject getThreadMessage() { return threadMessageObject; } public MessageObject getReplyMessage() { return replyingMessageObject; } public int getThreadId() { return threadMessageId; } public long getInlineReturn() { return inlineReturn; } public TLRPC.User getCurrentUser() { return currentUser; } public TLRPC.Chat getCurrentChat() { return currentChat; } public boolean allowGroupPhotos() { return !isEditingMessageMedia(); } public TLRPC.EncryptedChat getCurrentEncryptedChat() { return currentEncryptedChat; } public TLRPC.ChatFull getCurrentChatInfo() { return chatInfo; } public ChatObject.Call getGroupCall() { return chatMode == 0 && groupCall != null && groupCall.call instanceof TLRPC.TL_groupCall ? groupCall : null; } public TLRPC.UserFull getCurrentUserInfo() { return userInfo; } public void sendAudio(ArrayList audios, CharSequence caption, boolean notify, int scheduleDate) { fillEditingMediaWithCaption(caption, null); SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, caption != null ? caption : null, dialog_id, replyingMessageObject, getThreadMessage(), editingMessageObject, notify, scheduleDate); afterMessageSend(); } public void sendContact(TLRPC.User user, boolean notify, int scheduleDate) { getSendMessagesHelper().sendMessage(user, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate); afterMessageSend(); } public void sendPoll(TLRPC.TL_messageMediaPoll poll, HashMap params, boolean notify, int scheduleDate) { getSendMessagesHelper().sendMessage(poll, dialog_id, replyingMessageObject, getThreadMessage(), null, params, notify, scheduleDate); afterMessageSend(); } public void sendMedia(MediaController.PhotoEntry photoEntry, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { if (photoEntry == null) { return; } fillEditingMediaWithCaption(photoEntry.caption, photoEntry.entities); if (photoEntry.isVideo) { if (videoEditedInfo != null) { SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument); } else { SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument); } } else { if (photoEntry.imagePath != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument); } else if (photoEntry.path != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument); } } afterMessageSend(); } public void showOpenGameAlert(final TLRPC.TL_game game, final MessageObject messageObject, final String urlStr, boolean ask, final long uid) { TLRPC.User user = getMessagesController().getUser(uid); if (ask) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); String name; if (user != null) { name = ContactsController.formatName(user.first_name, user.last_name); } else { name = ""; } builder.setMessage(LocaleController.formatString("BotPermissionGameAlert", R.string.BotPermissionGameAlert, name)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { showOpenGameAlert(game, messageObject, urlStr, false, uid); MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("askgame_" + uid, false).commit(); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } else { if (Build.VERSION.SDK_INT >= 21 && !AndroidUtilities.isTablet() && WebviewActivity.supportWebview()) { if (parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) == this) { presentFragment(new WebviewActivity(urlStr, user != null && !TextUtils.isEmpty(user.username) ? user.username : "", game.title, game.short_name, messageObject)); } } else { WebviewActivity.openGameInBrowser(urlStr, messageObject, getParentActivity(), game.short_name, user != null && user.username != null ? user.username : ""); } } } private int commentLoadingGuid; private int commentMessagesLoadingGuid; private int commentRequestId; private int commentMessagesRequestId; private int commentLoadingMessageId; private TLRPC.TL_messages_discussionMessage savedDiscussionMessage; private TLRPC.messages_Messages savedHistory; private boolean savedNoHistory; private boolean savedNoDiscussion; private void processLoadedDiscussionMessage(boolean noDiscussion, TLRPC.TL_messages_discussionMessage discussionMessage, boolean noHistory, TLRPC.messages_Messages history, int maxReadId, MessageObject fallbackMessage, TLRPC.TL_messages_getDiscussionMessage req, TLRPC.Chat originalChat, int highlightMsgId, MessageObject originalMessage) { final int thisCommentLoadingMessageId = commentLoadingMessageId; if (history != null) { if (maxReadId != 1 && maxReadId != 0 && maxReadId != discussionMessage.read_inbox_max_id && highlightMsgId <= 0) { history = null; } else if (!history.messages.isEmpty() && discussionMessage != null && !discussionMessage.messages.isEmpty()) { TLRPC.Message message = history.messages.get(0); int replyId = message != null && message.reply_to != null ? (message.reply_to.reply_to_top_id != 0 ? message.reply_to.reply_to_top_id : message.reply_to.reply_to_msg_id) : 0; if (replyId != discussionMessage.messages.get(discussionMessage.messages.size() - 1).id) { history = null; } } if (BuildVars.LOGS_ENABLED) { FileLog.d("processLoadedDiscussionMessage reset history"); } } ArrayList arrayList = new ArrayList<>(); if (discussionMessage != null && discussionMessage.messages != null) { for (int a = 0, N = discussionMessage.messages.size(); a < N; a++) { TLRPC.Message message = discussionMessage.messages.get(a); if (message instanceof TLRPC.TL_messageEmpty) { continue; } message.isThreadMessage = true; arrayList.add(new MessageObject(UserConfig.selectedAccount, message, true, true)); } } if (!arrayList.isEmpty()) { Bundle args = new Bundle(); long dialogId = arrayList.get(0).getDialogId(); args.putLong("chat_id", -dialogId); args.putInt("message_id", Math.max(1, discussionMessage.read_inbox_max_id)); args.putInt("unread_count", discussionMessage.unread_count); args.putBoolean("historyPreloaded", history != null); ChatActivity chatActivity = new ChatActivity(args); chatActivity.setThreadMessages(arrayList, originalChat, req.msg_id, discussionMessage.read_inbox_max_id, discussionMessage.read_outbox_max_id); if (highlightMsgId != 0) { chatActivity.highlightMessageId = highlightMsgId; } if (originalMessage != null && originalMessage.messageOwner.replies != null && chatActivity.threadMessageObject.messageOwner.replies != null) { originalMessage.messageOwner.replies.replies = chatActivity.threadMessageObject.messageOwner.replies.replies; } if (originalMessage != null && originalMessage.messageOwner.reactions != null) { chatActivity.threadMessageObject.messageOwner.reactions = originalMessage.messageOwner.reactions; } final boolean[] chatOpened = new boolean[] { false }; Runnable openCommentsChat = () -> { if (chatOpened[0] || thisCommentLoadingMessageId != commentLoadingMessageId || !isFullyVisible || isFinishing()) { return; } chatOpened[0] = true; AndroidUtilities.runOnUIThread(() -> { commentLoadingMessageId = 0; chatListView.invalidateViews(); }, 200); presentFragment(chatActivity); if (isKeyboardVisible() && !chatActivity.hideKeyboardOnShow()) { chatActivity.chatActivityEnterView.getEditField().requestFocus(); } }; if (history != null) { int fnid = 0; if (!history.messages.isEmpty()) { for (int a = history.messages.size() - 1; a >= 0; a--) { TLRPC.Message message = history.messages.get(a); if (message.id > maxReadId && !message.out) { fnid = message.id; break; } } } TLRPC.messages_Messages historyFinal = history; int fnidFinal = fnid; final int commentsClassGuid = chatActivity.getClassGuid(); final NotificationCenter.NotificationCenterDelegate observer = new NotificationCenter.NotificationCenterDelegate() { @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.messagesDidLoad && (Integer) args[10] == commentsClassGuid) { openCommentsChat.run(); AndroidUtilities.runOnUIThread(() -> { chatActivity.didReceivedNotification(id, account, args); }, 50); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDidLoad); } } }; NotificationCenter.getInstance(currentAccount).addObserver(observer, NotificationCenter.messagesDidLoad); Utilities.stageQueue.postRunnable(() -> { getMessagesController().processLoadedMessages(historyFinal, historyFinal.messages.size(), dialogId, 0, 30, (highlightMsgId > 0 ? highlightMsgId : maxReadId), 0, false, commentsClassGuid, fnidFinal, 0, 0, 0, (highlightMsgId > 0 ? 3 : 2), true, 0, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0, true); }); } else { openCommentsChat.run(); } } else { commentLoadingMessageId = 0; chatListView.invalidateViews(); if (fallbackMessage != null) { openOriginalReplyChat(fallbackMessage); } else { if (getParentActivity() != null) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("ChannelPostDeleted", R.string.ChannelPostDeleted), themeDelegate).show(); } } } } private void openDiscussionMessageChat(long chatId, MessageObject originalMessage, int messageId, long linkedChatId, int maxReadId, int highlightMsgId, MessageObject fallbackMessage) { TLRPC.Chat chat = getMessagesController().getChat(chatId); TLRPC.TL_messages_getDiscussionMessage req = new TLRPC.TL_messages_getDiscussionMessage(); req.peer = MessagesController.getInputPeer(chat); req.msg_id = messageId; if (BuildVars.LOGS_ENABLED) { FileLog.d("getDiscussionMessage chat = " + chat.id + " msg_id = " + messageId); } commentLoadingMessageId = 0; savedDiscussionMessage = null; savedNoDiscussion = false; savedNoHistory = false; savedHistory = null; if (chatListView != null) { chatListView.invalidateViews(); } if (commentMessagesRequestId != -1) { getConnectionsManager().cancelRequest(commentMessagesRequestId, false); } if (commentRequestId != -1) { getConnectionsManager().cancelRequest(commentRequestId, false); } commentLoadingMessageId = fallbackMessage != null ? fallbackMessage.getId() : messageId; if (chatListView != null) { chatListView.invalidateViews(); } final int guid1 = ++commentLoadingGuid; commentRequestId = getConnectionsManager().sendRequest(req, (response, error) -> { Runnable runnable = () -> { if (guid1 != commentLoadingGuid) { return; } int maxReadId1 = maxReadId; long linkedChatId1 = linkedChatId; commentRequestId = -1; if (response instanceof TLRPC.TL_messages_discussionMessage) { savedDiscussionMessage = (TLRPC.TL_messages_discussionMessage) response; getMessagesController().putUsers(savedDiscussionMessage.users, false); getMessagesController().putChats(savedDiscussionMessage.chats, false); } else { savedNoDiscussion = true; } ArrayList msgs = new ArrayList<>(); if (savedDiscussionMessage != null && savedDiscussionMessage.messages != null) { for (int i = 0; i < savedDiscussionMessage.messages.size(); ++i) { TLRPC.Message message = savedDiscussionMessage.messages.get(i); if (message instanceof TLRPC.TL_messageEmpty) { continue; } msgs.add(message); } } if (msgs.size() > 0) { TLRPC.Message message = msgs.get(0); TLRPC.TL_messages_getReplies getReplies = new TLRPC.TL_messages_getReplies(); getReplies.peer = getMessagesController().getInputPeer(message.peer_id); getReplies.msg_id = message.id; getReplies.offset_date = 0; getReplies.limit = 30; if (highlightMsgId > 0) { getReplies.offset_id = highlightMsgId; getReplies.add_offset = -getReplies.limit / 2; } else { getReplies.offset_id = maxReadId1 == 0 ? 1 : maxReadId1; getReplies.add_offset = -getReplies.limit + 10; } final int guid2 = ++commentMessagesLoadingGuid; commentMessagesRequestId = getConnectionsManager().sendRequest(getReplies, (response2, error2) -> { AndroidUtilities.runOnUIThread(() -> doOnIdle(() -> { if (guid2 != commentMessagesLoadingGuid) { return; } commentMessagesRequestId = -1; if (response2 != null) { savedHistory = (TLRPC.messages_Messages) response2; } else { if ("CHANNEL_PRIVATE".equals(error2.text)) { if (getParentActivity() != null) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("JoinByPeekChannelText", R.string.JoinByPeekChannelText)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); showDialog(builder.create()); } commentLoadingMessageId = 0; chatListView.invalidateViews(); return; } savedNoHistory = true; } processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId1, fallbackMessage, req, chat, highlightMsgId, originalMessage); })); }); } else { savedNoHistory = true; processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId1, fallbackMessage, req, chat, highlightMsgId, originalMessage); } }; AndroidUtilities.runOnUIThread(() -> doOnIdle(runnable)); }); getConnectionsManager().bindRequestToGuid(commentRequestId, classGuid); } private void openOriginalReplyChat(MessageObject messageObject) { if (UserObject.isUserSelf(currentUser) && messageObject.messageOwner.fwd_from.saved_from_peer.user_id == currentUser.id) { scrollToMessageId(messageObject.messageOwner.fwd_from.saved_from_msg_id, messageObject.getId(), true, 0, true, 0); return; } Bundle args = new Bundle(); if (messageObject.messageOwner.fwd_from.saved_from_peer.channel_id != 0) { args.putLong("chat_id", messageObject.messageOwner.fwd_from.saved_from_peer.channel_id); } else if (messageObject.messageOwner.fwd_from.saved_from_peer.chat_id != 0) { args.putLong("chat_id", messageObject.messageOwner.fwd_from.saved_from_peer.chat_id); } else if (messageObject.messageOwner.fwd_from.saved_from_peer.user_id != 0) { args.putLong("user_id", messageObject.messageOwner.fwd_from.saved_from_peer.user_id); } args.putInt("message_id", messageObject.messageOwner.fwd_from.saved_from_msg_id); if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { presentFragment(new ChatActivity(args)); } } public void showRequestUrlAlert(final TLRPC.TL_urlAuthResultRequest request, TLRPC.TL_messages_requestUrlAuth buttonReq, String url, boolean ask) { if (getParentActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("OpenUrlTitle", R.string.OpenUrlTitle)); String format = LocaleController.getString("OpenUrlAlert2", R.string.OpenUrlAlert2); int index = format.indexOf("%"); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format(format, url)); if (index >= 0) { stringBuilder.setSpan(new URLSpan(url), index, index + url.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } builder.setMessage(stringBuilder); builder.setMessageTextViewClickable(false); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); CheckBoxCell[] cells = new CheckBoxCell[2]; LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(LinearLayout.VERTICAL); TLRPC.User selfUser = getUserConfig().getCurrentUser(); for (int a = 0; a < (request.request_write_access ? 2 : 1); a++) { cells[a] = new CheckBoxCell(getParentActivity(), 5, themeDelegate); cells[a].setBackgroundDrawable(Theme.getSelectorDrawable(false)); cells[a].setMultiline(true); cells[a].setTag(a); if (a == 0) { stringBuilder = AndroidUtilities.replaceTags(LocaleController.formatString("OpenUrlOption1", R.string.OpenUrlOption1, request.domain, ContactsController.formatName(selfUser.first_name, selfUser.last_name))); index = TextUtils.indexOf(stringBuilder, request.domain); if (index >= 0) { stringBuilder.setSpan(new URLSpan(""), index, index + request.domain.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } cells[a].setText(stringBuilder, "", true, false); } else { cells[a].setText(AndroidUtilities.replaceTags(LocaleController.formatString("OpenUrlOption2", R.string.OpenUrlOption2, UserObject.getFirstName(request.bot))), "", true, false); } cells[a].setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); linearLayout.addView(cells[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); cells[a].setOnClickListener(v -> { if (!v.isEnabled()) { return; } Integer num = (Integer) v.getTag(); cells[num].setChecked(!cells[num].isChecked(), true); if (num == 0 && cells[1] != null) { if (cells[num].isChecked()) { cells[1].setEnabled(true); } else { cells[1].setChecked(false, true); cells[1].setEnabled(false); } } }); } builder.setCustomViewOffset(12); builder.setView(linearLayout); builder.setPositiveButton(LocaleController.getString("Open", R.string.Open), (dialogInterface, i) -> { if (!cells[0].isChecked()) { Browser.openUrl(getParentActivity(), url, false); } else { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3, themeDelegate)}; TLRPC.TL_messages_acceptUrlAuth req = new TLRPC.TL_messages_acceptUrlAuth(); if (buttonReq.url != null) { req.url = buttonReq.url; req.flags |= 4; } else { req.button_id = buttonReq.button_id; req.msg_id = buttonReq.msg_id; req.peer = buttonReq.peer; req.flags |= 2; } if (request.request_write_access) { req.write_allowed = cells[1].isChecked(); } try { progressDialog[0].dismiss(); } catch (Throwable ignore) { } progressDialog[0] = null; int requestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_urlAuthResultAccepted) { TLRPC.TL_urlAuthResultAccepted res = (TLRPC.TL_urlAuthResultAccepted) response; Browser.openUrl(getParentActivity(), res.url, false); } else if (response instanceof TLRPC.TL_urlAuthResultDefault) { Browser.openUrl(getParentActivity(), url, false); } else if (buttonReq.url != null) { AlertsCreator.showOpenUrlAlert(ChatActivity.this, buttonReq.url, false, ask, themeDelegate); } })); AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } progressDialog[0].setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(requestId, true)); showDialog(progressDialog[0]); }, 500); } }); showDialog(builder.create()); } private void removeMessageObject(MessageObject messageObject) { int index = messages.indexOf(messageObject); if (index == -1) { return; } messages.remove(index); if (chatAdapter != null) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } } public void openVCard(TLRPC.User user, String vcard, String first_name, String last_name) { try { File f = AndroidUtilities.getSharingDirectory(); f.mkdirs(); f = new File(f, "vcard.vcf"); BufferedWriter writer = new BufferedWriter(new FileWriter(f)); writer.write(vcard); writer.close(); showDialog(new PhonebookShareAlert(this, null, user, null, f, first_name, last_name, themeDelegate)); } catch (Exception e) { FileLog.e(e); } } private void setCellSelectionBackground(MessageObject message, ChatMessageCell messageCell, int idx, boolean animated) { MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { boolean hasUnselected = false; for (int a = 0; a < groupedMessages.messages.size(); a++) { if (selectedMessagesIds[idx].indexOfKey(groupedMessages.messages.get(a).getId()) < 0) { hasUnselected = true; break; } } if (!hasUnselected) { groupedMessages = null; } } messageCell.setDrawSelectionBackground(groupedMessages == null); messageCell.setChecked(true, groupedMessages == null, animated); } private void openClickableLink(CharacterStyle url, String str, boolean longPress, final ChatMessageCell cell, final MessageObject messageObject) { if (longPress) { BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, themeDelegate); int timestamp = -1; if (str.startsWith("video?")) { timestamp = Utilities.parseInt(str); } if (timestamp >= 0) { builder.setTitle(AndroidUtilities.formatDuration(timestamp, false)); } else { String formattedUrl = str; try { formattedUrl = URLDecoder.decode(str.replaceAll("\\+", "%2b"), "UTF-8"); } catch (Exception e) { FileLog.e(e); } builder.setTitle(formattedUrl); builder.setTitleMultipleLines(true); } final int finalTimestamp = timestamp; boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.noforwards); builder.setItems(noforwards ? new CharSequence[] {LocaleController.getString("Open", R.string.Open)} : new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { if (which == 0) { if (str.startsWith("video?")) { didPressMessageUrl(url, false, messageObject, cell); } else { openClickableLink(url, str, false, cell, messageObject); } } else if (which == 1) { if (str.startsWith("video?") && messageObject != null && !messageObject.scheduled) { MessageObject messageObject1 = messageObject; boolean isMedia = messageObject.isVideo() || messageObject.isRoundVideo() || messageObject.isVoice() || messageObject.isMusic(); if (!isMedia && messageObject.replyMessageObject != null) { messageObject1 = messageObject.replyMessageObject; } long dialogId = messageObject1.getDialogId(); int messageId = messageObject1.getId(); String link = null; if (messageObject1.messageOwner.fwd_from != null) { if (messageObject1.messageOwner.fwd_from.saved_from_peer != null) { dialogId = MessageObject.getPeerId(messageObject1.messageOwner.fwd_from.saved_from_peer); messageId = messageObject1.messageOwner.fwd_from.saved_from_msg_id; } else if (messageObject1.messageOwner.fwd_from.from_id != null) { dialogId = MessageObject.getPeerId(messageObject1.messageOwner.fwd_from.from_id); messageId = messageObject1.messageOwner.fwd_from.channel_post; } } if (DialogObject.isChatDialog(dialogId)) { TLRPC.Chat currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); if (currentChat != null && currentChat.username != null) { link = "https://t.me/" + currentChat.username + "/" + messageId + "?t=" + finalTimestamp; } } else { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); if (user != null && user.username != null) { link = "https://t.me/" + user.username + "/" + messageId + "?t=" + finalTimestamp; } } if (link == null) { return; } AndroidUtilities.addToClipboard(link); } else { AndroidUtilities.addToClipboard(str); } if (str.startsWith("@")) { undoView.showWithAction(0, UndoView.ACTION_USERNAME_COPIED, null); } else if (str.startsWith("#") || str.startsWith("$")) { undoView.showWithAction(0, UndoView.ACTION_HASHTAG_COPIED, null); } else { undoView.showWithAction(0, UndoView.ACTION_LINK_COPIED, null); } } }); builder.setOnPreDismissListener(di -> { if (cell != null) { cell.resetPressedLink(-1); } }); showDialog(builder.create()); } else { if (str.startsWith("@")) { String username = str.substring(1).toLowerCase(); if (currentChat != null && !TextUtils.isEmpty(currentChat.username) && username.equals(currentChat.username.toLowerCase()) || currentUser != null && !TextUtils.isEmpty(currentUser.username) && username.equals(currentUser.username.toLowerCase())) { Bundle args = new Bundle(); if (currentChat != null) { args.putLong("chat_id", currentChat.id); } else if (currentUser != null) { args.putLong("user_id", currentUser.id); if (currentEncryptedChat != null) { args.putLong("dialog_id", dialog_id); } } ProfileActivity fragment = new ProfileActivity(args, avatarContainer.getSharedMediaPreloader()); fragment.setPlayProfileAnimation(1); fragment.setChatInfo(chatInfo); fragment.setUserInfo(userInfo); presentFragment(fragment); } else { getMessagesController().openByUserName(username, ChatActivity.this, 0); } } else if (str.startsWith("#") || str.startsWith("$")) { if (ChatObject.isChannel(currentChat)) { if (chatMode == MODE_SCHEDULED || chatMode == MODE_PINNED) { chatActivityDelegate.openSearch(str); finishFragment(); } else { openSearchWithText(str); } } else { DialogsActivity fragment = new DialogsActivity(null); fragment.setSearchString(str); presentFragment(fragment); } } else { processExternalUrl(0, str, false); } } } private void processExternalUrl(int type, String url, boolean forceAlert) { try { Uri uri = Uri.parse(url); String host = uri.getHost() != null ? uri.getHost().toLowerCase() : ""; if ((currentEncryptedChat == null || getMessagesController().secretWebpagePreview == 1) && getMessagesController().authDomains.contains(host)) { getSendMessagesHelper().requestUrlAuth(url, this, type == 0 || type == 2); return; } } catch (Exception e) { FileLog.e(e); } if (forceAlert || AndroidUtilities.shouldShowUrlInAlert(url)) { if (type == 0 || type == 2) { AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, true, true, themeDelegate); } else if (type == 1) { AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, true, false, themeDelegate); } } else { if (type == 0) { Browser.openUrl(getParentActivity(), url); } else if (type == 1) { Browser.openUrl(getParentActivity(), url, inlineReturn == 0, false); } else if (type == 2) { Browser.openUrl(getParentActivity(), url, inlineReturn == 0); } } } private void didPressMessageUrl(CharacterStyle url, boolean longPress, MessageObject messageObject, ChatMessageCell cell) { if (url == null || getParentActivity() == null) { return; } boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.noforwards); if (url instanceof URLSpanMono) { if (!noforwards) { ((URLSpanMono) url).copyToClipboard(); getUndoView().showWithAction(0, UndoView.ACTION_TEXT_COPIED, null); } if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (url instanceof URLSpanUserMention) { TLRPC.User user = getMessagesController().getUser(Utilities.parseLong(((URLSpanUserMention) url).getURL())); if (user != null) { MessagesController.openChatOrProfileWith(user, null, ChatActivity.this, 0, false); } if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (url instanceof URLSpanNoUnderline) { String str = ((URLSpanNoUnderline) url).getURL(); if (messageObject != null && str.startsWith("/")) { if (URLSpanBotCommand.enabled) { chatActivityEnterView.setCommand(messageObject, str, longPress, currentChat != null && currentChat.megagroup); if (!longPress && chatActivityEnterView.getFieldText() == null) { hideFieldPanel(false); } } if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (messageObject != null && str.startsWith("video") && !longPress) { int seekTime = Utilities.parseInt(str); TLRPC.WebPage webPage; if (messageObject.isYouTubeVideo()) { webPage = messageObject.messageOwner.media.webpage; } else if (messageObject.replyMessageObject != null && messageObject.replyMessageObject.isYouTubeVideo()) { webPage = messageObject.replyMessageObject.messageOwner.media.webpage; messageObject = messageObject.replyMessageObject; } else { webPage = null; } if (webPage != null) { EmbedBottomSheet.show(getParentActivity(), messageObject, photoViewerProvider, webPage.site_name, webPage.title, webPage.url, webPage.embed_url, webPage.embed_width, webPage.embed_height, seekTime, isKeyboardVisible()); } else { if (!messageObject.isVideo() && messageObject.replyMessageObject != null) { MessageObject obj = messagesDict[messageObject.replyMessageObject.getDialogId() == dialog_id ? 0 : 1].get(messageObject.replyMessageObject.getId()); cell = null; if (obj == null) { messageObject = messageObject.replyMessageObject; } else { messageObject = obj; } } messageObject.forceSeekTo = seekTime / (float) messageObject.getDuration(); openPhotoViewerForMessage(cell, messageObject); } } else if (messageObject != null && str.startsWith("audio")) { int seekTime = Utilities.parseInt(str); if (!messageObject.isMusic() && messageObject.replyMessageObject != null) { messageObject = messagesDict[messageObject.replyMessageObject.getDialogId() == dialog_id ? 0 : 1].get(messageObject.replyMessageObject.getId()); } float progress = seekTime / (float) messageObject.getDuration(); MediaController mediaController = getMediaController(); if (mediaController.isPlayingMessage(messageObject)) { messageObject.audioProgress = progress; mediaController.seekToProgress(messageObject, progress); if (mediaController.isMessagePaused()) { mediaController.playMessage(messageObject); } } else { messageObject.forceSeekTo = seekTime / (float) messageObject.getDuration(); mediaController.playMessage(messageObject); } if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (str.startsWith("card:")) { final ChatMessageCell finalCell = cell; String number = str.substring(5); final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3, themeDelegate)}; TLRPC.TL_payments_getBankCardData req = new TLRPC.TL_payments_getBankCardData(); req.number = number; int requestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { try { progressDialog[0].dismiss(); } catch (Throwable ignore) { } progressDialog[0] = null; if (response instanceof TLRPC.TL_payments_bankCardData) { if (getParentActivity() == null) { return; } TLRPC.TL_payments_bankCardData data = (TLRPC.TL_payments_bankCardData) response; BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, themeDelegate); ArrayList arrayList = new ArrayList<>(); for (int a = 0, N = data.open_urls.size(); a < N; a++) { arrayList.add(data.open_urls.get(a).name); } arrayList.add(LocaleController.getString("CopyCardNumber", R.string.CopyCardNumber)); builder.setTitle(data.title); builder.setItems(arrayList.toArray(new CharSequence[0]), (dialog, which) -> { if (which < data.open_urls.size()) { Browser.openUrl(getParentActivity(), data.open_urls.get(which).url, inlineReturn == 0, false); } else { AndroidUtilities.addToClipboard(number); Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("CardNumberCopied", R.string.CardNumberCopied), Toast.LENGTH_SHORT).show(); } }); builder.setOnPreDismissListener(di -> { if (finalCell != null) { finalCell.resetPressedLink(-1); } }); showDialog(builder.create()); } else if (finalCell != null) { finalCell.resetPressedLink(-1); } }), null, null, 0, getMessagesController().webFileDatacenterId, ConnectionsManager.ConnectionTypeGeneric, true); AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } progressDialog[0].setOnCancelListener(dialog -> { getConnectionsManager().cancelRequest(requestId, true); finalCell.resetPressedLink(-1); }); showDialog(progressDialog[0]); }, 500); } else { openClickableLink(url, str, longPress, cell, messageObject); } } else { final String urlFinal = ((URLSpan) url).getURL(); if (longPress) { final ChatMessageCell finalCell = cell; BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, themeDelegate); String formattedUrl = urlFinal; try { formattedUrl = URLDecoder.decode(urlFinal.replaceAll("\\+", "%2b"), "UTF-8"); } catch (Exception e) { FileLog.e(e); } builder.setTitle(formattedUrl); builder.setTitleMultipleLines(true); builder.setItems(noforwards ? new CharSequence[] {LocaleController.getString("Open", R.string.Open)} : new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { if (which == 0) { processExternalUrl(1, urlFinal, false); } else if (which == 1) { String url1 = urlFinal; boolean tel = false; boolean mail = false; if (url1.startsWith("mailto:")) { url1 = url1.substring(7); mail = true; } else if (url1.startsWith("tel:")) { url1 = url1.substring(4); tel = true; } AndroidUtilities.addToClipboard(url1); if (mail) { undoView.showWithAction(0, UndoView.ACTION_EMAIL_COPIED, null); } else if (tel) { undoView.showWithAction(0, UndoView.ACTION_PHONE_COPIED, null); } else { undoView.showWithAction(0, UndoView.ACTION_LINK_COPIED, null); } } }); builder.setOnPreDismissListener(di -> { if (finalCell != null) { finalCell.resetPressedLink(-1); } }); showDialog(builder.create()); } else { boolean forceAlert = url instanceof URLSpanReplacement; if (url instanceof URLSpanReplacement && (urlFinal == null || !urlFinal.startsWith("mailto:")) || AndroidUtilities.shouldShowUrlInAlert(urlFinal)) { if (openLinkInternally(urlFinal, messageObject != null ? messageObject.getId() : 0)) { return; } forceAlert = true; } else { if (messageObject != null && messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { String lowerUrl = urlFinal.toLowerCase(); String lowerUrl2 = messageObject.messageOwner.media.webpage.url.toLowerCase(); if ((lowerUrl.contains("telegram.org/blog") || Browser.isTelegraphUrl(lowerUrl, false) || lowerUrl.contains("t.me/iv")) && (lowerUrl.contains(lowerUrl2) || lowerUrl2.contains(lowerUrl))) { ArticleViewer.getInstance().setParentActivity(getParentActivity(), ChatActivity.this); ArticleViewer.getInstance().open(messageObject); return; } } if (openLinkInternally(urlFinal, messageObject != null ? messageObject.getId() : 0)) { return; } } if (Browser.urlMustNotHaveConfirmation(urlFinal)) { forceAlert = false; } processExternalUrl(2, urlFinal, forceAlert); } } } void openPhotoViewerForMessage(ChatMessageCell cell, MessageObject message) { if (cell == null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (child instanceof ChatMessageCell) { ChatMessageCell messageCell = (ChatMessageCell) child; if (messageCell.getMessageObject().equals(message)) { cell = messageCell; break; } } } } if (message.isVideo()) { sendSecretMessageRead(message, true); } PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); MessageObject playingObject = MediaController.getInstance().getPlayingMessageObject(); if (cell != null && playingObject != null && playingObject.isVideo()) { getFileLoader().setLoadingVideoForPlayer(playingObject.getDocument(), false); if (playingObject.equals(message)) { AnimatedFileDrawable animation = cell.getPhotoImage().getAnimation(); if (animation != null && videoTextureView != null && videoPlayerContainer.getTag() != null) { Bitmap bitmap = animation.getAnimatedBitmap(); if (bitmap != null) { try { Bitmap src = videoTextureView.getBitmap(bitmap.getWidth(), bitmap.getHeight()); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(src, 0, 0, null); src.recycle(); } catch (Throwable e) { FileLog.e(e); } } } } MediaController.getInstance().cleanupPlayer(true, true, false, playingObject.equals(message)); } if (chatMode == MODE_SCHEDULED && (message.isVideo() || message.type == 1)) { PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); ArrayList arrayList = new ArrayList<>(); for (int a = 0, N = messages.size(); a < N; a++) { MessageObject m = messages.get(a); if (m.isVideo() || m.type == 1) { arrayList.add(0, m); } } PhotoViewer.getInstance().openPhoto(arrayList, arrayList.indexOf(message), dialog_id, 0, photoViewerProvider); } else { PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider); } hideHints(false); MediaController.getInstance().resetGoingToShowMessageObject(); } private void updateMessageListAccessibilityVisibility() { if (currentEncryptedChat != null) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { chatListView.setImportantForAccessibility(mentionContainer != null && mentionContainer.isOpen() || (scrimPopupWindow != null && scrimPopupWindow.isShowing()) ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); } } private void markSponsoredAsRead(MessageObject object) { if (!object.isSponsored() || object.viewsReloaded) { return; } object.viewsReloaded = true; TLRPC.TL_channels_viewSponsoredMessage req = new TLRPC.TL_channels_viewSponsoredMessage(); req.channel = MessagesController.getInputChannel(currentChat); req.random_id = object.sponsoredId; getConnectionsManager().sendRequest(req, (response, error) -> { }); getMessagesController().markSponsoredAsRead(dialog_id, object); } @Override public boolean canBeginSlide() { return swipeBackEnabled && chatActivityEnterView.swipeToBackEnabled() && pullingDownOffset == 0; } @Override public boolean isSwipeBackEnabled(MotionEvent event) { return swipeBackEnabled; } public class ChatActivityAdapter extends RecyclerAnimationScrollHelper.AnimatableAdapter { private Context mContext; private boolean isBot; private int rowCount; private int botInfoRow = -5; private int botInfoEmptyRow = -5; private int loadingUpRow = -5; private int loadingDownRow = -5; private int messagesStartRow; private int messagesEndRow; public boolean isFrozen; public ArrayList frozenMessages = new ArrayList<>(); public ChatActivityAdapter(Context context) { mContext = context; isBot = currentUser != null && currentUser.bot; setHasStableIds(true); } public void updateRowsSafe() { int prevRowCount = rowCount; int prevBotInfoRow = botInfoRow; int prevLoadingUpRow = loadingUpRow; int prevLoadingDownRow = loadingDownRow; int prevMessagesStartRow = messagesStartRow; int prevMessagesEndRow = messagesEndRow; updateRowsInternal(); if (prevRowCount != rowCount || prevBotInfoRow != botInfoRow || prevLoadingUpRow != loadingUpRow || prevLoadingDownRow != loadingDownRow || prevMessagesStartRow != messagesStartRow || prevMessagesEndRow != messagesEndRow) { notifyDataSetChanged(false); } } private void updateRowsInternal() { rowCount = 0; ArrayList messages = isFrozen ? frozenMessages : ChatActivity.this.messages; if (!messages.isEmpty()) { if ((!forwardEndReached[0] || mergeDialogId != 0 && !forwardEndReached[1]) && !hideForwardEndReached) { loadingDownRow = rowCount++; } else { loadingDownRow = -5; } messagesStartRow = rowCount; rowCount += messages.size(); messagesEndRow = rowCount; if ((UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && chatMode == 0) && endReached[0]) { botInfoRow = rowCount++; } else { botInfoRow = -5; } if (!endReached[0] || mergeDialogId != 0 && !endReached[1]) { loadingUpRow = rowCount++; } else { loadingUpRow = -5; } } else { loadingUpRow = -5; loadingDownRow = -5; messagesStartRow = -5; messagesEndRow = -5; if (UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && chatMode == 0) { botInfoRow = rowCount++; } else { botInfoRow = -5; } } } @Override public int getItemCount() { botInfoEmptyRow = -5; if (clearingHistory) { if (currentUser != null && currentUser.bot && chatMode == 0 && (botInfo.size() > 0 && (botInfo.get(currentUser.id).description != null || botInfo.get(currentUser.id).description_photo != null || botInfo.get(currentUser.id).description_document != null) || UserObject.isReplyUser(currentUser))) { botInfoEmptyRow = 0; return 1; } return 0; } return clearingHistory ? 0 : rowCount; } @Override public long getItemId(int position) { if (clearingHistory) { if (position == botInfoEmptyRow) { return 1; } } ArrayList messages = isFrozen ? frozenMessages : ChatActivity.this.messages; if (position >= messagesStartRow && position < messagesEndRow) { return messages.get(position - messagesStartRow).stableId; } else if (position == botInfoRow || position == botInfoEmptyRow) { return 1; } else if (position == loadingUpRow) { return 2; } else if (position == loadingDownRow) { return 3; } return 4; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = null; if (viewType == 0) { if (!chatMessageCellsCache.isEmpty()) { view = chatMessageCellsCache.get(0); chatMessageCellsCache.remove(0); } else { view = new ChatMessageCell(mContext, true, themeDelegate); } ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.shouldCheckVisibleOnScreen = true; chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { @Override public void didPressHint(ChatMessageCell cell, int type) { if (type == 0) { TLRPC.TL_messageMediaPoll media = (TLRPC.TL_messageMediaPoll) cell.getMessageObject().messageOwner.media; showPollSolution(cell.getMessageObject(), media.results); } else if (type == 1) { MessageObject messageObject = cell.getMessageObject(); if (messageObject.messageOwner.fwd_from == null || TextUtils.isEmpty(messageObject.messageOwner.fwd_from.psa_type)) { return; } CharSequence text = LocaleController.getString("PsaMessageInfo_" + messageObject.messageOwner.fwd_from.psa_type); if (TextUtils.isEmpty(text)) { text = LocaleController.getString("PsaMessageInfoDefault", R.string.PsaMessageInfoDefault); } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(text); MessageObject.addLinks(false, stringBuilder); MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); if (group != null) { for (int a = 0, N = group.posArray.size(); a < N; a++) { MessageObject.GroupedMessagePosition pos = group.posArray.get(a); if ((pos.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { MessageObject m = group.messages.get(a); if (m != messageObject) { messageObject = m; int count = chatListView.getChildCount(); for (int b = 0; b < count; b++) { View view = chatListView.getChildAt(b); if (!(view instanceof ChatMessageCell)) { continue; } ChatMessageCell c = (ChatMessageCell) view; if (messageObject.equals(c.getMessageObject())) { cell = c; } } } break; } } } showInfoHint(messageObject, stringBuilder, 1); } cell.showHintButton(false, true, type); } @Override public boolean shouldDrawThreadProgress(ChatMessageCell cell) { MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); MessageObject message; if (group != null && !group.messages.isEmpty()) { message = group.messages.get(0); } else { message = cell.getMessageObject(); } if (message == null) { return false; } return message.getId() == commentLoadingMessageId; } @Override public void didPressSideButton(ChatMessageCell cell) { if (getParentActivity() == null) { return; } if (chatActivityEnterView != null) { chatActivityEnterView.closeKeyboard(); } MessageObject messageObject = cell.getMessageObject(); if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageObject.getId()); finishFragment(); } else if ((UserObject.isReplyUser(currentUser) || UserObject.isUserSelf(currentUser)) && messageObject.messageOwner.fwd_from.saved_from_peer != null) { if (UserObject.isReplyUser(currentUser) && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_to_top_id != 0) { openDiscussionMessageChat(messageObject.messageOwner.reply_to.reply_to_peer_id.channel_id, null, messageObject.messageOwner.reply_to.reply_to_top_id, 0, -1, messageObject.messageOwner.fwd_from.saved_from_msg_id, messageObject); } else { openOriginalReplyChat(messageObject); } } else { ArrayList arrayList = null; if (messageObject.getGroupId() != 0) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); if (groupedMessages != null) { arrayList = groupedMessages.messages; } } if (arrayList == null) { arrayList = new ArrayList<>(); arrayList.add(messageObject); } showDialog(new ShareAlert(mContext, ChatActivity.this, arrayList, null, null, ChatObject.isChannel(currentChat), null, null, false, false, themeDelegate) { @Override public void dismissInternal() { super.dismissInternal(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { fragmentView.requestLayout(); } } @Override protected void onSend(LongSparseArray dids, int count) { if (dids.size() == 1) { undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count); } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, count, dids.size(), null, null); } } }); AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); fragmentView.requestLayout(); } } @Override public boolean needPlayMessage(MessageObject messageObject) { if (messageObject.isVoice() || messageObject.isRoundVideo()) { boolean result = MediaController.getInstance().playMessage(messageObject); MediaController.getInstance().setVoiceMessagesPlaylist(result ? createVoiceMessagesPlaylist(messageObject, false) : null, false); return result; } else if (messageObject.isMusic()) { return MediaController.getInstance().setPlaylist(messages, messageObject, mergeDialogId); } return false; } @Override public void videoTimerReached() { showNoSoundHint(); } @Override public void didPressTime(ChatMessageCell cell) { undoView.showWithAction(dialog_id, UndoView.ACTION_IMPORT_INFO, null); } @Override public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) { if (chat == null) { return; } if (actionBar.isActionModeShowed() || reportType >= 0) { processRowSelect(cell, true, touchX, touchY); return; } openChat(cell, chat, postId); } @Override public void didPressHiddenForward(ChatMessageCell cell) { if (cell.getMessageObject().isImportedForward()) { didPressTime(cell); return; } showForwardHint(cell); } @Override public void didPressOther(ChatMessageCell cell, float otherX, float otherY) { MessageObject messageObject = cell.getMessageObject(); if (messageObject.type == 16) { if (currentUser != null) { VoIPHelper.startCall(currentUser, messageObject.isVideoCall(), userInfo != null && userInfo.video_calls_available, getParentActivity(), getMessagesController().getUserFull(currentUser.id), getAccountInstance()); } } else { createMenu(cell, true, false, otherX, otherY, messageObject.isMusic()); } } @Override public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { if (actionBar.isActionModeShowed() || reportType >= 0) { processRowSelect(cell, true, touchX, touchY); return; } openProfile(user); } @Override public boolean didLongPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { if (isAvatarPreviewerEnabled()) { final boolean enableMention = currentChat != null && (bottomOverlayChat == null || bottomOverlayChat.getVisibility() != View.VISIBLE) && (bottomOverlay == null || bottomOverlay.getVisibility() != View.VISIBLE); final AvatarPreviewer.MenuItem[] menuItems = new AvatarPreviewer.MenuItem[2 + (enableMention ? 1 : 0)]; menuItems[0] = AvatarPreviewer.MenuItem.OPEN_PROFILE; menuItems[1] = AvatarPreviewer.MenuItem.SEND_MESSAGE; if (enableMention) { menuItems[2] = AvatarPreviewer.MenuItem.MENTION; } final TLRPC.UserFull userFull = getMessagesController().getUserFull(user.id); final AvatarPreviewer.Data data; if (userFull != null) { data = AvatarPreviewer.Data.of(userFull, menuItems); } else { data = AvatarPreviewer.Data.of(user, classGuid, menuItems); } if (AvatarPreviewer.canPreview(data)) { AvatarPreviewer.getInstance().show((ViewGroup) fragmentView, data, item -> { switch (item) { case SEND_MESSAGE: openDialog(cell, user); break; case OPEN_PROFILE: openProfile(user); break; case MENTION: appendMention(user); break; } }); return true; } } return false; } private void appendMention(TLRPC.User user) { if (chatActivityEnterView != null) { SpannableStringBuilder sb; final CharSequence text = chatActivityEnterView.getFieldText(); if (text != null) { sb = new SpannableStringBuilder(text); if (text.charAt(text.length() - 1) != ' ') { sb.append(" "); } } else { sb = new SpannableStringBuilder(); } if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') { sb.append(' '); } if (user.username != null) { sb.append("@").append(user.username).append(" "); } else { String name = UserObject.getFirstName(user, false); Spannable spannable = new SpannableString(name + " "); spannable.setSpan(new URLSpanUserMention("" + user.id, 3), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sb.append(spannable); } chatActivityEnterView.setFieldText(sb); AndroidUtilities.runOnUIThread(() -> chatActivityEnterView.openKeyboard(), 200); } } @Override public boolean didLongPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) { if (isAvatarPreviewerEnabled()) { AvatarPreviewer.MenuItem[] menuItems = {AvatarPreviewer.MenuItem.OPEN_PROFILE}; if (currentChat == null || currentChat.id != chat.id || isThreadChat()) { menuItems = Arrays.copyOf(menuItems, 2); menuItems[1] = chat.broadcast ? AvatarPreviewer.MenuItem.OPEN_CHANNEL : AvatarPreviewer.MenuItem.OPEN_GROUP; } final TLRPC.ChatFull chatFull = getMessagesController().getChatFull(chat.id); final AvatarPreviewer.Data data; if (chatFull != null) { data = AvatarPreviewer.Data.of(chat, chatFull, menuItems); } else { data = AvatarPreviewer.Data.of(chat, classGuid, menuItems); } if (AvatarPreviewer.canPreview(data)) { AvatarPreviewer.getInstance().show((ViewGroup) fragmentView, data, item -> { switch (item) { case OPEN_PROFILE: openProfile(chat); break; case OPEN_GROUP: case OPEN_CHANNEL: openChat(cell, chat, 0); break; } }); return true; } } return false; } private void openProfile(TLRPC.User user) { if (user != null && user.id != getUserConfig().getClientUserId()) { Bundle args = new Bundle(); args.putLong("user_id", user.id); ProfileActivity fragment = new ProfileActivity(args); fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == user.id ? 1 : 0); AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); presentFragment(fragment); } } private void openProfile(TLRPC.Chat chat) { if (chat != null) { Bundle args = new Bundle(); args.putLong("chat_id", chat.id); presentFragment(new ProfileActivity(args)); } } private void openDialog(ChatMessageCell cell, TLRPC.User user) { if (user != null) { Bundle args = new Bundle(); args.putLong("user_id", user.id); if (getMessagesController().checkCanOpenChat(args, ChatActivity.this, cell.getMessageObject())) { presentFragment(new ChatActivity(args)); } } } private void openChat(ChatMessageCell cell, TLRPC.Chat chat, int postId) { if (currentChat != null && chat.id == currentChat.id) { scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, true, 0); } else if (currentChat == null || chat.id != currentChat.id || isThreadChat()) { Bundle args = new Bundle(); args.putLong("chat_id", chat.id); if (postId != 0) { args.putInt("message_id", postId); } if (getMessagesController().checkCanOpenChat(args, ChatActivity.this, cell.getMessageObject())) { presentFragment(new ChatActivity(args)); } } } private boolean isAvatarPreviewerEnabled() { return UserObject.isUserSelf(currentUser) || (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)); } @Override public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { return; } chatActivityEnterView.didPressedBotButton(button, cell.getMessageObject(), cell.getMessageObject()); } @Override public void needShowPremiumFeatures(String source) { presentFragment(new PremiumPreviewFragment(source)); } @Override public void didLongPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { return; } if (button instanceof TLRPC.TL_keyboardButtonUrl) { openClickableLink(null, button.url, true, cell, cell.getMessageObject()); try { cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} } } @Override public void didPressReaction(ChatMessageCell cell, TLRPC.TL_reactionCount reaction, boolean longpress) { if (getParentActivity() == null) { return; } if (longpress) { if (!ChatObject.isChannelAndNotMegaGroup(currentChat)) { cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); FrameLayout scrimPopupContainerLayout = new FrameLayout(getParentActivity()) { @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { closeMenu(); } return super.dispatchKeyEvent(event); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int h = Math.min(MeasureSpec.getSize(heightMeasureSpec), AndroidUtilities.dp(ReactedUsersListView.VISIBLE_ITEMS * ReactedUsersListView.ITEM_HEIGHT_DP)); if (h == 0) { h = AndroidUtilities.dp(ReactedUsersListView.VISIBLE_ITEMS * ReactedUsersListView.ITEM_HEIGHT_DP); } super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST)); } }; scrimPopupContainerLayout.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); Rect backgroundPaddings = new Rect(); Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); shadowDrawable2.getPadding(backgroundPaddings); scrimPopupContainerLayout.setBackground(shadowDrawable2); ReactionsLayoutInBubble.ReactionButton button = cell.getReactionButton(reaction.reaction); if (button == null) { return; } float bottom = cell.reactionsLayoutInBubble.y + button.y + AndroidUtilities.dp(28); float left = cell.reactionsLayoutInBubble.x + button.x; int[] loc = new int[2]; cell.getLocationInWindow(loc); scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, cell.getPrimaryMessageObject(), reaction, false) .setOnProfileSelectedListener((view1, userId) -> { Bundle args = new Bundle(); args.putLong("user_id", userId); ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @Override public void dismiss() { super.dismiss(); if (scrimPopupWindow != this) { return; } scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); if (scrimPopupWindowHideDimOnDismiss) { dimBehindView(false); } else { scrimPopupWindowHideDimOnDismiss = true; } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } } }; scrimPopupWindow.setPauseNotifications(true); scrimPopupWindow.setDismissAnimationDuration(220); scrimPopupWindow.setOutsideTouchable(true); scrimPopupWindow.setClippingEnabled(true); scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); scrimPopupWindow.setFocusable(true); scrimPopupContainerLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); scrimPopupWindow.getContentView().setFocusableInTouchMode(true); int totalHeight = contentView.getHeight(); int height = scrimPopupContainerLayout.getMeasuredHeight(); int keyboardHeight = contentView.measureKeyboardHeight(); if (keyboardHeight > AndroidUtilities.dp(20)) { totalHeight += keyboardHeight; } int popupX = (int) (left - AndroidUtilities.dp(28)); popupX = Math.max(AndroidUtilities.dp(6), Math.min(chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth(), popupX)); if (AndroidUtilities.isTablet()) { int[] location = new int[2]; fragmentView.getLocationInWindow(location); popupX += location[0]; } int popupY; if (height < totalHeight) { if (height < totalHeight / 2f && chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y > totalHeight / 2f) { popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y - height); } else { popupY = (int) (chatListView.getY() + cell.getY() + cell.reactionsLayoutInBubble.y + button.y + button.height); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, scrimPopupX = popupX, scrimPopupY = popupY); chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); scrimViewReaction = reaction.reaction; dimBehindView(cell, true); hideHints(false); if (topUndoView != null) { topUndoView.hide(true, 1); } if (undoView != null) { undoView.hide(true, 1); } if (chatActivityEnterView != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } } } else { selectReaction(cell.getPrimaryMessageObject(), null, 0, 0, getMediaDataController().getReactionsMap().get(reaction.reaction), false, false); } } @Override public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { if (showCount >= 0 || buttons.isEmpty()) { if (getParentActivity() == null) { return; } if (pollHintView == null) { pollHintView = new HintView(getParentActivity(), HintView.TYPE_POLL_VOTE, themeDelegate); pollHintView.setAlpha(0.0f); pollHintView.setVisibility(View.INVISIBLE); int index = contentView.indexOfChild(chatActivityEnterView); if (index == -1) { return; } contentView.addView(pollHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); } if (buttons.isEmpty() && showCount < 0) { ArrayList pollButtons = cell.getPollButtons(); float lastDiff = 0; for (int a = 0, N = pollButtons.size(); a < N; a++) { ChatMessageCell.PollButton button = pollButtons.get(a); lastDiff = cell.getY() + button.y - AndroidUtilities.dp(4) - chatListViewPaddingTop; pollHintX = button.x + AndroidUtilities.dp(13.3f); pollHintY = button.y - AndroidUtilities.dp(6) + y; if (lastDiff > 0) { lastDiff = 0; x = pollHintX; y = pollHintY; break; } } if (lastDiff != 0) { chatListView.smoothScrollBy(0, (int) lastDiff); pollHintCell = cell; return; } } pollHintView.showForMessageCell(cell, showCount, x, y, true); } else { getSendMessagesHelper().sendVote(cell.getMessageObject(), buttons, null); } } @Override public void didPressCancelSendButton(ChatMessageCell cell) { MessageObject message = cell.getMessageObject(); if (message.messageOwner.send_state != 0) { getSendMessagesHelper().cancelSendingMessage(message); } } @Override public void didLongPress(ChatMessageCell cell, float x, float y) { createMenu(cell, false, false, x, y); startMultiselect(chatListView.getChildAdapterPosition(cell)); } @Override public boolean canPerformActions() { return actionBar != null && !actionBar.isActionModeShowed() && reportType < 0 && !inPreviewMode; } @Override public void didPressUrl(ChatMessageCell cell, final CharacterStyle url, boolean longPress) { didPressMessageUrl(url, longPress, cell.getMessageObject(), cell); } @Override public void needOpenWebView(MessageObject message, String url, String title, String description, String originalUrl, int w, int h) { try { EmbedBottomSheet.show(getParentActivity(), message, photoViewerProvider, title, description, originalUrl, url, w, h, isKeyboardVisible()); } catch (Throwable e) { FileLog.e(e); } } @Override public void didPressReplyMessage(ChatMessageCell cell, int id) { if (UserObject.isReplyUser(currentUser)) { didPressSideButton(cell); return; } MessageObject messageObject = cell.getMessageObject(); if (chatMode == MODE_PINNED || chatMode == MODE_SCHEDULED) { chatActivityDelegate.openReplyMessage(id); finishFragment(); } else { scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); } } @Override public void didPressViaBotNotInline(ChatMessageCell cell, long botId) { Bundle args = new Bundle(); args.putLong("user_id", botId); if (getMessagesController().checkCanOpenChat(args, ChatActivity.this, cell.getMessageObject())) { presentFragment(new ChatActivity(args)); } } @Override public void didPressViaBot(ChatMessageCell cell, String username) { if (bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || bottomOverlay != null && bottomOverlay.getVisibility() == View.VISIBLE) { return; } if (chatActivityEnterView != null && username != null && username.length() > 0) { chatActivityEnterView.setFieldText("@" + username + " "); chatActivityEnterView.openKeyboard(); } } @Override public void didStartVideoStream(MessageObject message) { if (message.isVideo()) { sendSecretMessageRead(message, true); } } @Override public void needReloadPolls() { invalidateMessagesVisiblePart(); } @Override public void didPressImage(ChatMessageCell cell, float x, float y) { MessageObject message = cell.getMessageObject(); message.putInDownloadsStore = true; if (message.isSendError()) { createMenu(cell, false, false, x, y); return; } else if (message.isSending()) { return; } if (message.isDice()) { undoView.showWithAction(0, chatActivityEnterView.getVisibility() == View.VISIBLE && bottomOverlay.getVisibility() != View.VISIBLE ? UndoView.ACTION_DICE_INFO : UndoView.ACTION_DICE_NO_SEND_INFO, message.getDiceEmoji(), null, () -> getSendMessagesHelper().sendMessage(message.getDiceEmoji(), dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, null)); } else if (message.isAnimatedEmoji() && (!message.isAnimatedAnimatedEmoji() || emojiAnimationsOverlay.supports(MessageObject.findAnimatedEmojiEmoticon(message.getDocument())) && currentUser != null) || message.isPremiumSticker()) { restartSticker(cell); emojiAnimationsOverlay.onTapItem(cell, ChatActivity.this, true); chatListView.cancelClickRunnables(false); } else if (message.needDrawBluredPreview()) { Runnable action = sendSecretMessageRead(message, false); cell.invalidate(); SecretMediaViewer.getInstance().setParentActivity(getParentActivity()); SecretMediaViewer.getInstance().openMedia(message, photoViewerProvider, action); } else if (MessageObject.isAnimatedEmoji(message.getDocument()) && MessageObject.getInputStickerSet(message.getDocument()) != null) { ArrayList inputSets = new ArrayList<>(1); inputSets.add(MessageObject.getInputStickerSet(message.getDocument())); EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } else if (message.getInputStickerSet() != null) { StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, message.getInputStickerSet(), null, bottomOverlayChat.getVisibility() != View.VISIBLE && (currentChat == null || ChatObject.canSendStickers(currentChat)) ? chatActivityEnterView : null, themeDelegate); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } else if (message.isVideo() || message.type == 1 || message.type == 0 && !message.isWebpageDocument() || message.isGif()) { openPhotoViewerForMessage(cell, message); } else if (message.type == 3) { sendSecretMessageRead(message, true); try { File f = null; if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) { f = new File(message.messageOwner.attachPath); } if (f == null || !f.exists()) { f = getFileLoader().getPathToMessage(message.messageOwner); } Intent intent = new Intent(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= 24) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(FileProvider.getUriForFile(getParentActivity(), ApplicationLoader.getApplicationId() + ".provider", f), "video/mp4"); } else { intent.setDataAndType(Uri.fromFile(f), "video/mp4"); } getParentActivity().startActivityForResult(intent, 500); } catch (Exception e) { FileLog.e(e); alertUserOpenError(message); } } else if (message.type == 4) { if (!AndroidUtilities.isMapsInstalled(ChatActivity.this)) { return; } if (message.isLiveLocation()) { LocationActivity fragment = new LocationActivity(currentChat == null || ChatObject.canSendMessages(currentChat) || currentChat.megagroup ? 2 : LocationActivity.LOCATION_TYPE_LIVE_VIEW); fragment.setDelegate(ChatActivity.this); fragment.setMessageObject(message); presentFragment(fragment); } else { LocationActivity fragment = new LocationActivity(currentEncryptedChat == null ? 3 : 0); fragment.setDelegate(ChatActivity.this); fragment.setMessageObject(message); presentFragment(fragment); } } else if (message.type == 9 || message.type == 0) { if (message.getDocumentName().toLowerCase().endsWith("attheme")) { File locFile = null; if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) { File f = new File(message.messageOwner.attachPath); if (f.exists()) { locFile = f; } } if (locFile == null) { File f = getFileLoader().getPathToMessage(message.messageOwner); if (f.exists()) { locFile = f; } } Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, message.getDocumentName(), null, true); if (themeInfo != null) { presentFragment(new ThemePreviewActivity(themeInfo)); return; } else { scrollToPositionOnRecreate = -1; } } boolean handled = false; if (message.canPreviewDocument()) { PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider); handled = true; } if (!handled) { try { AndroidUtilities.openForView(message, getParentActivity(), themeDelegate); } catch (Exception e) { FileLog.e(e); alertUserOpenError(message); } } } } @Override public void didPressInstantButton(ChatMessageCell cell, int type) { MessageObject messageObject = cell.getMessageObject(); if (type == 8) { PollVotesAlert.showForPoll(ChatActivity.this, messageObject); } else if (type == 0) { if (messageObject.messageOwner.media != null && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { ArticleViewer.getInstance().setParentActivity(getParentActivity(), ChatActivity.this); ArticleViewer.getInstance().open(messageObject); } } else if (type == 5) { long uid = messageObject.messageOwner.media.user_id; TLRPC.User user = null; if (uid != 0) { user = MessagesController.getInstance(currentAccount).getUser(uid); } openVCard(user, messageObject.messageOwner.media.vcard, messageObject.messageOwner.media.first_name, messageObject.messageOwner.media.last_name); } else { if (messageObject.isSponsored()) { Bundle args = new Bundle(); if (messageObject.sponsoredChatInvite != null) { showDialog(new JoinGroupAlert(mContext, messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this, themeDelegate)); } else { long peerId = MessageObject.getPeerId(messageObject.messageOwner.from_id); if (peerId < 0) { args.putLong("chat_id", -peerId); } else { args.putLong("user_id", peerId); } if (messageObject.sponsoredChannelPost != 0) { args.putInt("message_id", messageObject.sponsoredChannelPost); } if (messageObject.botStartParam != null) { args.putString("inline_query", messageObject.botStartParam); } if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { presentFragment(new ChatActivity(args)); } } } else if (messageObject.messageOwner.media != null && messageObject.messageOwner.media.webpage != null) { if (!openLinkInternally(messageObject.messageOwner.media.webpage.url, messageObject.getId())) { Browser.openUrl(getParentActivity(), messageObject.messageOwner.media.webpage.url); } } } } @Override public void didPressCommentButton(ChatMessageCell cell) { MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); MessageObject message; if (group != null && !group.messages.isEmpty()) { message = group.messages.get(0); } else { message = cell.getMessageObject(); } int maxReadId; long linkedChatId; if (message.messageOwner.replies != null) { maxReadId = message.messageOwner.replies.read_max_id; linkedChatId = message.messageOwner.replies.channel_id; } else { maxReadId = -1; linkedChatId = 0; } openDiscussionMessageChat(currentChat.id, message, message.getId(), linkedChatId, maxReadId, 0, null); } @Override public String getAdminRank(long uid) { if (ChatObject.isChannel(currentChat) && currentChat.megagroup) { return getMessagesController().getAdminRank(currentChat.id, uid); } return null; } @Override public boolean shouldRepeatSticker(MessageObject message) { return !alreadyPlayedStickers.containsKey(message); } @Override public void setShouldNotRepeatSticker(MessageObject message) { alreadyPlayedStickers.put(message, true); } @Override public TextSelectionHelper.ChatListTextSelectionHelper getTextSelectionHelper() { return textSelectionHelper; } @Override public boolean hasSelectedMessages() { return selectedMessagesIds[0].size() + selectedMessagesIds[1].size() > 0; } @Override public void onDiceFinished() { if (fireworksOverlay.isStarted()) { return; } fireworksOverlay.start(); fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } @Override public PinchToZoomHelper getPinchToZoomHelper() { return pinchToZoomHelper; } @Override public boolean keyboardIsOpened() { return contentView.getKeyboardHeight() + chatEmojiViewPadding >= AndroidUtilities.dp(20); } public boolean isLandscape() { return contentView.getMeasuredWidth() > contentView.getMeasuredHeight(); } @Override public void invalidateBlur() { contentView.invalidateBlur(); } @Override public boolean canDrawOutboundsContent() { return false; } @Override public boolean onAccessibilityAction(int action, Bundle arguments) { if (action == AccessibilityNodeInfo.ACTION_CLICK || action == R.id.acc_action_small_button || action == R.id.acc_action_msg_options) { if (inPreviewMode && allowExpandPreviewByClick) { if (parentLayout != null) { parentLayout.expandPreviewFragment(); } return true; } return !canPerformActions(); } return false; } }); if (currentEncryptedChat == null) { chatMessageCell.setAllowAssistant(true); } } else if (viewType == 1) { view = new ChatActionCell(mContext, true, themeDelegate) { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); // if alpha == 0, then visibleToUser == false, so we need to override it // to keep accessibility working correctly info.setVisibleToUser(true); } }; ((ChatActionCell) view).setInvalidateColors(true); ((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() { @Override public void didOpenPremiumGift(ChatActionCell cell, TLRPC.TL_premiumGiftOption giftOption, boolean animateConfetti) { showDialog(new PremiumPreviewBottomSheet(ChatActivity.this, currentAccount, getCurrentUser(), new GiftPremiumBottomSheet.GiftTier(giftOption)) .setAnimateConfetti(animateConfetti) .setOutboundGift(cell.getMessageObject().isOut())); } @Override public void needShowEffectOverlay(ChatActionCell cell, TLRPC.Document document, TLRPC.VideoSize videoSize) { emojiAnimationsOverlay.showAnimationForActionCell(cell, document, videoSize); } @Override public void didClickImage(ChatActionCell cell) { MessageObject message = cell.getMessageObject(); PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, 640); if (photoSize != null) { ImageLocation imageLocation = ImageLocation.getForPhoto(photoSize, message.messageOwner.action.photo); PhotoViewer.getInstance().openPhoto(photoSize.location, imageLocation, photoViewerProvider); } else { PhotoViewer.getInstance().openPhoto(message, null, 0, 0, photoViewerProvider); } } @Override public boolean didLongPress(ChatActionCell cell, float x, float y) { return createMenu(cell, false, false, x, y); } @Override public void needOpenUserProfile(long uid) { if (uid < 0) { Bundle args = new Bundle(); args.putLong("chat_id", -uid); if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { presentFragment(new ChatActivity(args)); } } else if (uid != getUserConfig().getClientUserId()) { Bundle args = new Bundle(); args.putLong("user_id", uid); if (currentEncryptedChat != null && uid == currentUser.id) { args.putLong("dialog_id", dialog_id); } ProfileActivity fragment = new ProfileActivity(args); fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == uid ? 1 : 0); presentFragment(fragment); } } @Override public void didPressReplyMessage(ChatActionCell cell, int id) { MessageObject messageObject = cell.getMessageObject(); scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); } @Override public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { return; } chatActivityEnterView.didPressedBotButton(button, messageObject, messageObject); } }); } else if (viewType == 2) { view = new ChatUnreadCell(mContext, themeDelegate); } else if (viewType == 3) { view = new BotHelpCell(mContext, themeDelegate); ((BotHelpCell) view).setDelegate(url -> { if (url.startsWith("@")) { getMessagesController().openByUserName(url.substring(1), ChatActivity.this, 0); } else if (url.startsWith("#") || url.startsWith("$")) { DialogsActivity fragment = new DialogsActivity(null); fragment.setSearchString(url); presentFragment(fragment); } else if (url.startsWith("/")) { chatActivityEnterView.setCommand(null, url, false, false); if (chatActivityEnterView.getFieldText() == null) { hideFieldPanel(false); } } else { processExternalUrl(0, url, false); } }); } else if (viewType == 4) { view = new ChatLoadingCell(mContext, contentView, themeDelegate); } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position == botInfoRow || position == botInfoEmptyRow) { BotHelpCell helpView = (BotHelpCell) holder.itemView; if (UserObject.isReplyUser(currentUser)) { helpView.setText(false, LocaleController.getString("RepliesChatInfo", R.string.RepliesChatInfo)); } else { TLRPC.BotInfo mBotInfo = botInfo.size() != 0 ? botInfo.get(currentUser.id) : null; helpView.setText(true, mBotInfo != null ? mBotInfo.description : null, mBotInfo != null ? mBotInfo.description_document != null ? mBotInfo.description_document : mBotInfo.description_photo : null, mBotInfo); } } else if (position == loadingDownRow || position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; loadingCell.setProgressVisible(loadsCount > 1); } else if (position >= messagesStartRow && position < messagesEndRow) { ArrayList messages = isFrozen ? frozenMessages : ChatActivity.this.messages; MessageObject message = messages.get(position - messagesStartRow); View view = holder.itemView; if (view instanceof ChatMessageCell) { final ChatMessageCell messageCell = (ChatMessageCell) view; MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); messageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser); messageCell.isBot = currentUser != null && currentUser.bot; messageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; messageCell.isThreadChat = threadMessageId != 0; messageCell.hasDiscussion = chatMode != MODE_SCHEDULED && ChatObject.isChannel(currentChat) && currentChat.has_link && !currentChat.megagroup; messageCell.isPinned = chatMode == 0 && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())); messageCell.linkedChatId = chatMode != MODE_SCHEDULED && chatInfo != null ? chatInfo.linked_chat_id : 0; messageCell.isRepliesChat = UserObject.isReplyUser(currentUser); messageCell.isPinnedChat = chatMode == MODE_PINNED; boolean pinnedBottom = false; boolean pinnedBottomByGroup = false; boolean pinnedTop = false; boolean pinnedTopByGroup = false; int prevPosition; int nextPosition; if (groupedMessages != null) { MessageObject.GroupedMessagePosition pos = groupedMessages.positions.get(message); if (pos != null) { if (groupedMessages.isDocuments) { prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; nextPosition = position - groupedMessages.posArray.size() + groupedMessages.posArray.indexOf(pos); } else { if ((pos.flags & MessageObject.POSITION_FLAG_TOP) != 0) { prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; } else { pinnedTop = true; pinnedTopByGroup = true; prevPosition = -100; } if ((pos.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { nextPosition = position - groupedMessages.posArray.size() + groupedMessages.posArray.indexOf(pos); } else { pinnedBottom = true; pinnedBottomByGroup = true; nextPosition = -100; } } } else { prevPosition = -100; nextPosition = -100; } } else { nextPosition = position - 1; prevPosition = position + 1; } int nextType = getItemViewType(nextPosition); int prevType = getItemViewType(prevPosition); if (!(message.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && nextType == holder.getItemViewType()) { MessageObject nextMessage = messages.get(nextPosition - messagesStartRow); pinnedBottom = nextMessage.isOutOwner() == message.isOutOwner() && Math.abs(nextMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; if (pinnedBottom) { if (message.isImportedForward() || nextMessage.isImportedForward()) { if (message.isImportedForward() && nextMessage.isImportedForward()) { if (Math.abs(nextMessage.messageOwner.fwd_from.date - message.messageOwner.fwd_from.date) <= 5 * 60) { if (nextMessage.messageOwner.fwd_from.from_name != null && message.messageOwner.fwd_from.from_name != null) { pinnedBottom = nextMessage.messageOwner.fwd_from.from_name.equals(message.messageOwner.fwd_from.from_name); } else if (nextMessage.messageOwner.fwd_from.from_id != null && message.messageOwner.fwd_from.from_id != null) { pinnedBottom = MessageObject.getPeerId(nextMessage.messageOwner.fwd_from.from_id) == MessageObject.getPeerId(message.messageOwner.fwd_from.from_id); } else { pinnedBottom = false; } } else { pinnedBottom = false; } } else { pinnedBottom = false; } } else if (currentChat != null) { long fromId = nextMessage.getFromChatId(); pinnedBottom = fromId == message.getFromChatId(); if (!pinnedBottomByGroup && pinnedBottom && fromId < 0 && currentChat.megagroup) { pinnedBottom = false; } } else if (UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser)) { if (message.isPrivateForward() || nextMessage.isPrivateForward()) { pinnedBottom = false; } else { pinnedBottom = nextMessage.getSenderId() == message.getSenderId(); } } } } if (prevType == holder.getItemViewType()) { MessageObject prevMessage = messages.get(prevPosition - messagesStartRow); pinnedTop = !(prevMessage.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && prevMessage.isOutOwner() == message.isOutOwner() && Math.abs(prevMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; if (pinnedTop) { if (message.isImportedForward() || prevMessage.isImportedForward()) { if (message.isImportedForward() && prevMessage.isImportedForward()) { if (Math.abs(message.messageOwner.fwd_from.date - prevMessage.messageOwner.fwd_from.date) <= 5 * 60) { if (prevMessage.messageOwner.fwd_from.from_name != null && message.messageOwner.fwd_from.from_name != null) { pinnedTop = prevMessage.messageOwner.fwd_from.from_name.equals(message.messageOwner.fwd_from.from_name); } else if (prevMessage.messageOwner.fwd_from.from_id != null && message.messageOwner.fwd_from.from_id != null) { pinnedTop = MessageObject.getPeerId(prevMessage.messageOwner.fwd_from.from_id) == MessageObject.getPeerId(message.messageOwner.fwd_from.from_id); } else { pinnedTop = false; } } else { pinnedTop = false; } } else { pinnedTop = false; } } else if (currentChat != null) { long fromId = prevMessage.getFromChatId(); pinnedTop = fromId == message.getFromChatId() && !message.isImportedForward() && !prevMessage.isImportedForward(); if (!pinnedTopByGroup && pinnedTop && fromId < 0 && currentChat.megagroup) { pinnedTop = false; } } else if (UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser)) { if (message.isPrivateForward() || prevMessage.isPrivateForward()) { pinnedTop = false; } else { pinnedTop = prevMessage.getSenderId() == message.getSenderId(); } } } } if (ChatObject.isChannel(currentChat) && currentChat.megagroup && message.getFromChatId() <= 0 && message.messageOwner.fwd_from != null && message.messageOwner.fwd_from.saved_from_peer instanceof TLRPC.TL_peerChannel) { if (!pinnedTopByGroup) { pinnedTop = false; } if (!pinnedBottomByGroup) { pinnedBottom = false; } } messageCell.setMessageObject(message, groupedMessages, pinnedBottom, pinnedTop); messageCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && message.getId() == highlightMessageId); if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } int index; if ((index = animatingMessageObjects.indexOf(message)) != -1) { boolean applyAnimation = false; if (message.type == MessageObject.TYPE_ROUND_VIDEO && instantCameraView.getTextureView() != null) { applyAnimation = true; messageCell.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { PipRoundVideoView pipRoundVideoView = PipRoundVideoView.getInstance(); if (pipRoundVideoView != null) { pipRoundVideoView.showTemporary(true); } messageCell.getViewTreeObserver().removeOnPreDrawListener(this); ImageReceiver imageReceiver = messageCell.getPhotoImage(); float w = imageReceiver.getImageWidth(); org.telegram.ui.Components.Rect rect = instantCameraView.getCameraRect(); float scale = w / rect.width; int[] position = new int[2]; messageCell.getTransitionParams().ignoreAlpha = true; messageCell.setAlpha(0.0f); messageCell.setTimeAlpha(0.0f); messageCell.getLocationOnScreen(position); position[0] += imageReceiver.getImageX() - messageCell.getAnimationOffsetX(); position[1] += imageReceiver.getImageY() - messageCell.getTranslationY(); final InstantCameraView.InstantViewCameraContainer cameraContainer = instantCameraView.getCameraContainer(); cameraContainer.setPivotX(0.0f); cameraContainer.setPivotY(0.0f); AnimatorSet animatorSet = new AnimatorSet(); cameraContainer.setImageReceiver(imageReceiver); instantCameraView.cancelBlur(); AnimatorSet allAnimators = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(cameraContainer, View.SCALE_X, scale), ObjectAnimator.ofFloat(cameraContainer, View.SCALE_Y, scale), ObjectAnimator.ofFloat(cameraContainer, View.TRANSLATION_Y, position[1] - rect.y), ObjectAnimator.ofFloat(instantCameraView.getSwitchButtonView(), View.ALPHA, 0.0f), ObjectAnimator.ofInt(instantCameraView.getPaint(), AnimationProperties.PAINT_ALPHA, 0), ObjectAnimator.ofFloat(instantCameraView.getMuteImageView(), View.ALPHA, 0.0f) ); animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); ObjectAnimator o = ObjectAnimator.ofFloat(cameraContainer, View.TRANSLATION_X, position[0] - rect.x); o.setInterpolator(CubicBezierInterpolator.DEFAULT); allAnimators.playTogether(o, animatorSet); allAnimators.setStartDelay(120); allAnimators.setDuration(180); instantCameraView.setIsMessageTransition(true); allAnimators.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { messageCell.setAlpha(1.0f); messageCell.getTransitionParams().ignoreAlpha = false; Property ALPHA = new AnimationProperties.FloatProperty("alpha") { @Override public void setValue(ChatMessageCell object, float value) { object.setTimeAlpha(value); } @Override public Float get(ChatMessageCell object) { return object.getTimeAlpha(); } }; AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(cameraContainer, View.ALPHA, 0.0f), ObjectAnimator.ofFloat(messageCell, ALPHA, 1.0f) ); animatorSet.setDuration(100); animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { instantCameraView.setIsMessageTransition(false); instantCameraView.hideCamera(true); instantCameraView.setVisibility(View.INVISIBLE); } }); animatorSet.start(); } }); allAnimators.start(); return true; } }); } else if (message.isAnyKindOfSticker() && !message.isAnimatedEmojiStickers()) { applyAnimation = true; messageCell.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { messageCell.getViewTreeObserver().removeOnPreDrawListener(this); MessageObject.SendAnimationData sendAnimationData = messageCell.getMessageObject().sendAnimationData; if (sendAnimationData == null) { return true; } animateSendingViews.add(messageCell); ImageReceiver imageReceiver = messageCell.getPhotoImage(); float w = imageReceiver.getImageWidth(); float scale = sendAnimationData.width / w; int[] position = new int[2]; messageCell.getTransitionParams().ignoreAlpha = true; messageCell.getLocationInWindow(position); position[1] -= messageCell.getTranslationY(); if (chatActivityEnterView.isTopViewVisible()) { position[1] += AndroidUtilities.dp(48); } AnimatorSet allAnimators = new AnimatorSet(); Property param1 = new AnimationProperties.FloatProperty("p1") { @Override public void setValue(MessageObject.SendAnimationData object, float value) { object.currentScale = value; } @Override public Float get(MessageObject.SendAnimationData object) { return object.currentScale; } }; Property param2 = new AnimationProperties.FloatProperty("p2") { @Override public void setValue(MessageObject.SendAnimationData object, float value) { object.currentX = value; if (fragmentView != null) { fragmentView.invalidate(); } } @Override public Float get(MessageObject.SendAnimationData object) { return object.currentX; } }; Property param3 = new AnimationProperties.FloatProperty("p3") { @Override public void setValue(MessageObject.SendAnimationData object, float value) { object.currentY = value; if (fragmentView != null) { fragmentView.invalidate(); } } @Override public Float get(MessageObject.SendAnimationData object) { return object.currentY; } }; AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(sendAnimationData, param1, scale, 1.0f), ObjectAnimator.ofFloat(sendAnimationData, param3, sendAnimationData.y, position[1] + imageReceiver.getCenterY()) ); animatorSet.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); ObjectAnimator o = ObjectAnimator.ofFloat(sendAnimationData, param2, sendAnimationData.x, position[0] + imageReceiver.getCenterX()); o.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); allAnimators.playTogether(o, animatorSet); allAnimators.setDuration(ChatListItemAnimator.DEFAULT_DURATION); allAnimators.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animateSendingViews.remove(messageCell); if (fragmentView != null) { fragmentView.invalidate(); chatListView.invalidate(); } messageCell.setAlpha(1.0f); messageCell.getTransitionParams().ignoreAlpha = false; } }); allAnimators.start(); Property ALPHA = new AnimationProperties.FloatProperty("alpha") { @Override public void setValue(MessageObject.SendAnimationData object, float value) { object.timeAlpha = value; if (fragmentView != null) { fragmentView.invalidate(); } } @Override public Float get(MessageObject.SendAnimationData object) { return object.timeAlpha; } }; AnimatorSet animatorSet2 = new AnimatorSet(); animatorSet2.playTogether( ObjectAnimator.ofFloat(sendAnimationData, ALPHA, 0.0f, 1.0f) ); animatorSet2.setDuration(100); animatorSet2.setStartDelay(150); animatorSet2.setInterpolator(new DecelerateInterpolator()); animatorSet2.start(); return true; } }); } if (applyAnimation || chatListItemAnimator == null) { animatingMessageObjects.remove(index); chatActivityEnterView.startMessageTransition(); chatActivityEnterView.hideTopView(true); } } if (!animatingDocuments.isEmpty() && animatingDocuments.containsKey(message.getDocument())) { animatingDocuments.remove(message.getDocument()); if (chatListItemAnimator != null) { chatListItemAnimator.onGreetingStickerTransition(holder, greetingsViewContainer); } } } else if (view instanceof ChatActionCell) { ChatActionCell actionCell = (ChatActionCell) view; actionCell.setMessageObject(message); actionCell.setAlpha(1.0f); actionCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } else if (view instanceof ChatUnreadCell) { ChatUnreadCell unreadCell = (ChatUnreadCell) view; unreadCell.setText(LocaleController.getString("UnreadMessages", R.string.UnreadMessages)); if (createUnreadMessageAfterId != 0) { createUnreadMessageAfterId = 0; } } } } @Override public int getItemViewType(int position) { if (clearingHistory) { if (position == botInfoEmptyRow) { return 3; } } if (position >= messagesStartRow && position < messagesEndRow) { ArrayList messages = isFrozen ? frozenMessages : ChatActivity.this.messages; return messages.get(position - messagesStartRow).contentType; } else if (position == botInfoRow) { return 3; } return 4; } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { if (holder.itemView instanceof ChatMessageCell || holder.itemView instanceof ChatActionCell) { View view = holder.itemView; holder.itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); int height = chatListView.getMeasuredHeight(); int top = view.getTop(); int bottom = view.getBottom(); int viewTop = top >= 0 ? 0 : -top; int viewBottom = view.getMeasuredHeight(); if (viewBottom > height) { viewBottom = viewTop + height; } int recyclerChatViewHeight = (contentView.getHeightWithKeyboard() - (inPreviewMode ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop()); int keyboardOffset = contentView.getKeyboardHeight(); int parentHeight = viewBottom - viewTop; if (keyboardOffset < AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing() || chatActivityEnterView.panelAnimationInProgress()) { keyboardOffset = chatActivityEnterView.getEmojiPadding(); } if (holder.itemView instanceof ChatMessageCell) { ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setVisiblePart(viewTop, viewBottom - viewTop, recyclerChatViewHeight, keyboardOffset, view.getY() + (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), blurredViewTopOffset, blurredViewBottomOffset); markSponsoredAsRead(chatMessageCell.getMessageObject()); } else if (holder.itemView instanceof ChatActionCell) { if (actionBar != null && contentView != null) { ((ChatActionCell) view).setVisiblePart(view.getY() + (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY(), contentView.getBackgroundSizeY()); } } return true; } }); } if (holder.itemView instanceof ChatMessageCell) { final ChatMessageCell messageCell = (ChatMessageCell) holder.itemView; MessageObject message = messageCell.getMessageObject(); messageCell.showHintButton(true, false, -1); if (hintMessageObject != null && hintMessageObject.equals(message)) { messageCell.showHintButton(false, false, hintMessageType); } if (message.isAnimatedEmoji()) { String emoji = message.getStickerEmoji(); if (emoji != null) { MessagesController.EmojiSound sound = getMessagesController().emojiSounds.get(emoji.replace("\uFE0F", "")); if (sound != null) { getMediaController().playEmojiSound(getAccountInstance(), emoji, sound, true); } } } boolean selected = false; boolean disableSelection = false; if (actionBar.isActionModeShowed() || reportType >= 0) { messageCell.setCheckBoxVisible(threadMessageObjects == null || !threadMessageObjects.contains(message), false); int idx = message.getDialogId() == dialog_id ? 0 : 1; if (selectedMessagesIds[idx].indexOfKey(message.getId()) >= 0) { setCellSelectionBackground(message, messageCell, idx, false); selected = true; } else { messageCell.setDrawSelectionBackground(false); messageCell.setChecked(false, false, false); } disableSelection = true; } else { messageCell.setDrawSelectionBackground(false); messageCell.setChecked(false, false, false); messageCell.setCheckBoxVisible(false, false); } messageCell.setCheckPressed(!disableSelection, disableSelection && selected); if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && getMediaDataController().isMessageFound(message.getId(), message.getDialogId() == mergeDialogId) && getMediaDataController().getLastSearchQuery() != null) { messageCell.setHighlightedText(getMediaDataController().getLastSearchQuery()); } else { messageCell.setHighlightedText(null); } if (!inPreviewMode || !messageCell.isHighlighted()) { messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageCell.getMessageObject().getId() == highlightMessageId); if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } } } int position = holder.getAdapterPosition(); if (position >= messagesStartRow && position < messagesEndRow) { ArrayList messages = isFrozen ? frozenMessages : ChatActivity.this.messages; MessageObject message = messages.get(position - messagesStartRow); View view = holder.itemView; if (message != null && message.messageOwner != null && message.messageOwner.media_unread && message.messageOwner.mentioned) { if (!inPreviewMode && chatMode == 0) { if (!message.isVoice() && !message.isRoundVideo()) { newMentionsCount--; if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } getMessagesController().markMentionMessageAsRead(message.getId(), ChatObject.isChannel(currentChat) ? currentChat.id : 0, dialog_id); message.setContentIsRead(); } } if (view instanceof ChatMessageCell) { ChatMessageCell messageCell = (ChatMessageCell) view; if (inPreviewMode) { messageCell.setHighlighted(true); } else { messageCell.setHighlightedAnimated(); } } } } } public void updateRowAtPosition(int index) { if (chatLayoutManager == null || isFrozen) { return; } int lastVisibleItem = RecyclerView.NO_POSITION; int top = 0; if (!wasManualScroll && unreadMessageObject != null) { int n = chatListView.getChildCount(); for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == unreadMessageObject) { int unreadMessageIndex = messages.indexOf(unreadMessageObject); if (unreadMessageIndex >= 0) { lastVisibleItem = messagesStartRow + messages.indexOf(unreadMessageObject); top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom(); } break; } } } notifyItemChanged(index); if (lastVisibleItem != RecyclerView.NO_POSITION) { chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top); } } public void invalidateRowWithMessageObject(MessageObject messageObject) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; if (cell.getMessageObject() == messageObject) { cell.invalidate(); return; } } } } public View updateRowWithMessageObject(MessageObject messageObject, boolean allowInPlace) { if (allowInPlace) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; if (cell.getMessageObject() == messageObject && !cell.isAdminLayoutChanged()) { cell.setMessageObject(messageObject, cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop()); return cell; } } } } ArrayList messages = isFrozen ? frozenMessages : ChatActivity.this.messages; int index = messages.indexOf(messageObject); if (index == -1) { return null; } updateRowAtPosition(index + messagesStartRow); return null; } public void notifyDataSetChanged(boolean animated) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify data set changed fragmentOpened=" + fragmentOpened); } if (animated && fragmentOpened) { if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } } else { chatListView.setItemAnimator(null); } updateRowsInternal(); try { super.notifyDataSetChanged(); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyDataSetChanged() { notifyDataSetChanged(false); } @Override public void notifyItemChanged(int position) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item changed " + position); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); try { super.notifyItemChanged(position); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyItemRangeChanged(int positionStart, int itemCount) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item range changed " + positionStart + ":" + itemCount); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); try { super.notifyItemRangeChanged(positionStart, itemCount); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyItemInserted(int position) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item inserted " + position); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); try { super.notifyItemInserted(position); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyItemMoved(int fromPosition, int toPosition) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item moved" + fromPosition + ":" + toPosition); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); try { super.notifyItemMoved(fromPosition, toPosition); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyItemRangeInserted(int positionStart, int itemCount) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item range inserted" + positionStart + ":" + itemCount); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); if (positionStart == 1 && itemCount > 0) { int lastPosition = positionStart + itemCount; if (lastPosition >= messagesStartRow && lastPosition < messagesEndRow) { MessageObject m1 = messages.get(lastPosition - messagesStartRow); MessageObject m2 = messages.get(lastPosition - messagesStartRow - 1); if (currentChat != null && m1.getFromChatId() == m2.getFromChatId() || currentUser != null && m1.isOutOwner() == m2.isOutOwner()) { notifyItemChanged(positionStart); } } } try { super.notifyItemRangeInserted(positionStart, itemCount); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyItemRemoved(int position) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item removed " + position); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); try { super.notifyItemRemoved(position); } catch (Exception e) { FileLog.e(e); } } @Override public void notifyItemRangeRemoved(int positionStart, int itemCount) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item range removed" + positionStart + ":" + itemCount); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } updateRowsInternal(); try { super.notifyItemRangeRemoved(positionStart, itemCount); } catch (Exception e) { FileLog.e(e); } } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { return false; } } private boolean openLinkInternally(String urlFinal, int fromMessageId) { if (currentChat == null || urlFinal == null) { return false; } if (urlFinal.startsWith("tg:privatepost") || urlFinal.startsWith("tg://privatepost")) { String urlTmp = urlFinal.replace("tg:privatepost", "tg://telegram.org").replace("tg://privatepost", "tg://telegram.org"); Uri data = Uri.parse(urlTmp); int messageId = Utilities.parseInt(data.getQueryParameter("post")); long channelId = Utilities.parseLong(data.getQueryParameter("channel")); int threadId = Utilities.parseInt(data.getQueryParameter("thread")); if (channelId == currentChat.id && messageId != 0) { if (threadId != 0) { openDiscussionMessageChat(currentChat.id, null, threadId, 0, -1, 0, null); } else { showScrollToMessageError = true; if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); finishFragment(); } else { scrollToMessageId(messageId, fromMessageId, true, 0, false, 0); } } return true; } } else if (currentChat.username != null) { String username = currentChat.username.toLowerCase(); if (publicMsgUrlPattern == null) { publicMsgUrlPattern = Pattern.compile("(https://)?t.me/([0-9a-zA-Z_]+)/([0-9]+)"); voiceChatUrlPattern = Pattern.compile("(https://)?t.me/([0-9a-zA-Z_]+)\\?(voicechat+)"); } Matcher matcher = publicMsgUrlPattern.matcher(urlFinal); if (matcher.find(2) && matcher.find(3) && username.equals(matcher.group(2).toLowerCase())) { Uri data = Uri.parse(urlFinal); int threadId = Utilities.parseInt(data.getQueryParameter("thread")); int commentId = Utilities.parseInt(data.getQueryParameter("comment")); if (threadId != 0 || commentId != 0) { return false; } else { int messageId = Integer.parseInt(matcher.group(3)); showScrollToMessageError = true; if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); finishFragment(); } else { startFromVideoTimestamp = LaunchActivity.getTimestampFromLink(data); if (startFromVideoTimestamp >= 0) { startFromVideoMessageId = messageId; } scrollToMessageId(messageId, fromMessageId, true, 0, false, 0); } } return true; } else if (urlFinal.startsWith("tg:resolve") || urlFinal.startsWith("tg://resolve")) { String urlTmp = urlFinal.replace("tg:resolve", "tg://telegram.org").replace("tg://resolve", "tg://telegram.org"); Uri data = Uri.parse(urlTmp); String usernameE = data.getQueryParameter("domain").toLowerCase(); int messageId = Utilities.parseInt(data.getQueryParameter("post")); int threadId = Utilities.parseInt(data.getQueryParameter("thread")); int commentId = Utilities.parseInt(data.getQueryParameter("comment")); if (username.equals(usernameE) && messageId != 0) { if (threadId != 0 || commentId != 0) { return false; } else { if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); finishFragment(); } else { scrollToMessageId(messageId, fromMessageId, true, 0, false, 0); } return true; } } } else { matcher = voiceChatUrlPattern.matcher(urlFinal); try { if (matcher.find(2) && matcher.find(3) && username.equals(matcher.group(2).toLowerCase())) { Uri data = Uri.parse(urlFinal); String voicechat = data.getQueryParameter("voicechat"); if (!TextUtils.isEmpty(voicechat)) { voiceChatHash = voicechat; checkGroupCallJoin(true); return true; } } } catch (Exception e) { FileLog.e(e); } } } else { if (privateMsgUrlPattern == null) { privateMsgUrlPattern = Pattern.compile("(https://)?t.me/c/([0-9]+)/([0-9]+)"); } Matcher matcher = privateMsgUrlPattern.matcher(urlFinal); if (matcher.find(2) && matcher.find(3)) { long channelId = Long.parseLong(matcher.group(2)); int messageId = Integer.parseInt(matcher.group(3)); if (channelId == currentChat.id && messageId != 0) { Uri data = Uri.parse(urlFinal); int threadId = Utilities.parseInt(data.getQueryParameter("thread")); int commentId = Utilities.parseInt(data.getQueryParameter("comment")); if (threadId != 0 || commentId != 0) { return false; } else { showScrollToMessageError = true; if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); finishFragment(); } else { scrollToMessageId(messageId, fromMessageId, true, 0, false, 0); } return true; } } } } return false; } @Override protected void setInMenuMode(boolean value) { super.setInMenuMode(value); if (actionBar != null) { actionBar.createMenu().setVisibility(inMenuMode ? View.GONE : View.VISIBLE); } } public void setPreloadedSticker(TLRPC.Document preloadedSticker, boolean historyEmpty) { preloadedGreetingsSticker = preloadedSticker; forceHistoryEmpty = historyEmpty; } public class ChatScrollCallback extends RecyclerAnimationScrollHelper.AnimationCallback { private MessageObject scrollTo; private int lastItemOffset; private boolean lastBottom; private int lastPadding; @Override public void onStartAnimation() { super.onStartAnimation(); scrollCallbackAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollCallbackAnimationIndex, allowedNotificationsDuringChatListAnimations); if (pinchToZoomHelper.isInOverlayMode()) { pinchToZoomHelper.finishZoom(); } } @Override public void onEndAnimation() { if (scrollTo != null) { chatAdapter.updateRowsSafe(); int lastItemPosition = chatAdapter.messagesStartRow + messages.indexOf(scrollTo); if (lastItemPosition >= 0) { chatLayoutManager.scrollToPositionWithOffset(lastItemPosition, (int) (lastItemOffset + lastPadding - chatListViewPaddingTop), lastBottom); } } else { chatAdapter.updateRowsSafe(); chatLayoutManager.scrollToPositionWithOffset(0, 0, true); } scrollTo = null; checkTextureViewPosition = true; // chatListView.getOnScrollListener().onScrolled(chatListView, 0, chatScrollHelper.getScrollDirection() == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN ? 1 : -1); updateVisibleRows(); AndroidUtilities.runOnUIThread(() -> getNotificationCenter().onAnimationFinish(scrollCallbackAnimationIndex)); } @Override public void recycleView(View view) { if (view instanceof ChatMessageCell) { chatMessageCellsCache.add((ChatMessageCell) view); } } } public static boolean isClickableLink(String str) { return str.startsWith("https://") || str.startsWith("@") || str.startsWith("#") || str.startsWith("$") || str.startsWith("video?"); } public SimpleTextView getReplyNameTextView() { return replyNameTextView; } public SimpleTextView getReplyObjectTextView() { return replyObjectTextView; } @Override public ArrayList getThemeDescriptions() { if (isPauseOnThemePreview) { isPauseOnThemePreview = false; return null; } ThemeDescription.ThemeDescriptionDelegate selectedBackgroundDelegate = () -> { if (chatActivityEnterView != null) { chatActivityEnterView.updateColors(); } Theme.refreshAttachButtonsColors(); if (chatAttachAlert != null) { chatAttachAlert.checkColors(); } if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (child instanceof ChatMessageCell) { ((ChatMessageCell) child).createSelectorDrawable(0); } else if (child instanceof ChatActionCell) { ((ChatActionCell) child).setInvalidateColors(true); } } } if (messagesSearchListView != null) { int count = messagesSearchListView.getChildCount(); for (int a = 0; a < count; a++) { View child = messagesSearchListView.getChildAt(a); if (child instanceof DialogCell) { ((DialogCell) child).update(0); } } } if (scrimPopupWindowItems != null) { for (int a = 0; a < scrimPopupWindowItems.length; a++) { scrimPopupWindowItems[a].setColors(getThemedColor(Theme.key_actionBarDefaultSubmenuItem), getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon)); scrimPopupWindowItems[a].setSelectorColor(getThemedColor(Theme.key_dialogButtonSelector)); } } if (scrimPopupWindow != null) { final View contentView = scrimPopupWindow.getContentView(); contentView.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); contentView.invalidate(); } if (instantCameraView != null) { instantCameraView.invalidateBlur(); } if (pinnedLineView != null) { pinnedLineView.updateColors(); } if (chatActivityEnterTopView != null && chatActivityEnterTopView.getEditView() != null) { chatActivityEnterTopView.getEditView().updateColors(); } if (headerItem != null) { headerItem.updateColor(); } setNavigationBarColor(getThemedColor(Theme.key_windowBackgroundGray)); if (fragmentContextView != null) { fragmentContextView.updateColors(); } if (avatarContainer != null) { avatarContainer.updateColors(); } if (pinnedMessageView != null) { pinnedMessageView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); } if (topChatPanelView != null) { topChatPanelView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); } if (contentView != null) { contentView.invalidateBlurredViews(); } if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); } if (suggestEmojiPanel != null) { suggestEmojiPanel.updateColors(); } }; ArrayList themeDescriptions = new ArrayList<>(); themeDescriptions.add(new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_chat_wallpaper)); themeDescriptions.add(new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_chat_wallpaper_gradient_to1)); themeDescriptions.add(new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_chat_wallpaper_gradient_to2)); themeDescriptions.add(new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_chat_wallpaper_gradient_to3)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); if (reportType < 0) { themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBTITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubtitle)); } else { themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarActionModeDefault)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBTITLECOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); } themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, selectedBackgroundDelegate, Theme.key_actionBarDefaultSubmenuBackground)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, selectedBackgroundDelegate, Theme.key_actionBarDefaultSubmenuItem)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, selectedBackgroundDelegate, Theme.key_actionBarDefaultSubmenuItemIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubtitle)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getSubtitleTextView() : null, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, null, new Paint[]{Theme.chat_statusPaint, Theme.chat_statusRecordPaint}, null, null, Theme.key_chat_status, null)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getSubtitleTextView() : null, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_actionBarDefaultSubtitle, null)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_BACKGROUND, null, null, null, null, Theme.key_actionBarActionModeDefault)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_TOPBACKGROUND, null, null, null, null, Theme.key_actionBarActionModeDefaultTop)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(selectedMessagesCountTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, 0, null, null, new Drawable[]{Theme.chat_muteIconDrawable}, null, Theme.key_chat_muteIcon)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, 0, null, null, new Drawable[]{Theme.chat_lockIconDrawable}, null, Theme.key_chat_lockIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, Theme.avatarDrawables, null, Theme.key_avatar_text)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundRed)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundOrange)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundViolet)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundGreen)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundCyan)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundBlue)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundPink)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessageRed)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessageOrange)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessageViolet)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessageGreen)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessageCyan)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessageBlue)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_nameInMessagePink)); Theme.MessageDrawable msgInDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgIn); Theme.MessageDrawable msgInMediaDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgInMedia); Theme.MessageDrawable msgInSelectedDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgInSelected); Theme.MessageDrawable msgInMediaSelectedDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgInMediaSelected); Theme.MessageDrawable msgOutDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOut); Theme.MessageDrawable msgOutMediaDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOutMedia); Theme.MessageDrawable msgOutSelectedDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOutSelected); Theme.MessageDrawable msgOutMediaSelectedDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOutMediaSelected); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class, BotHelpCell.class}, null, new Drawable[]{msgInDrawable, msgInMediaDrawable}, null, Theme.key_chat_inBubble)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgInSelectedDrawable, msgInMediaSelectedDrawable}, null, Theme.key_chat_inBubbleSelected)); if (msgInDrawable != null) { themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, msgInDrawable.getShadowDrawables(), null, Theme.key_chat_inBubbleShadow)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, msgInMediaDrawable.getShadowDrawables(), null, Theme.key_chat_inBubbleShadow)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, msgOutDrawable.getShadowDrawables(), null, Theme.key_chat_outBubbleShadow)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, msgOutMediaDrawable.getShadowDrawables(), null, Theme.key_chat_outBubbleShadow)); } themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgOutDrawable, msgOutMediaDrawable}, null, Theme.key_chat_outBubble)); if (!themeDelegate.isThemeChangeAvailable()) { themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgOutDrawable, msgOutMediaDrawable}, null, Theme.key_chat_outBubbleGradient1)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgOutDrawable, msgOutMediaDrawable}, null, Theme.key_chat_outBubbleGradient2)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgOutDrawable, msgOutMediaDrawable}, null, Theme.key_chat_outBubbleGradient3)); } themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgOutSelectedDrawable, msgOutMediaSelectedDrawable}, null, Theme.key_chat_outBubbleSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{msgOutSelectedDrawable, msgOutMediaSelectedDrawable}, null, Theme.key_chat_outBubbleGradientSelectedOverlay)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{ChatActionCell.class}, getThemedPaint(Theme.key_paint_chatActionText), null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatActionCell.class}, getThemedPaint(Theme.key_paint_chatActionText), null, null, Theme.key_chat_serviceLink)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_botCardDrawable, getThemedDrawable(Theme.key_drawable_shareIcon), getThemedDrawable(Theme.key_drawable_replyIcon), getThemedDrawable(Theme.key_drawable_botInline), getThemedDrawable(Theme.key_drawable_botLink), getThemedDrawable(Theme.key_drawable_botInvite), getThemedDrawable(Theme.key_drawable_goIcon), getThemedDrawable(Theme.key_drawable_commentSticker)}, null, Theme.key_chat_serviceIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class, ChatActionCell.class}, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class, ChatActionCell.class}, null, null, null, Theme.key_chat_serviceBackgroundSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class, BotHelpCell.class}, null, null, null, Theme.key_chat_messageTextIn)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageTextOut)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatMessageCell.class, BotHelpCell.class}, null, null, null, Theme.key_chat_messageLinkIn, null)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageLinkOut, null)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgNoSoundDrawable}, null, Theme.key_chat_mediaTimeText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutCheck)}, null, Theme.key_chat_outSentCheck)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutCheckSelected)}, null, Theme.key_chat_outSentCheckSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutCheckRead), getThemedDrawable(Theme.key_drawable_msgOutHalfCheck)}, null, Theme.key_chat_outSentCheckRead)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutCheckReadSelected), getThemedDrawable(Theme.key_drawable_msgOutHalfCheckSelected)}, null, Theme.key_chat_outSentCheckReadSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outSentClock)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outSentClockSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inSentClock)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inSentClockSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgStickerHalfCheck), getThemedDrawable(Theme.key_drawable_msgStickerCheck), getThemedDrawable(Theme.key_drawable_msgStickerClock), getThemedDrawable(Theme.key_drawable_msgStickerViews), getThemedDrawable(Theme.key_drawable_msgStickerReplies), getThemedDrawable(Theme.key_drawable_msgStickerPinned)}, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_mediaSentClock)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutViews), getThemedDrawable(Theme.key_drawable_msgOutReplies), getThemedDrawable(Theme.key_drawable_msgOutPinned)}, null, Theme.key_chat_outViews)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutViewsSelected), getThemedDrawable(Theme.key_drawable_msgOutRepliesSelected), getThemedDrawable(Theme.key_drawable_msgOutPinnedSelected)}, null, Theme.key_chat_outViewsSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsDrawable, Theme.chat_msgInRepliesDrawable, Theme.chat_msgInPinnedDrawable}, null, Theme.key_chat_inViews)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInViewsSelectedDrawable, Theme.chat_msgInRepliesSelectedDrawable, Theme.chat_msgInPinnedSelectedDrawable}, null, Theme.key_chat_inViewsSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaViewsDrawable, Theme.chat_msgMediaRepliesDrawable, Theme.chat_msgMediaPinnedDrawable}, null, Theme.key_chat_mediaViews)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutMenu)}, null, Theme.key_chat_outMenu)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutMenuSelected)}, null, Theme.key_chat_outMenuSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInMenuDrawable}, null, Theme.key_chat_inMenu)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInMenuSelectedDrawable}, null, Theme.key_chat_inMenuSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaMenuDrawable}, null, Theme.key_chat_mediaMenu)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutInstant)}, null, Theme.key_chat_outInstant)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInInstantDrawable, Theme.chat_commentDrawable, Theme.chat_commentArrowDrawable}, null, Theme.key_chat_inInstant)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutCallAudio), getThemedDrawable(Theme.key_drawable_msgOutCallVideo)}, null, Theme.key_chat_outInstant)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{getThemedDrawable(Theme.key_drawable_msgOutCallAudioSelected), getThemedDrawable(Theme.key_drawable_msgOutCallVideoSelected)}, null, Theme.key_chat_outInstant)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, Theme.chat_msgInCallDrawable, null, Theme.key_chat_inInstant)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, Theme.chat_msgInCallSelectedDrawable, null, Theme.key_chat_inInstantSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgCallUpGreenDrawable}, null, Theme.key_chat_outGreenCall)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgCallDownRedDrawable}, null, Theme.key_chat_inRedCall)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgCallDownGreenDrawable}, null, Theme.key_chat_inGreenCall)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_msgErrorPaint, null, null, Theme.key_chat_sentError)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgErrorDrawable}, null, Theme.key_chat_sentErrorIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, selectedBackgroundDelegate, Theme.key_chat_selectedBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_durationPaint, null, null, Theme.key_chat_previewDurationText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_gamePaint, null, null, Theme.key_chat_previewGameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inPreviewInstantText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outPreviewInstantText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inPreviewInstantSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outPreviewInstantSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_deleteProgressPaint, null, null, Theme.key_chat_secretTimeText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, getThemedPaint(Theme.key_paint_chatBotButton), null, null, Theme.key_chat_botButtonText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_botProgressPaint, null, null, Theme.key_chat_botProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, getThemedPaint(Theme.key_paint_chatTimeBackground), null, null, Theme.key_chat_mediaTimeBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inForwardedNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outForwardedNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inPsaNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outPsaNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inViaBotNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outViaBotNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerViaBotNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerReplyNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyMessageText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyMessageText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyMediaMessageText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyMediaMessageText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyMediaMessageSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyMediaMessageSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerReplyMessageText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inPreviewLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outPreviewLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inSiteNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outSiteNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inContactNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outContactNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inContactPhoneText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inContactPhoneSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outContactPhoneText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outContactPhoneSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_mediaProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioSelectedProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioSelectedProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_mediaTimeText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inTimeText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outTimeText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inTimeSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAdminText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAdminSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAdminText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAdminSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outTimeSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioPerformerText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioPerformerSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioPerformerText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioPerformerSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioTitleText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioTitleText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioDurationText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioDurationText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioDurationSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioDurationSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioSeekbar)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioSeekbar)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioSeekbarSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioSeekbarSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioSeekbarFill)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inAudioCacheSeekbar)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioSeekbarFill)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outAudioCacheSeekbar)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inVoiceSeekbar)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVoiceSeekbar)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inVoiceSeekbarSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVoiceSeekbarSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inVoiceSeekbarFill)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVoiceSeekbarFill)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileProgress)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileProgressSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileProgressSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileInfoText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileInfoText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inFileBackgroundSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outFileBackgroundSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inVenueInfoText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVenueInfoText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inVenueInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVenueInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_mediaInfoText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_urlPaint, null, null, Theme.key_chat_linkSelectBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_outUrlPaint, null, null, Theme.key_chat_outLinkSelectBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_textSearchSelectionPaint, null, null, Theme.key_chat_textSelectBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLoader)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outMediaIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLoaderSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outMediaIconSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inLoader)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inMediaIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inLoaderSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inMediaIconSelected)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[0][0], Theme.chat_photoStatesDrawables[1][0], Theme.chat_photoStatesDrawables[2][0], Theme.chat_photoStatesDrawables[3][0]}, null, Theme.key_chat_mediaLoaderPhoto)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[0][0], Theme.chat_photoStatesDrawables[1][0], Theme.chat_photoStatesDrawables[2][0], Theme.chat_photoStatesDrawables[3][0]}, null, Theme.key_chat_mediaLoaderPhotoIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[0][1], Theme.chat_photoStatesDrawables[1][1], Theme.chat_photoStatesDrawables[2][1], Theme.chat_photoStatesDrawables[3][1]}, null, Theme.key_chat_mediaLoaderPhotoSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[0][1], Theme.chat_photoStatesDrawables[1][1], Theme.chat_photoStatesDrawables[2][1], Theme.chat_photoStatesDrawables[3][1]}, null, Theme.key_chat_mediaLoaderPhotoIconSelected)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[7][0], Theme.chat_photoStatesDrawables[8][0]}, null, Theme.key_chat_outLoaderPhoto)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[7][0], Theme.chat_photoStatesDrawables[8][0]}, null, Theme.key_chat_outLoaderPhotoIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[7][1], Theme.chat_photoStatesDrawables[8][1]}, null, Theme.key_chat_outLoaderPhotoSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[7][1], Theme.chat_photoStatesDrawables[8][1]}, null, Theme.key_chat_outLoaderPhotoIconSelected)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][0], Theme.chat_photoStatesDrawables[11][0]}, null, Theme.key_chat_inLoaderPhoto)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][0], Theme.chat_photoStatesDrawables[11][0]}, null, Theme.key_chat_inLoaderPhotoIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][1], Theme.chat_photoStatesDrawables[11][1]}, null, Theme.key_chat_inLoaderPhotoSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][1], Theme.chat_photoStatesDrawables[11][1]}, null, Theme.key_chat_inLoaderPhotoIconSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[12][0]}, null, Theme.key_chat_inFileIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[12][1]}, null, Theme.key_chat_inFileSelectedIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[0]}, null, Theme.key_chat_inContactBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[0]}, null, Theme.key_chat_inContactIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[1]}, null, Theme.key_chat_outContactBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[1]}, null, Theme.key_chat_outContactIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inLocationBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_locationDrawable[0]}, null, Theme.key_chat_inLocationIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLocationBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_locationDrawable[1]}, null, Theme.key_chat_outLocationIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inPollCorrectAnswer)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outPollCorrectAnswer)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inPollWrongAnswer)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outPollWrongAnswer)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_pollHintDrawable[0]}, null, Theme.key_chat_inPreviewInstantText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_pollHintDrawable[1]}, null, Theme.key_chat_outPreviewInstantText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_psaHelpDrawable[0]}, null, Theme.key_chat_inViews)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_psaHelpDrawable[1]}, null, Theme.key_chat_outViews)); if (!themeDelegate.isThemeChangeAvailable()) { themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, Theme.avatarDrawables, null, Theme.key_avatar_text)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countPaint, null, null, Theme.key_chats_unreadCounter)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Paint[]{Theme.dialogs_namePaint[0], Theme.dialogs_namePaint[1], Theme.dialogs_searchNamePaint}, null, null, Theme.key_chats_name)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Paint[]{Theme.dialogs_nameEncryptedPaint[0], Theme.dialogs_nameEncryptedPaint[1], Theme.dialogs_searchNameEncryptedPaint}, null, null, Theme.key_chats_secretName)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable, Theme.dialogs_fakeDrawable}, null, Theme.key_chats_draft)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePaint[1], null, null, Theme.key_chats_message_threeLines)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messageNamePaint, null, null, Theme.key_chats_nameMessage_threeLines)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chats_nameMessage)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chats_attachMessage)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, Theme.dialogs_messagePrintingPaint, null, null, Theme.key_chats_actionMessage)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_timePaint, null, null, Theme.key_chats_date)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_checkDrawable}, null, Theme.key_chats_sentCheck)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_checkReadDrawable, Theme.dialogs_halfCheckDrawable}, null, Theme.key_chats_sentReadCheck)); } themeDescriptions.add(new ThemeDescription(mentionContainer, 0, null, getThemedPaint(Theme.key_paint_chatComposeBackground), null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(mentionContainer, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); themeDescriptions.add(new ThemeDescription(mentionContainer, 0, null, null, new Drawable[]{Theme.chat_composeShadowRoundDrawable}, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(searchContainer, 0, null, getThemedPaint(Theme.key_paint_chatComposeBackground), null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(searchContainer, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); themeDescriptions.add(new ThemeDescription(bottomOverlay, 0, null, getThemedPaint(Theme.key_paint_chatComposeBackground), null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(bottomOverlay, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); themeDescriptions.add(new ThemeDescription(bottomOverlayChat, 0, null, getThemedPaint(Theme.key_paint_chatComposeBackground), null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(bottomOverlayChat, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); themeDescriptions.add(new ThemeDescription(bottomMessagesActionContainer, 0, null, getThemedPaint(Theme.key_paint_chatComposeBackground), null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(bottomMessagesActionContainer, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, null, getThemedPaint(Theme.key_paint_chatComposeBackground), null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"messageEditText"}, null, null, null, Theme.key_chat_messagePanelText)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_CURSORCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"messageEditText"}, null, null, null, Theme.key_chat_messagePanelCursor)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_HINTTEXTCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"messageEditText"}, null, null, null, Theme.key_chat_messagePanelHint)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"sendButton"}, null, null, null, Theme.key_chat_messagePanelSend)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"sendButton"}, null, null, 24, null, Theme.key_chat_messagePanelSend)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"botButton"}, null, null, null, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"botButton"}, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"notifyButton"}, null, null, null, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatActivityEnterView.class}, new String[]{"scheduledButton"}, null, null, null, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"scheduledButton"}, null, null, null, Theme.key_chat_recordedVoiceDot)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"scheduledButton"}, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"attachButton"}, null, null, null, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"attachButton"}, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"audioSendButton"}, null, null, null, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"videoSendButton"}, null, null, null, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"notifyButton"}, null, null, null, Theme.key_chat_messagePanelVideoFrame)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"notifyButton"}, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"videoTimelineView"}, null, null, null, Theme.key_chat_messagePanelSend)); //themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"doneButtonImage"}, null, null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"micDrawable"}, null, null, null, Theme.key_chat_messagePanelVoicePressed)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"cameraDrawable"}, null, null, null, Theme.key_chat_messagePanelVoicePressed)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"sendDrawable"}, null, null, null, Theme.key_chat_messagePanelVoicePressed)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, null, null, null, null, Theme.key_chat_messagePanelVoiceLock)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, null, null, null, Theme.key_chat_messagePanelVoiceLockBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"lockShadowDrawable"}, null, null, null, Theme.key_chat_messagePanelVoiceLockShadow)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"recordDeleteImageView"}, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatActivityEnterView.class}, new String[]{"recordedAudioBackground"}, null, null, null, Theme.key_chat_recordedVoiceBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, null, null, null, null, Theme.key_chat_recordTime)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, null, null, null, null, Theme.key_chat_recordVoiceCancel)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"recordedAudioTimeTextView"}, null, null, null, Theme.key_chat_messagePanelVoiceDuration)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, null, null, null, null, Theme.key_chat_recordVoiceCancel)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"doneButtonProgress"}, null, null, null, Theme.key_contextProgressInner1)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"doneButtonProgress"}, null, null, null, Theme.key_contextProgressOuter1)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"cancelBotButton"}, null, null, null, Theme.key_chat_messagePanelCancelInlineBot)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"cancelBotButton"}, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"redDotPaint"}, null, null, null, Theme.key_chat_recordedVoiceDot)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"paint"}, null, null, null, Theme.key_chat_messagePanelVoiceBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"seekBarWaveform"}, null, null, null, Theme.key_chat_recordedVoiceProgress)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"seekBarWaveform"}, null, null, null, Theme.key_chat_recordedVoiceProgressInner)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"dotPaint"}, null, null, null, Theme.key_chat_emojiPanelNewTrending)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_recordedVoicePlayPause)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelShadowLine)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelEmptyText)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelIcon)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelIconSelected)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerPackSelector)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBackspace)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelTrendingTitle)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelTrendingDescription)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBadgeText)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBadgeBackground)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiBottomPanelIcon)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiSearchIcon)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerSetNameHighlight)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : null, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerPackSelectorLine)); if (chatActivityEnterView != null) { final TrendingStickersAlert trendingStickersAlert = chatActivityEnterView.getTrendingStickersAlert(); if (trendingStickersAlert != null) { themeDescriptions.addAll(trendingStickersAlert.getThemeDescriptions()); } themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, new Drawable[]{chatActivityEnterView.getStickersArrowDrawable()}, null, Theme.key_chat_messagePanelIcons)); } for (int a = 0; a < 2; a++) { UndoView v = a == 0 ? undoView : topUndoView; themeDescriptions.add(new ThemeDescription(v, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_undo_background)); themeDescriptions.add(new ThemeDescription(v, 0, new Class[]{UndoView.class}, new String[]{"undoImageView"}, null, null, null, Theme.key_undo_cancelColor)); themeDescriptions.add(new ThemeDescription(v, 0, new Class[]{UndoView.class}, new String[]{"undoTextView"}, null, null, null, Theme.key_undo_cancelColor)); themeDescriptions.add(new ThemeDescription(v, 0, new Class[]{UndoView.class}, new String[]{"infoTextView"}, null, null, null, Theme.key_undo_infoColor)); themeDescriptions.add(new ThemeDescription(v, 0, new Class[]{UndoView.class}, new String[]{"subinfoTextView"}, null, null, null, Theme.key_undo_infoColor)); themeDescriptions.add(new ThemeDescription(v, ThemeDescription.FLAG_LINKCOLOR, new Class[]{UndoView.class}, new String[]{"subinfoTextView"}, null, null, null, Theme.key_undo_cancelColor)); themeDescriptions.add(new ThemeDescription(v, 0, new Class[]{UndoView.class}, new String[]{"textPaint"}, null, null, null, Theme.key_undo_infoColor)); themeDescriptions.add(new ThemeDescription(v, 0, new Class[]{UndoView.class}, new String[]{"progressPaint"}, null, null, null, Theme.key_undo_infoColor)); themeDescriptions.add(new ThemeDescription(v, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{UndoView.class}, new String[]{"leftImageView"}, null, null, null, Theme.key_undo_infoColor)); } themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_botKeyboardButtonText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_botKeyboardButtonBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_botKeyboardButtonBackgroundPressed)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"subtitleTextView"}, null, null, null, Theme.key_inappPlayerClose)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText)); themeDescriptions.add(new ThemeDescription(pinnedLineView, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_topPanelLine)); themeDescriptions.add(new ThemeDescription(pinnedLineView, 0, null, null, null, selectedBackgroundDelegate, Theme.key_windowBackgroundWhite)); themeDescriptions.add(new ThemeDescription(pinnedCounterTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); for (int a = 0; a < 2; a++) { themeDescriptions.add(new ThemeDescription(pinnedNameTextView[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); themeDescriptions.add(new ThemeDescription(pinnedMessageTextView[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelMessage)); } themeDescriptions.add(new ThemeDescription(alertNameTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); themeDescriptions.add(new ThemeDescription(alertTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelMessage)); themeDescriptions.add(new ThemeDescription(closePinned, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelClose)); themeDescriptions.add(new ThemeDescription(pinnedListButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelClose)); themeDescriptions.add(new ThemeDescription(closeReportSpam, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelClose)); themeDescriptions.add(new ThemeDescription(topChatPanelView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_topPanelBackground)); themeDescriptions.add(new ThemeDescription(alertView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_topPanelBackground)); themeDescriptions.add(new ThemeDescription(pinnedMessageView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_topPanelBackground)); themeDescriptions.add(new ThemeDescription(addToContactsButton, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_addContact)); themeDescriptions.add(new ThemeDescription(reportSpamButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_chat_reportSpam)); themeDescriptions.add(new ThemeDescription(reportSpamButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_chat_addContact)); themeDescriptions.add(new ThemeDescription(replyLineView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_chat_replyPanelLine)); themeDescriptions.add(new ThemeDescription(replyNameTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_replyPanelName)); themeDescriptions.add(new ThemeDescription(replyObjectTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText)); themeDescriptions.add(new ThemeDescription(replyObjectHintTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText)); themeDescriptions.add(new ThemeDescription(replyIconImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_replyPanelIcons)); themeDescriptions.add(new ThemeDescription(replyCloseImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_replyPanelClose)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_replyPanelName)); themeDescriptions.add(new ThemeDescription(searchUpButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchUpButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchDownButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchDownButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchCalendarButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchCalendarButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchUserButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_searchPanelIcons)); themeDescriptions.add(new ThemeDescription(searchUserButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(searchCountText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_searchPanelText)); themeDescriptions.add(new ThemeDescription(searchAsListTogglerView, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(replyButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(replyButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(forwardButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); themeDescriptions.add(new ThemeDescription(forwardButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); themeDescriptions.add(new ThemeDescription(bottomOverlayText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_secretChatStatusText)); themeDescriptions.add(new ThemeDescription(bottomOverlayChatText, 0, null, null, null, null, Theme.key_chat_fieldOverlayText)); themeDescriptions.add(new ThemeDescription(bottomOverlayChatText, 0, null, null, null, null, Theme.key_chat_goDownButtonCounterBackground)); themeDescriptions.add(new ThemeDescription(bottomOverlayChatText, 0, null, null, null, null, Theme.key_chat_messagePanelBackground)); themeDescriptions.add(new ThemeDescription(bottomOverlayProgress, 0, null, null, null, null, Theme.key_chat_fieldOverlayText)); themeDescriptions.add(new ThemeDescription(bottomOverlayImage, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); themeDescriptions.add(new ThemeDescription(bigEmptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(emptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(progressBar, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE, new Class[]{ChatUnreadCell.class}, new String[]{"backgroundLayout"}, null, null, null, Theme.key_chat_unreadMessagesStartBackground)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatUnreadCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_chat_unreadMessagesStartArrowIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{ChatUnreadCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_unreadMessagesStartText)); themeDescriptions.add(new ThemeDescription(progressView2, ThemeDescription.FLAG_SERVICEBACKGROUND, null, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(emptyView, ThemeDescription.FLAG_SERVICEBACKGROUND, null, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(bigEmptyView, ThemeDescription.FLAG_SERVICEBACKGROUND, null, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_SERVICEBACKGROUND, new Class[]{ChatLoadingCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{ChatLoadingCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotSwitchCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_botSwitchToInlineText)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), ThemeDescription.FLAG_TEXTCOLOR, new Class[]{MentionCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), ThemeDescription.FLAG_TEXTCOLOR, new Class[]{MentionCell.class}, new String[]{"usernameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText3)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, new Drawable[]{Theme.chat_inlineResultFile, Theme.chat_inlineResultAudio, Theme.chat_inlineResultLocation}, null, Theme.key_chat_inlineResultIcon)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteLinkText)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_chat_inAudioProgress)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_chat_inAudioSelectedProgress)); themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_divider)); themeDescriptions.add(new ThemeDescription(gifHintTextView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_gifSaveHintBackground)); themeDescriptions.add(new ThemeDescription(gifHintTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_gifSaveHintText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachMediaBanBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachMediaBanText)); themeDescriptions.add(new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_gifSaveHintText)); themeDescriptions.add(new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{HintView.class}, new String[]{"imageView"}, null, null, null, Theme.key_chat_gifSaveHintText)); themeDescriptions.add(new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"arrowImageView"}, null, null, null, Theme.key_chat_gifSaveHintBackground)); themeDescriptions.add(new ThemeDescription(forwardHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_gifSaveHintText)); themeDescriptions.add(new ThemeDescription(forwardHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"arrowImageView"}, null, null, null, Theme.key_chat_gifSaveHintBackground)); themeDescriptions.add(new ThemeDescription(pagedownButtonCounter, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButtonCounterBackground)); themeDescriptions.add(new ThemeDescription(pagedownButtonCounter, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_goDownButtonCounter)); themeDescriptions.add(new ThemeDescription(pagedownButtonImage, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButton)); themeDescriptions.add(new ThemeDescription(pagedownButtonImage, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chat_goDownButtonShadow)); themeDescriptions.add(new ThemeDescription(pagedownButtonImage, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_goDownButtonIcon)); themeDescriptions.add(new ThemeDescription(mentiondownButtonCounter, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButtonCounterBackground)); themeDescriptions.add(new ThemeDescription(mentiondownButtonCounter, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_goDownButtonCounter)); themeDescriptions.add(new ThemeDescription(mentiondownButtonImage, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButton)); themeDescriptions.add(new ThemeDescription(mentiondownButtonImage, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chat_goDownButtonShadow)); themeDescriptions.add(new ThemeDescription(mentiondownButtonImage, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_goDownButtonIcon)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTimeItem() : null, 0, null, null, null, null, Theme.key_chat_secretTimerBackground)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTimeItem() : null, 0, null, null, null, null, Theme.key_chat_secretTimerText)); themeDescriptions.add(new ThemeDescription(floatingDateView, 0, null, null, null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(floatingDateView, 0, null, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(infoTopView, 0, null, null, null, null, Theme.key_chat_serviceText)); themeDescriptions.add(new ThemeDescription(infoTopView, 0, null, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachGalleryIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachGalleryBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachGalleryText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachAudioIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachAudioBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachAudioText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachFileIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachFileBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachFileText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachContactIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachContactBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachContactText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachLocationIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachLocationBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachLocationText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachPollIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachPollBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachPollText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.chat_attachEmptyDrawable}, null, Theme.key_chat_attachEmptyImage)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachPhotoBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogBackgroundGray)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogTextGray2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogScrollGlow)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogGrayLine)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogCameraIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogButtonSelector)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_windowBackgroundWhiteLinkSelection)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_windowBackgroundWhiteInputField)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_outTextSelectionHighlight)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inTextSelectionHighlight)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_TextSelectionCursor)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayGreen1)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayGreen2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayBlue1)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayBlue2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_topPanelGreen1)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_topPanelGreen2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_topPanelBlue1)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_topPanelBlue2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_topPanelGray)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayAlertGradientMuted)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayAlertGradientMuted2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayAlertGradientUnmuted)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayAlertGradientUnmuted2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_mutedByAdminGradient)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_mutedByAdminGradient2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_mutedByAdminGradient3)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayAlertMutedByAdmin)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_voipgroup_overlayAlertMutedByAdmin2)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_windowBackgroundGray)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_outReactionButtonBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inReactionButtonBackground)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inReactionButtonText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_outReactionButtonText)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inReactionButtonTextSelected)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_inReactionButtonTextSelected)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_BlurAlpha)); if (chatActivityEnterView != null) { themeDescriptions.add(new ThemeDescription(chatActivityEnterView.botCommandsMenuContainer.listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotCommandsMenuView.BotCommandView.class}, new String[]{"description"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView.botCommandsMenuContainer.listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotCommandsMenuView.BotCommandView.class}, new String[]{"command"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText)); } if (pendingRequestsDelegate != null) { pendingRequestsDelegate.fillThemeDescriptions(themeDescriptions); } for (ThemeDescription description : themeDescriptions) { description.resourcesProvider = themeDelegate; } return themeDescriptions; } public ChatAvatarContainer getAvatarContainer() { return avatarContainer; } @Override protected AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { if (isOpen && fromPullingDownTransition && getParentLayout().fragmentsStack.size() > 1) { BaseFragment previousFragment = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2); if (previousFragment instanceof ChatActivity) { wasManualScroll = true; ChatActivity previousChat = (ChatActivity) previousFragment; previousChat.setTransitionToChatActivity(this); fragmentView.setAlpha(0); contentView.setSkipBackgroundDrawing(true); avatarContainer.setTranslationY(AndroidUtilities.dp(8)); avatarContainer.getAvatarImageView().setAlpha(0); avatarContainer.getAvatarImageView().setTranslationY(-AndroidUtilities.dp(8)); toPullingDownTransition = true; ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f); if (chatActivityEnterView != null) { chatActivityEnterView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST)); } if (bottomOverlay != null) { bottomOverlay.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST)); } int currentBottom = Math.max(chatActivityEnterView == null ? 0 : chatActivityEnterView.getMeasuredHeight(), bottomOverlay == null ? 0 : bottomOverlay.getMeasuredHeight()); int prevBottom = Math.max(previousChat.chatActivityEnterView == null ? 0 : previousChat.chatActivityEnterView.getMeasuredHeight(), bottomOverlay == null ? 0 : bottomOverlay.getMeasuredHeight()); pullingBottomOffset = -(prevBottom - currentBottom); boolean useAlphaForContextView = previousChat.fragmentContextView.getMeasuredHeight() != fragmentContextView.getMeasuredHeight(); valueAnimator.addUpdateListener(valueAnimator1 -> { float progress = (float) valueAnimator1.getAnimatedValue(); previousChat.setTransitionToChatProgress(progress); float y = AndroidUtilities.dp(8) * (1f - progress); avatarContainer.setTranslationY(y); avatarContainer.getAvatarImageView().setTranslationY(-y); y = -AndroidUtilities.dp(8) * progress; previousChat.avatarContainer.setTranslationY(y); previousChat.avatarContainer.getAvatarImageView().setTranslationY(-y); avatarContainer.getAvatarImageView().setScaleX(0.8f + 0.2f * progress); avatarContainer.getAvatarImageView().setScaleY(0.8f + 0.2f * progress); avatarContainer.getAvatarImageView().setAlpha(progress); previousChat.avatarContainer.getAvatarImageView().setScaleX(0.8f + 0.2f * (1f - progress)); previousChat.avatarContainer.getAvatarImageView().setScaleY(0.8f + 0.2f * (1f - progress)); previousChat.avatarContainer.getAvatarImageView().setAlpha(1f - progress); if (previousChat.chatActivityEnterView != null) { previousChat.chatActivityEnterView.setTranslationY(-pullingBottomOffset * progress); } if (previousChat.bottomOverlay != null) { previousChat.bottomOverlay.setTranslationY(-pullingBottomOffset * progress); } if (useAlphaForContextView) { previousChat.fragmentContextView.setAlpha(1f - progress); } previousChat.pinnedMessageView.setAlpha(1f - progress); previousChat.topChatPanelView.setAlpha(1f - progress); }); updateChatListViewTopPadding(); fragmentTransition = new AnimatorSet(); fragmentTransition.addListener(new AnimatorListenerAdapter() { int index; @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); index = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(index, null); } @Override public void onAnimationEnd(Animator animation) { fragmentOpened = true; fragmentBeginToShow = true; fragmentTransition = null; AndroidUtilities.runOnUIThread(() -> { NotificationCenter.getInstance(currentAccount).onAnimationFinish(index); }, 32); super.onAnimationEnd(animation); contentView.invalidate(); contentView.setSkipBackgroundDrawing(false); toPullingDownTransition = false; previousChat.setTransitionToChatProgress(0); previousChat.setTransitionToChatActivity(null); fragmentView.setAlpha(1f); callback.run(); avatarContainer.setTranslationY(0); previousChat.avatarContainer.setTranslationY(0); previousChat.avatarContainer.getAvatarImageView().setTranslationY(0); avatarContainer.getAvatarImageView().setScaleX(1f); avatarContainer.getAvatarImageView().setScaleY(1f); avatarContainer.getAvatarImageView().setAlpha(1f); previousChat.avatarContainer.getAvatarImageView().setScaleX(1f); previousChat.avatarContainer.getAvatarImageView().setScaleY(1f); previousChat.avatarContainer.getAvatarImageView().setAlpha(1f); previousChat.pinnedMessageView.setAlpha(1f); previousChat.topChatPanelView.setAlpha(1f); } }); fragmentTransition.setDuration(300); fragmentTransition.setInterpolator(CubicBezierInterpolator.DEFAULT); fragmentTransition.playTogether(valueAnimator); AndroidUtilities.runOnUIThread(fragmentTransitionRunnable, 200); return fragmentTransition; } } return null; } private void setTransitionToChatActivity(ChatActivity chatActivity) { pullingDownAnimateToActivity = chatActivity; } private void setTransitionToChatProgress(float p) { pullingDownAnimateProgress = p; fragmentView.invalidate(); chatListView.invalidate(); } private void showChatThemeBottomSheet() { chatThemeBottomSheet = new ChatThemeBottomSheet(ChatActivity.this, themeDelegate); chatListView.setOnInterceptTouchListener(event -> true); setChildrenEnabled(contentView, false); showDialog(chatThemeBottomSheet, dialogInterface -> { chatThemeBottomSheet = null; chatListView.setOnInterceptTouchListener(null); setChildrenEnabled(contentView, true); ChatThemeController.clearWallpaperThumbImages(); }); } private void setChildrenEnabled(View view, boolean isEnabled) { if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); ++i) { setChildrenEnabled(viewGroup.getChildAt(i), isEnabled); } } if (view != chatListView && view != contentView) { view.setEnabled(isEnabled); } } private void checkThemeEmoticon() { if (!fragmentOpened) { return; } String emoticon = null; if (userInfo != null) { emoticon = userInfo.theme_emoticon; } if (emoticon == null && chatInfo != null) { emoticon = chatInfo.theme_emoticon; } setChatThemeEmoticon(emoticon); } private void setChatThemeEmoticon(final String emoticon) { ChatThemeController.getInstance(currentAccount).setDialogTheme(dialog_id, emoticon, false); if (!TextUtils.isEmpty(emoticon)) { ChatThemeController.requestChatTheme(emoticon, result -> { themeDelegate.setCurrentTheme(result, openAnimationStartTime != 0, null); }); } else { themeDelegate.setCurrentTheme(null, openAnimationStartTime != 0, null); } } @Override public int getNavigationBarColor() { return getThemedColor(Theme.key_windowBackgroundGray); } @Override public int getThemedColor(String key) { Integer color = themeDelegate != null ? themeDelegate.getColor(key) : null; return color != null ? color : super.getThemedColor(key); } @Override public Drawable getThemedDrawable(String drawableKey) { Drawable drawable = themeDelegate.getDrawable(drawableKey); return drawable != null ? drawable : super.getThemedDrawable(drawableKey); } private Paint getThemedPaint(String paintKey) { Paint paint = themeDelegate.getPaint(paintKey); return paint != null ? paint : Theme.getThemePaint(paintKey); } public float getChatListViewPadding() { return chatListViewPaddingTop; } public FragmentContextView getFragmentContextView() { return fragmentContextView; } public Theme.ResourcesProvider getResourceProvider() { return themeDelegate; } public Runnable onThemeChange; public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.ThemeDelegate, ForwardingPreviewView.ResourcesDelegate { private final HashMap currentDrawables = new HashMap<>(); private final HashMap currentPaints = new HashMap<>(); private final Matrix actionMatrix = new Matrix(); private HashMap currentColors = new HashMap<>(); private HashMap animatingColors; private EmojiThemes chatTheme; private Drawable backgroundDrawable; private ValueAnimator patternIntensityAnimator; private Bitmap serviceBitmap; private Bitmap serviceBitmapSource; private Paint paint = new Paint(); private Canvas serviceCanvas; private BitmapShader serviceShader; private BitmapShader serviceShaderSource; private boolean useSourceShader; private int currentColor; private boolean isDark; private List cachedThemes; private AnimatorSet patternAlphaAnimator; Theme.MessageDrawable animatingMessageDrawable; Theme.MessageDrawable animatingMessageMediaDrawable; ThemeDelegate() { isDark = Theme.getActiveTheme().isDark(); boolean setup = false; if (isThemeChangeAvailable()) { chatTheme = ChatThemeController.getInstance(currentAccount).getDialogTheme(dialog_id); if (chatTheme != null) { setup = true; setupChatTheme(chatTheme, false, true); } } if (!setup && ThemeEditorView.getInstance() == null) { Theme.refreshThemeColors(true, true); } else { AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewTheme, false, true, parentLayout != null && !parentLayout.isTransitionAnimationInProgress())); } } public List getCachedThemes() { return cachedThemes; } public void setCachedThemes(List cachedThemes) { this.cachedThemes = cachedThemes; } @Override public Integer getColor(String key) { if (chatTheme == null) { return Theme.getColor(key); } if (animatingColors != null) { Integer color = animatingColors.get(key); if (color != null) { return color; } } Integer color = currentColors.get(key); if (color == null) { if (Theme.key_chat_outBubbleGradient1.equals(key) || Theme.key_chat_outBubbleGradient2.equals(key) || Theme.key_chat_outBubbleGradient3.equals(key)) { color = currentColors.get(Theme.key_chat_outBubble); if (color == null) { color = Theme.getColorOrNull(key); } if (color == null) { color = Theme.getColor(Theme.key_chat_outBubble); } } if (color == null) { String fallbackKey = Theme.getFallbackKey(key); if (fallbackKey != null) { color = currentColors.get(fallbackKey); } } } if (color == null) { if (chatTheme != null) { color = Theme.getDefaultColor(key); } } return color; } @Override public Integer getCurrentColor(String key) { return getCurrentColor(key, false); } public Integer getCurrentColor(String key, boolean ignoreAnimation) { if (chatTheme == null) { return Theme.getColorOrNull(key); } Integer color = null; if (!ignoreAnimation && animatingColors != null) { color = animatingColors.get(key); } if (color == null) { color = currentColors.get(key); } return color; } @Override public void setAnimatedColor(String key, int color) { if (animatingColors != null) { animatingColors.put(key, color); } } @Override public void applyServiceShaderMatrix(int w, int h, float translationX, float translationY) { if (chatTheme == null || serviceBitmap == null || serviceShader == null) { ChatActionCell.ThemeDelegate.super.applyServiceShaderMatrix(w, h, translationX, translationY); } else { if (useSourceShader) { Theme.applyServiceShaderMatrix(serviceBitmapSource, serviceShaderSource, actionMatrix, w, h, translationX, translationY); } else { Theme.applyServiceShaderMatrix(serviceBitmap, serviceShader, actionMatrix, w, h, translationX, translationY); } } } @Override public int getCurrentColor() { return chatTheme != null ? currentColor : Theme.currentColor; } @Override public boolean hasGradientService() { return chatTheme != null ? serviceShader != null : Theme.hasGradientService(); } @Override public Drawable getDrawable(String drawableKey) { return !currentDrawables.isEmpty() ? currentDrawables.get(drawableKey) : null; } @Override public Paint getPaint(String paintKey) { return chatTheme != null ? currentPaints.get(paintKey) : null; } public boolean isThemeChangeAvailable() { return currentChat == null && currentEncryptedChat == null && !currentUser.bot && dialog_id >= 0; } public EmojiThemes getCurrentTheme() { return chatTheme; } @Override public Drawable getWallpaperDrawable() { return backgroundDrawable != null ? backgroundDrawable : Theme.getCachedWallpaperNonBlocking(); } @Override public boolean isWallpaperMotion() { return chatTheme != null ? false : Theme.isWallpaperMotion(); } public void setCurrentTheme(final EmojiThemes chatTheme, boolean animated, Boolean forceDark) { if (parentLayout == null) { return; } final EmojiThemes prevTheme = this.chatTheme; boolean newIsDark = forceDark != null ? forceDark : Theme.getActiveTheme().isDark(); String newEmoticon = chatTheme != null ? chatTheme.getEmoticon() : null; String oldEmoticon = this.chatTheme != null ? this.chatTheme.getEmoticon() : null; if (!isThemeChangeAvailable() || (TextUtils.equals(oldEmoticon, newEmoticon) && this.isDark == newIsDark)) { return; } this.isDark = newIsDark; Theme.ThemeInfo currentTheme = newIsDark ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); ActionBarLayout.ThemeAnimationSettings animationSettings = new ActionBarLayout.ThemeAnimationSettings(currentTheme, currentTheme.currentAccentId, currentTheme.isDark(), !animated); if (this.chatTheme == null) { Drawable background = Theme.getCachedWallpaperNonBlocking(); drawServiceGradient = background instanceof MotionBackgroundDrawable; initServiceMessageColors(background); startServiceTextColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceText); startServiceLinkColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceLink); startServiceButtonColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceLink); startServiceIconColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceIcon); } else if (drawServiceGradient) { startServiceBitmap = ((MotionBackgroundDrawable) backgroundDrawable).getBitmap(); } startServiceColor = currentServiceColor; startServiceTextColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceText, true); startServiceLinkColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); startServiceButtonColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); startServiceIconColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceIcon, true); if (chatTheme != null) { int[] colors = AndroidUtilities.calcDrawableColor(backgroundDrawable); currentColor = colors[0]; initDrawables(); initPaints(); } animationSettings.applyTheme = false; animationSettings.afterStartDescriptionsAddedRunnable = () -> { setupChatTheme(chatTheme, animated, false); initServiceMessageColors(backgroundDrawable); }; if (animated) { animationSettings.animationProgress = new ActionBarLayout.ThemeAnimationSettings.onAnimationProgress() { @Override public void setProgress(float p) { chatListView.invalidate(); animatingMessageDrawable.crossfadeProgress = p; animatingMessageMediaDrawable.crossfadeProgress = p; updateServiceMessageColor(p); } }; animationSettings.beforeAnimationRunnable = () -> { animatingColors = new HashMap<>(); animatingMessageDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOut); animatingMessageDrawable.crossfadeFromDrawable = parentLayout.messageDrawableOutStart; animatingMessageMediaDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOutMedia); animatingMessageMediaDrawable.crossfadeFromDrawable = parentLayout.messageDrawableOutMediaStart; animatingMessageDrawable.crossfadeProgress = 0f; animatingMessageMediaDrawable.crossfadeProgress = 0f; updateMessagesVisiblePart(false); updateServiceMessageColor(0); }; animationSettings.afterAnimationRunnable = () -> { animatingMessageDrawable.crossfadeFromDrawable = null; animatingMessageMediaDrawable.crossfadeFromDrawable = null; animatingColors = null; updateServiceMessageColor(1f); }; } else { if (contentView != null) { contentView.setBackgroundImage(Theme.getCachedWallpaper(), Theme.isWallpaperMotion()); } } animationSettings.onlyTopFragment = true; animationSettings.resourcesProvider = this; animationSettings.duration = 250; parentLayout.animateThemedValues(animationSettings, null); if (onThemeChange != null) { onThemeChange.run(); } } private void setupChatTheme(EmojiThemes chatTheme, boolean withAnimation, boolean createNewResources) { this.chatTheme = chatTheme; Drawable prevDrawable = null; if (fragmentView != null) { prevDrawable = ((SizeNotifierFrameLayout) fragmentView).getBackgroundImage(); } final MotionBackgroundDrawable prevMotionDrawable = (prevDrawable instanceof MotionBackgroundDrawable) ? (MotionBackgroundDrawable) prevDrawable : null; final int prevPhase = prevMotionDrawable != null ? prevMotionDrawable.getPhase() : 0; if (chatTheme == null || chatTheme.showAsDefaultStub) { currentColor = Theme.getServiceMessageColor(); } if (chatTheme == null) { currentColors = new HashMap<>(); currentPaints.clear(); currentDrawables.clear(); Drawable wallpaper = Theme.getCachedWallpaperNonBlocking(); if (wallpaper instanceof MotionBackgroundDrawable) { ((MotionBackgroundDrawable) wallpaper).setPhase(prevPhase); } backgroundDrawable = null; Theme.ThemeInfo activeTheme; if (Theme.getActiveTheme().isDark() == isDark) { activeTheme = Theme.getActiveTheme(); } else { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); String dayThemeName = preferences.getString("lastDayTheme", "Blue"); if (Theme.getTheme(dayThemeName) == null || Theme.getTheme(dayThemeName).isDark()) { dayThemeName = "Blue"; } String nightThemeName = preferences.getString("lastDarkTheme", "Dark Blue"); if (Theme.getTheme(nightThemeName) == null || !Theme.getTheme(nightThemeName).isDark()) { nightThemeName = "Dark Blue"; } activeTheme = isDark ? Theme.getTheme(nightThemeName) : Theme.getTheme(dayThemeName); } Theme.applyTheme(activeTheme, false, isDark); } else { if (ApplicationLoader.applicationContext != null) { Theme.createChatResources(ApplicationLoader.applicationContext, false); } currentColors = chatTheme.createColors(currentAccount, isDark ? 1 : 0); backgroundDrawable = getBackgroundDrawableFromTheme(chatTheme, prevPhase); if (patternAlphaAnimator != null) { patternAlphaAnimator.cancel(); } if (withAnimation) { patternAlphaAnimator = new AnimatorSet(); if (prevMotionDrawable != null) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f); valueAnimator.addUpdateListener(animator -> prevMotionDrawable.setPatternAlpha((float) animator.getAnimatedValue())); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); prevMotionDrawable.setPatternAlpha(1f); } }); valueAnimator.setDuration(200); patternAlphaAnimator.playTogether(valueAnimator); } if (backgroundDrawable instanceof MotionBackgroundDrawable) { final MotionBackgroundDrawable currentBackgroundDrawable = (MotionBackgroundDrawable) backgroundDrawable; currentBackgroundDrawable.setPatternAlpha(0f); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f); valueAnimator.addUpdateListener(animator -> currentBackgroundDrawable.setPatternAlpha((float) animator.getAnimatedValue())); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); currentBackgroundDrawable.setPatternAlpha(1f); } }); valueAnimator.setDuration(250); patternAlphaAnimator.playTogether(valueAnimator); } patternAlphaAnimator.start(); } if (createNewResources) { int[] colors = AndroidUtilities.calcDrawableColor(backgroundDrawable); currentColor = colors[0]; initDrawables(); initPaints(); initServiceMessageColors(backgroundDrawable); updateServiceMessageColor(1f); } } } private void initDrawables() { Map chatDrawablesMap = Theme.getThemeDrawablesMap(); for (Map.Entry entry : chatDrawablesMap.entrySet()) { Drawable drawable; switch (entry.getKey()) { case Theme.key_drawable_msgIn: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, false, false, this); break; case Theme.key_drawable_msgInSelected: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, false, true, this); break; case Theme.key_drawable_msgInMedia: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_MEDIA, false, false, this); break; case Theme.key_drawable_msgInMediaSelected: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_MEDIA, false, true, this); break; case Theme.key_drawable_msgOut: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, true, false, this); break; case Theme.key_drawable_msgOutSelected: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, true, true, this); break; case Theme.key_drawable_msgOutMedia: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_MEDIA, true, false, this); break; case Theme.key_drawable_msgOutMediaSelected: drawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_MEDIA, true, true, this); break; default: drawable = entry.getValue(); Drawable.ConstantState constantState = drawable.getConstantState(); if (constantState != null) { drawable = constantState.newDrawable().mutate(); } else { drawable = null; } if (drawable != null) { String colorKey = Theme.getThemeDrawableColorKey(entry.getKey()); if (colorKey != null) { Integer color = getColor(colorKey); if (color == null) { color = Theme.getColor(colorKey); } Theme.setDrawableColor(drawable, color); } } } if (drawable != null) { currentDrawables.put(entry.getKey(), drawable); } } } private void initPaints() { Map chatPaintsMap = Theme.getThemePaintsMap(); for (Map.Entry entry : chatPaintsMap.entrySet()) { Paint oldPaint = entry.getValue(); Paint newPaint; if (oldPaint instanceof TextPaint) { newPaint = new TextPaint(); newPaint.setTextSize(oldPaint.getTextSize()); newPaint.setTypeface(oldPaint.getTypeface()); } else { newPaint = new Paint(); } if ((oldPaint.getFlags() & Paint.ANTI_ALIAS_FLAG) != 0) { newPaint.setFlags(Paint.ANTI_ALIAS_FLAG); } String colorKey = Theme.getThemePaintColorKey(entry.getKey()); if (colorKey != null) { Integer color = getColor(colorKey); if (color == null) { color = Theme.getColor(colorKey); } newPaint.setColor(color); } currentPaints.put(entry.getKey(), newPaint); } } int startServiceTextColor; int startServiceLinkColor; int startServiceButtonColor; int startServiceIconColor; int startServiceColor; int startSelectedBackgroundColor; Bitmap startServiceBitmap; int currentServiceColor; boolean drawServiceGradient; boolean drawSelectedGradient; private void initServiceMessageColors(Drawable backgroundDrawable) { int[] result = AndroidUtilities.calcDrawableColor(backgroundDrawable); int currentServiceMessageColor = result[0]; Integer serviceColor = getCurrentColor(Theme.key_chat_serviceBackground); Integer selectedBackgroundColor = getCurrentColor(Theme.key_chat_selectedBackground); Integer serviceColor2 = serviceColor; if (serviceColor == null) { serviceColor = currentServiceMessageColor; } currentServiceColor = serviceColor; drawServiceGradient = backgroundDrawable instanceof MotionBackgroundDrawable && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; drawSelectedGradient = drawServiceGradient; if (drawServiceGradient) { serviceBitmap = Bitmap.createBitmap(60, 80, Bitmap.Config.ARGB_8888); serviceBitmapSource = ((MotionBackgroundDrawable) backgroundDrawable).getBitmap(); serviceCanvas = new Canvas(serviceBitmap); serviceCanvas.drawBitmap(serviceBitmapSource, 0, 0, null); serviceShader = new BitmapShader(serviceBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); serviceShaderSource = new BitmapShader(serviceBitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); useSourceShader = true; } else { serviceBitmap = null; serviceShader = null; } Paint actionBackgroundPaint = getPaint(Theme.key_paint_chatActionBackground); Paint actionBackgroundSelectedPaint = getPaint(Theme.key_paint_chatActionBackgroundSelected); Paint msgBackgroundSelectedPaint = getPaint(Theme.key_paint_chatMessageBackgroundSelected); if (actionBackgroundPaint != null) { if (drawServiceGradient) { ColorMatrix colorMatrix = new ColorMatrix(); colorMatrix.setSaturation(((MotionBackgroundDrawable) backgroundDrawable).getIntensity() >= 0 ? 1.8f : 0.5f); actionBackgroundPaint.setAlpha(127); actionBackgroundPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); actionBackgroundPaint.setShader(serviceShaderSource); actionBackgroundSelectedPaint.setAlpha(127); actionBackgroundSelectedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); actionBackgroundSelectedPaint.setShader(serviceShaderSource); } else { actionBackgroundPaint.setColorFilter(null); actionBackgroundPaint.setShader(null); actionBackgroundSelectedPaint.setColorFilter(null); actionBackgroundSelectedPaint.setShader(null); } } if (msgBackgroundSelectedPaint == null) { msgBackgroundSelectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); currentPaints.put(Theme.key_paint_chatMessageBackgroundSelected, msgBackgroundSelectedPaint); } if (drawSelectedGradient) { ColorMatrix colorMatrix2 = new ColorMatrix(); AndroidUtilities.adjustSaturationColorMatrix(colorMatrix2, 2.5f); AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix2, .75f); msgBackgroundSelectedPaint.setAlpha(64); msgBackgroundSelectedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix2)); msgBackgroundSelectedPaint.setShader(serviceShaderSource); } else { if (selectedBackgroundColor == null) { selectedBackgroundColor = getColor(Theme.key_chat_selectedBackground); } msgBackgroundSelectedPaint.setColor(selectedBackgroundColor); msgBackgroundSelectedPaint.setColorFilter(null); msgBackgroundSelectedPaint.setShader(null); } } private void updateServiceMessageColor(float progress) { if (currentPaints.isEmpty()) { return; } Paint actionBackgroundPaint = getPaint(Theme.key_paint_chatActionBackground); Paint actionBackgroundSelectedPaint = getPaint(Theme.key_paint_chatActionBackgroundSelected); Paint msgBackgroundSelectedPaint = getPaint(Theme.key_paint_chatMessageBackgroundSelected); int serviceColor = currentServiceColor; int serviceTextColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceText, true); int serviceLinkColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); int serviceButtonColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); int serviceIconColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceIcon, true); if (progress != 1f) { serviceColor = ColorUtils.blendARGB(startServiceColor, serviceColor, progress); serviceTextColor = ColorUtils.blendARGB(startServiceTextColor, serviceTextColor, progress); serviceLinkColor = ColorUtils.blendARGB(startServiceLinkColor, serviceLinkColor, progress); serviceButtonColor = ColorUtils.blendARGB(startServiceButtonColor, serviceButtonColor, progress); serviceIconColor = ColorUtils.blendARGB(startServiceIconColor, serviceIconColor, progress); } if (actionBackgroundPaint != null && !drawServiceGradient) { actionBackgroundPaint.setColor(serviceColor); actionBackgroundSelectedPaint.setColor(serviceColor); } currentColor = serviceColor; Paint linkPaint = getPaint(Theme.key_paint_chatActionText); if (linkPaint != null) { ((TextPaint) linkPaint).linkColor = serviceLinkColor; getPaint(Theme.key_paint_chatActionText).setColor(serviceTextColor); getPaint(Theme.key_paint_chatBotButton).setColor(serviceButtonColor); } Theme.setDrawableColor(getDrawable(Theme.key_drawable_msgStickerCheck), serviceTextColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_msgStickerClock), serviceTextColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_msgStickerHalfCheck), serviceTextColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_msgStickerPinned), serviceTextColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_msgStickerReplies), serviceTextColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_msgStickerViews), serviceTextColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_botInline), serviceIconColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_botLink), serviceIconColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_botInvite), serviceIconColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_commentSticker), serviceIconColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_goIcon), serviceIconColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_replyIcon), serviceIconColor); Theme.setDrawableColor(getDrawable(Theme.key_drawable_shareIcon), serviceIconColor); if (serviceCanvas != null && serviceBitmapSource != null) { if (progress != 1f && startServiceBitmap != null) { useSourceShader = false; serviceCanvas.drawBitmap(startServiceBitmap, 0, 0, null); paint.setAlpha((int) (255 * progress)); serviceCanvas.drawBitmap(serviceBitmapSource, 0, 0, paint); if (actionBackgroundPaint != null) { actionBackgroundPaint.setShader(serviceShader); actionBackgroundSelectedPaint.setShader(serviceShader); } if (msgBackgroundSelectedPaint != null) { msgBackgroundSelectedPaint.setShader(serviceShader); } } else { useSourceShader = true; serviceCanvas.drawBitmap(serviceBitmapSource, 0, 0, null); if (actionBackgroundPaint != null) { actionBackgroundPaint.setShader(serviceShaderSource); actionBackgroundSelectedPaint.setShader(serviceShaderSource); } if (msgBackgroundSelectedPaint != null) { msgBackgroundSelectedPaint.setShader(serviceShaderSource); } } } } private Drawable getBackgroundDrawableFromTheme(EmojiThemes chatTheme, int prevPhase) { Drawable drawable; if (chatTheme.showAsDefaultStub) { Theme.ThemeInfo themeInfo = EmojiThemes.getDefaultThemeInfo(isDark); HashMap currentColors = chatTheme.getPreviewColors(currentAccount, isDark ? 1 : 0); String wallpaperLink = chatTheme.getWallpaperLink(isDark ? 1 : 0); Theme.BackgroundDrawableSettings settings = Theme.createBackgroundDrawable(themeInfo, currentColors, wallpaperLink, prevPhase); drawable = settings.wallpaper; } else { Integer backgroundColor = getColor(Theme.key_chat_wallpaper); Integer gradientColor1 = getColor(Theme.key_chat_wallpaper_gradient_to1); Integer gradientColor2 = getColor(Theme.key_chat_wallpaper_gradient_to2); Integer gradientColor3 = getColor(Theme.key_chat_wallpaper_gradient_to3); if (gradientColor3 == null) { gradientColor3 = 0; } MotionBackgroundDrawable motionDrawable = new MotionBackgroundDrawable(); motionDrawable.setPatternBitmap(chatTheme.getWallpaper(isDark ? 1 : 0).settings.intensity); motionDrawable.setColors(backgroundColor, gradientColor1, gradientColor2, gradientColor3, 0,true); motionDrawable.setPhase(prevPhase); int patternColor = motionDrawable.getPatternColor(); final boolean isDarkTheme = isDark; chatTheme.loadWallpaper(isDark ? 1 : 0, pair -> { if (pair == null) { return; } long themeId = pair.first; Bitmap bitmap = pair.second; if (this.chatTheme != null && themeId == this.chatTheme.getTlTheme(isDark ? 1 : 0).id && bitmap != null) { if (patternIntensityAnimator != null) { patternIntensityAnimator.cancel(); } int intensity = chatTheme.getWallpaper(isDarkTheme ? 1 : 0).settings.intensity; motionDrawable.setPatternBitmap(intensity, bitmap); motionDrawable.setPatternColorFilter(patternColor); patternIntensityAnimator = ValueAnimator.ofFloat(0, 1f); patternIntensityAnimator.addUpdateListener(animator -> { float value = (float) animator.getAnimatedValue(); motionDrawable.setPatternAlpha(value); }); patternIntensityAnimator.setDuration(250); patternIntensityAnimator.start(); } }); drawable = motionDrawable; } return drawable; } private int getCurrentColorOrDefault(String key, boolean ignoreAnimation) { Integer color = getCurrentColor(key, ignoreAnimation); if (color == null) { color = Theme.getColor(key, null, ignoreAnimation); } return color; } } @Override protected boolean allowPresentFragment() { return !inPreviewMode; } @Override protected boolean hideKeyboardOnShow() { if (threadMessageObject != null && threadMessageObject.getRepliesCount() == 0 && ChatObject.canSendMessages(currentChat)) { return false; } return super.hideKeyboardOnShow(); } @Override public boolean isLightStatusBar() { if (reportType >= 0) { Theme.ResourcesProvider resourcesProvider = getResourceProvider(); int color; if (resourcesProvider != null) { color = resourcesProvider.getColorOrDefault(Theme.key_actionBarActionModeDefault); } else { color = Theme.getColor(Theme.key_actionBarActionModeDefault, null, true); } return ColorUtils.calculateLuminance(color) > 0.7f; } return super.isLightStatusBar(); } public MessageObject.GroupedMessages getGroup(long id) { return groupedMessagesMap.get(id); } }