/* * 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 static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.lerp; import static org.telegram.messenger.LocaleController.formatPluralStringComma; import static org.telegram.messenger.LocaleController.formatString; import static org.telegram.messenger.LocaleController.getString; import static org.telegram.ui.bots.AffiliateProgramFragment.percents; 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.ContentValues; 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.LinearGradient; 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.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.os.SystemClock; import android.os.Vibrator; import android.provider.ContactsContract; import android.provider.MediaStore; import android.telephony.TelephonyManager; 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.ClickableSpan; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.text.style.URLSpan; import android.util.Pair; 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 androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.collection.LongSparseArray; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.dynamicanimation.animation.FloatValueHolder; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; import androidx.recyclerview.widget.ChatListItemAnimator; import androidx.recyclerview.widget.DefaultItemAnimator; 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.BotForumHelper; import org.telegram.messenger.BotInlineKeyboard; import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChannelBoostsController; import org.telegram.messenger.ChatMessageSharedResources; import org.telegram.messenger.ChatMessagesMetadataController; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; import org.telegram.messenger.CodeHighlighting; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.DocumentObject; import org.telegram.messenger.DownloadController; import org.telegram.messenger.Emoji; import org.telegram.messenger.EmojiData; import org.telegram.messenger.FactCheckController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.FlagSecureReason; import org.telegram.messenger.HashtagSearchController; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LanguageDetector; import org.telegram.messenger.LiteMode; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagePreviewParams; import org.telegram.messenger.MessageSuggestionParams; 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.SvgHelper; import org.telegram.messenger.Timer; import org.telegram.messenger.TranslateController; 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.camera.CameraView; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.messenger.utils.OnPostDrawView; import org.telegram.messenger.utils.PhotoUtilities; import org.telegram.messenger.utils.RectFMergeBounding; import org.telegram.messenger.utils.tlutils.TlUtils; import org.telegram.messenger.voip.VoIPService; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_account; import org.telegram.tgnet.tl.TL_bots; import org.telegram.tgnet.tl.TL_phone; import org.telegram.tgnet.tl.TL_stories; 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.INavigationLayout; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.ActionBar.theme.ThemeKey; import org.telegram.ui.Adapters.FiltersView; import org.telegram.ui.Adapters.MessagesSearchAdapter; import org.telegram.ui.Business.BusinessBotButton; import org.telegram.ui.Business.BusinessLinksActivity; import org.telegram.ui.Business.BusinessLinksController; import org.telegram.ui.Business.BusinessLinksEmptyView; import org.telegram.ui.Business.QuickRepliesActivity; import org.telegram.ui.Business.QuickRepliesController; import org.telegram.ui.Business.QuickRepliesEmptyView; import org.telegram.ui.Cells.BaseCell; 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.ProfileChannelCell; import org.telegram.ui.Cells.ShareDialogCell; import org.telegram.ui.Cells.StickerCell; import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.Cells.UserInfoCell; import org.telegram.ui.Components.*; import org.telegram.ui.Components.FloatingDebug.FloatingDebugController; import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider; import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; import org.telegram.ui.Components.Premium.boosts.BoostDialogs; import org.telegram.ui.Components.Premium.boosts.GiftInfoBottomSheet; import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftLinkBottomSheet; import org.telegram.ui.Components.Reactions.ChatSelectionReactionMenuOverlay; import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.blur3.BlurredBackgroundDrawableViewFactory; import org.telegram.ui.Components.blur3.BlurredBackgroundWithFadeDrawable; import org.telegram.ui.Components.blur3.DownscaleScrollableNoiseSuppressor; import org.telegram.ui.Components.blur3.drawable.color.BlurredBackgroundColorProviderThemed; import org.telegram.ui.Components.blur3.source.BlurredBackgroundSourceWrapped; import org.telegram.ui.Components.chat.ChatActivityBottomViewsVisibilityController; import org.telegram.ui.Components.chat.layouts.ChatActivityActionsButtonsLayout; import org.telegram.ui.Components.chat.layouts.ChatActivityChannelButtonsLayout; import org.telegram.ui.Components.chat.ChatInputViewsContainer; import org.telegram.ui.Components.chat.ChatListViewPaddingsAnimator; import org.telegram.ui.Components.chat.ViewPositionWatcher; import org.telegram.ui.Components.chat.WallpaperBitmapProvider; import org.telegram.ui.Components.blur3.source.BlurredBackgroundSource; import org.telegram.ui.Components.blur3.source.BlurredBackgroundSourceBitmap; import org.telegram.ui.Components.blur3.source.BlurredBackgroundSourceRenderNode; import org.telegram.ui.Components.blur3.drawable.BlurredBackgroundDrawable; import org.telegram.ui.Components.chat.layouts.ChatActivitySideControlsButtonsLayout; import org.telegram.ui.Components.inset.WindowInsetsStateHolder; import org.telegram.ui.Components.quickforward.QuickShareSelectorOverlayLayout; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.Components.voip.CellFlickerDrawable; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate; import org.telegram.ui.Gifts.GiftSheet; import org.telegram.ui.Stars.StarReactionsOverlay; import org.telegram.ui.Stars.StarsController; import org.telegram.ui.Stars.StarsIntroActivity; import org.telegram.ui.Stars.StarsReactionsSheet; import org.telegram.ui.Stars.MessageSuggestionOfferSheet; import org.telegram.messenger.utils.tlutils.AmountUtils; import org.telegram.ui.Stories.StoriesListPlaceProvider; import org.telegram.ui.Stories.StoriesUtilities; import org.telegram.ui.Stories.PublicStoriesList; import org.telegram.ui.Stories.recorder.HintView2; import org.telegram.ui.Stories.recorder.PreviewView; import org.telegram.ui.Stories.recorder.StoryEntry; import org.telegram.ui.Stories.recorder.StoryRecorder; import org.telegram.ui.TON.TONIntroActivity; import org.telegram.ui.bots.BotAdView; import org.telegram.ui.bots.BotCommandsMenuContainer; import org.telegram.ui.bots.BotCommandsMenuView; import org.telegram.ui.bots.BotWebViewSheet; import org.telegram.ui.bots.WebViewRequestProps; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.InputStream; import java.io.InputStreamReader; 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.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import me.vkryl.android.animator.BoolAnimator; import me.vkryl.android.animator.FactorAnimator; import me.vkryl.core.BitwiseUtils; import me.vkryl.core.reference.ReferenceList; @SuppressWarnings("unchecked") public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, LocationActivity.LocationActivityDelegate, ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate, ChatActivityInterface, FloatingDebugProvider, InstantCameraView.Delegate, FactorAnimator.Target { private final static boolean PULL_DOWN_BACK_FRAGMENT = false; private final static boolean DISABLE_PROGRESS_VIEW = true; private final static int SKELETON_DISAPPEAR_MS = 200; private static int SKELETON_LIGHT_OVERLAY_ALPHA = 22; private static float SKELETON_SATURATION = 1.4f; public final static int DEBUG_SHARE_ALERT_MODE_NORMAL = 0, DEBUG_SHARE_ALERT_MODE_LESS = 1, DEBUG_SHARE_ALERT_MODE_MORE = 2; public int shareAlertDebugMode = DEBUG_SHARE_ALERT_MODE_NORMAL; public boolean shareAlertDebugTopicsSlowMotion; public boolean justCreatedTopic = false; public boolean justCreatedChat = false; protected TLRPC.Chat currentChat; protected TLRPC.User currentUser; protected TLRPC.EncryptedChat currentEncryptedChat; private boolean userBlocked; private long chatInviterId; private static final LongSparseArray> chatMessageCellsCache = new LongSparseArray>(); private HashMap alreadyPlayedStickers = new HashMap<>(); private final WindowInsetsStateHolder windowInsetsStateHolder = new WindowInsetsStateHolder(this::checkInsets); private BlurredBackgroundColorProviderThemed blurredBackgroundColorProvider; private BlurredBackgroundColorProviderThemed blurredBackgroundColorProviderWhite; private final ReferenceList glassAttachedViews = new ReferenceList<>(); private final @Nullable DownscaleScrollableNoiseSuppressor scrollableViewNoiseSuppressor; private final int recommendedAdditionalSizeY; private final @Nullable BlurredBackgroundSourceRenderNode glassBackgroundSourceRenderNode; private final @Nullable BlurredBackgroundSourceRenderNode glassBackgroundSourceFrostedRenderNode; private final @NonNull BlurredBackgroundDrawableViewFactory glassBackgroundDrawableFactory; private final @NonNull BlurredBackgroundDrawableViewFactory glassBackgroundDrawableFactoryFrosted; private final @Nullable BlurredBackgroundSourceRenderNode navbarContentSourceMessages; // blurred messages list source private final @Nullable BlurredBackgroundDrawable navbarContentSourceMessagesDrawable; // blurred messages list drawable private final @Nullable BlurredBackgroundSourceRenderNode navbarContentSourceWallpaperAndMessagesRenderNode; private final @NonNull BlurredBackgroundSourceWrapped navbarContentSourceWallpaper; private final @NonNull BlurredBackgroundDrawableViewFactory navbarContentDrawableFactory; private Dialog closeChatDialog; private boolean showCloseChatDialogLater; private FrameLayout progressView; private View progressView2; private FrameLayout bottomOverlay; private ChatInputViewsContainer chatInputViewsContainer; private FrameLayout chatInputBubbleContainer; private FrameLayout chatInputInAppContainer; private WallpaperBitmapProvider wallpaperBitmapProvider = new WallpaperBitmapProvider(); protected ChatActivityEnterView chatActivityEnterView; private ChatActivityEnterTopView chatActivityEnterTopView; private int chatActivityEnterViewAnimateFromTop; private boolean chatActivityEnterViewAnimateBeforeSending; private ActionBarMenuItem.Item timeItem2; private ActionBarMenu.LazyItem attachItem; private ActionBarMenuItem.Item savedChatsItem, savedChatsGap;; private ActionBarMenuItem headerItem; private ActionBarMenu.LazyItem editTextItem; protected ActionBarMenuItem searchItem; private ActionBarMenuItem.Item translateItem; private ActionBarMenuItem searchIconItem; private ActionBarMenu.LazyItem audioCallIconItem; private boolean searchItemVisible; private RadialProgressView progressBar; private ActionBarMenuItem.Item addContactItem; private ActionBarMenuItem.Item clearHistoryItem; private ActionBarMenuItem.Item viewAsTopics; private ActionBarMenuItem.Item closeTopicItem; private ActionBarMenuItem.Item openForumItem; private ClippingImageView animatingImageView; private ThanosEffect chatListThanosEffect; private ChatListViewPaddingsAnimator chatListViewPaddingsAnimator; private ChatListRecyclerView chatListView; private ChatListItemAnimator chatListItemAnimator; private GridLayoutManagerFixed chatLayoutManager; private ChatActivityAdapter chatAdapter; private UnreadCounterTextView bottomOverlayChatText; private boolean bottomOverlayLinks; private LinkSpanDrawable.LinksTextView bottomOverlayLinksText; private TextView bottomOverlayText; private TextView bottomOverlayStartButton; private RadialProgressView bottomOverlayProgress; private AnimatorSet bottomOverlayAnimation; private boolean bottomOverlayChatWaitsReply; private HintView2 bottomGiftHintView; private HintView2 bottomSuggestHintView; private ChatActivityChannelButtonsLayout bottomChannelButtonsLayout; private ChatActivityActionsButtonsLayout actionsButtonsLayout; @Nullable private FrameLayout emptyViewContainer; private LinearLayout emptyViewContent; private ChatGreetingsView greetingsViewContainer; private ChatActionCell greetingsInfo; private QuickRepliesEmptyView quickRepliesEmptyView; private BusinessLinksEmptyView businessLinksEmptyView; public ChatActivityFragmentView contentView; private ChatBigEmptyView bigEmptyView; private ArrayList actionModeViews = new ArrayList<>(); public ChatAvatarContainer avatarContainer; private NumberTextView selectedMessagesCountTextView; private RecyclerListView.OnItemClickListener mentionsOnItemClickListener; private SuggestEmojiView suggestEmojiPanel; private ActionBarMenuItem.Item muteItem; private ActionBarMenuItem.Item muteItemGap; private ActionBarMenuItem.Item feeItemGap; private ActionBarMenuItem.Item feeItemText; private ChatNotificationsPopupWrapper chatNotificationsPopupWrapper; private ChatActivitySideControlsButtonsLayout topButtonsLayout; private ChatActivitySideControlsButtonsLayout sideControlsButtonsLayout; private boolean pagedownButtonShowedByScroll; private int reactionsMentionCount; public Bulletin messageSeenPrivacyBulletin; TextView webBotTitle; public SearchTagsList actionBarSearchTags; public ChatSearchTabs hashtagSearchTabs; private ViewPagerFixed searchViewPager; private int defaultSearchPage; private boolean requestClearSearchPages; private HashtagHistoryView hashtagHistoryView; private AlertDialog scheduleNowDialog; private HintView2 savedMessagesHint; private HintView2 savedMessagesSearchHint; private HintView2 savedMessagesTagHint; private HintView2 groupEmojiPackHint; private HintView2 botMessageHint; private HintView2 factCheckHint; private HintView2 videoConversionTimeHint; private float videoConversionTimeHintY; private TL_stories.TL_premium_boostsStatus boostsStatus; private ChannelBoostsController.CanApplyBoost canApplyBoosts; private BackupImageView replyImageView; private SimpleTextView replyNameTextView; private SimpleTextView replyObjectTextView; private SimpleTextView replyObjectHintTextView; private boolean showTapForForwardingOptionsHit; private Runnable tapForForwardingOptionsHitRunnable; private ImageView replyIconImageView; private ImageView replyCloseImageView; private MentionsContainerView mentionContainer; private AnimatorSet mentionListAnimation; public ChatAttachAlert chatAttachAlert; @Nullable private BlurredFrameLayout topChatPanelView; @Nullable private BlurredFrameLayout topChatPanelView2; private AnimatorSet reportSpamViewAnimator; private AnimatorSet topChatPanelView2Animator; @Nullable private TextView addToContactsButton; private boolean addToContactsButtonArchive; @Nullable private TextView reportSpamButton; @Nullable private TextView restartTopicButton; @Nullable private TranslateButton translateButton; public TopicsTabsView topicsTabs; @Nullable private BusinessBotButton bizBotButton; @Nullable private View topViewSeparator1, topViewSeparator2, topViewSeparator3; @Nullable private LinkSpanDrawable.LinksTextView emojiStatusSpamHint; @Nullable private ImageView closeReportSpam; private BotAdView botAdView; private TextView chatWithAdminTextView; private FragmentContextView fragmentContextView; private FragmentContextView fragmentLocationContextView; private TextView emptyView; private FlickerLoadingView hashtagLoadingView; private StickerEmptyView hashtagSearchEmptyView; private HintView gifHintTextView; private HintView emojiHintTextView; private HintView mediaBanTooltip; private HintView scheduledOrNoSoundHint; private boolean scheduledOrNoSoundHintShown; private HintView scheduledHint; private boolean scheduledHintShown; 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; @Nullable private FrameLayout alertView; private Runnable hideAlertViewRunnable; private TextView alertNameTextView; private TextView alertTextView; private AnimatorSet alertViewAnimator; private final int searchContainerHeight = 44; private FrameLayout searchContainer; private ImageView searchCalendarButton; private ImageView searchUserButton; private AnimatedTextView searchCountText; private AnimatedTextView searchExpandList; private AnimatedTextView searchOtherButton; private ChatActionCell floatingDateView; private TopicSeparator.Cell floatingTopicSeparator; private float intoTopViewTop; private ChatActionCell infoTopView; private int hideDateDelay = 500; public InstantCameraView instantCameraView; private View overlayView; private boolean currentFloatingDateOnScreen; private boolean currentFloatingTopicOnScreen; private boolean currentFloatingTopIsNotMessage; private AnimatorSet floatingDateAnimation; private ValueAnimator floatingTopicAnimation; private float floatingTopicViewAlpha; private boolean scrollingFloatingDate; private boolean scrollingFloatingTopic; private boolean scrollingChatListView; private boolean checkTextureViewPosition; private boolean searchingForUser; private TLRPC.User searchingUserMessages; private TLRPC.Chat searchingChatMessages; public static boolean scrolling; public ReactionsLayoutInBubble.VisibleReaction searchingReaction; public ReactionsLayoutInBubble.VisibleReaction getFilterTag() { return chatAdapter != null && chatAdapter.isFiltered ? searchingReaction : null; } public String getFilterQuery() { return chatAdapter != null && chatAdapter.isFiltered ? searchingQuery : null; } public boolean isFiltered() { return chatAdapter != null && chatAdapter.isFiltered; } public ArrayList getFilteredMessages() { return chatAdapter != null ? chatAdapter.filteredMessages : null; } private boolean searchingFiltered; private boolean searching; private String searchingQuery; private String searchingHashtag; private int hashtagSearchSelectedIndex; private int searchLastCount; private int searchLastIndex; private UndoView undoView; private UndoView topUndoView; private Bulletin pinBulletin; private boolean showPinBulletin; private int pinBullerinTag; protected boolean openKeyboardOnAttachMenuClose; private FlagSecureReason flagSecure; public boolean isFullyVisible; private MessageObject hintMessageObject; private int hintMessageType; private MessageObject hint2MessageObject; private FrameLayout messagesSearchListContainer; public RecyclerListView messagesSearchListView; private MessagesSearchAdapter messagesSearchAdapter; private AnimatorSet messagesSearchListViewAnimation; public static final int MODE_DEFAULT = 0; public static final int MODE_SCHEDULED = 1; public static final int MODE_PINNED = 2; public static final int MODE_SAVED = 3; public static final int MODE_QUICK_REPLIES = 5; public static final int MODE_EDIT_BUSINESS_LINK = 6; public static final int MODE_SEARCH = 7; public static final int MODE_SUGGESTIONS = 8; public static final int SEARCH_THIS_CHAT = 0; public static final int SEARCH_MY_MESSAGES = 1; public static final int SEARCH_PUBLIC_POSTS = 2; public static final int SEARCH_CHANNEL_POSTS = 3; private int searchType; public TL_account.TL_businessChatLink businessLink = null; public String quickReplyShortcut; private int chatMode; private int scheduledMessagesCount = -1; public boolean isSubscriberSuggestions; private String reportTitle; private byte[] reportOption; private String reportMessage; public boolean isReport() { return !TextUtils.isEmpty(reportTitle); } @Nullable private MessageObject threadMessageObject; private MessageObject topicStarterMessageObject; private boolean threadMessageVisible = true; private ArrayList threadMessageObjects; private MessageObject replyMessageHeaderObject; private TLRPC.TL_forumTopic forumTopic; private long threadMessageId; private int replyOriginalMessageId; public TLRPC.Chat replyOriginalChat; public boolean isComments; public boolean isTopic; private boolean threadMessageAdded; private boolean scrollToThreadMessage; private int threadMaxInboxReadId; private int threadMaxOutboxReadId; private int replyMaxReadId; private Runnable delayedReadRunnable; private final SparseArray pendingSendMessagesDict = new SparseArray<>(); private final ArrayList pendingSendMessages = new ArrayList<>(); private int threadUnreadMessagesCount; private boolean convertingToast, convertingToastShown; private int convertingToastMessageId; public ArrayList animatingMessageObjects = new ArrayList<>(); private final HashMap animatingDocuments = new HashMap<>(); private MessageObject needAnimateToMessage; private int scrollToPositionOnRecreate = -1; private int scrollToOffsetOnRecreate = 0; private final ArrayList pollsToCheck = 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 int maxPinnedMessageId; 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; public boolean loadingPinnedMessagesList; private boolean pinnedEndReached; public void reloadPinnedMessages() { pinnedMessageIds.clear(); pinnedMessageObjects.clear(); currentPinnedMessageId = 0; loadedPinnedMessagesCount = 0; totalPinnedMessagesCount = 0; updatePinnedMessageView(true); getMediaDataController().loadPinnedMessages(getDialogId(), 0, chatInfo == null ? 0 : chatInfo.pinned_msg_id); loadingPinnedMessagesList = true; updatePinnedTopicStarterMessage(); } private AnimatorSet editButtonAnimation; private AnimatorSet forwardButtonAnimation; SparseIntArray dateObjectsStableIds = new SparseIntArray(); SparseIntArray conversionObjectsStableIds = new SparseIntArray(); public static int lastStableId = 10; private boolean openSearchKeyboard; private boolean waitingForReplyMessageLoad; private boolean ignoreAttachOnPause; private boolean allowStickersPanel = true; 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 boolean forbidForwardingWithDismiss; public MessagePreviewParams messagePreviewParams; public MessageSuggestionParams messageSuggestionParams; private CharSequence formwardingNameText; private MessageObject forwardingMessage; private MessageObject.GroupedMessages forwardingMessageGroup; private MessageObject.GroupedMessages replyingQuoteGroup; public MessageObject replyingTopMessage; private ReplyQuote replyingQuote; private boolean ignoreDraft; private MessageObject replyingMessageObject; private int editingMessageObjectReqId; public 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 boolean replyImageHasMediaSpoiler; private int pinnedImageSize; private int pinnedImageCacheType; private boolean pinnedImageHasBlur; private TLRPC.PhotoSize pinnedImageLocation; private TLRPC.PhotoSize pinnedImageThumbLocation; private TLObject pinnedImageLocationObject; private int linkSearchRequestId; public 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 LongSparseIntArray clearingHistoryArr = new LongSparseIntArray(); boolean isClearingHistory() { return clearingHistoryArr.get(getThreadId(), 0) != 0; } void setClearingHistory(long threadId, boolean isClearingHistory) { clearingHistoryArr.put(threadId, isClearingHistory ? 1 : 0); } 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<>(); private SparseArray> messagesByDaysSorted = new SparseArray<>(); private LongSparseArray conversionMessages = new LongSparseArray<>(); public 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 = true; private boolean firstLoading = true; private boolean chatWasReset; private boolean firstUnreadSent; private int loadsCount; private int last_message_id = 0; private long mergeDialogId; private boolean sentBotStart; private long startMessageAppearTransitionMs; private List messageSkeletons = new ArrayList<>(); private int lastSkeletonCount; private int lastSkeletonMessageCount; private Paint skeletonPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint skeletonServicePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private ColorMatrix skeletonColorMatrix = new ColorMatrix(); private Theme.MessageDrawable.PathDrawParams skeletonBackgroundCacheParams = new Theme.MessageDrawable.PathDrawParams(); private Theme.MessageDrawable skeletonBackgroundDrawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, false, false, new Theme.ResourcesProvider() { @Override public int getColor(int key) { return getThemedColor(key); } }); private long skeletonLastUpdateTime; private int skeletonGradientWidth; private int skeletonTotalTranslation; private Matrix skeletonMatrix = new Matrix(); private LinearGradient skeletonGradient; private int skeletonColor0; private int skeletonColor1; private Paint skeletonOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Matrix skeletonOutlineMatrix = new Matrix(); private LinearGradient skeletonOutlineGradient; public boolean forceDisallowApplyWallpeper; public boolean forceDisallowRedrawThemeDescriptions; private boolean waitingForGetDifference; private int initialMessagesSize; private boolean loadInfo; private boolean historyPreloaded; private int migrated_to; private boolean firstMessagesLoaded; private boolean clearOnLoad; private boolean clearOnLoadButIsNewTopic; private int clearOnLoadAndScrollMessageId = -1, clearOnLoadAndScrollOffset; private boolean topicChangedFromMessage; private Runnable closeInstantCameraAnimation; { skeletonOutlinePaint.setStyle(Paint.Style.STROKE); skeletonOutlinePaint.setStrokeWidth(AndroidUtilities.dp(1)); } private String textToSet; private boolean premiumInvoiceBot; private boolean showScrollToMessageError; private int startLoadFromMessageId; private int startReplyTo; 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; public int highlightMessageId = Integer.MAX_VALUE; public boolean showNoQuoteAlert; public boolean highlightMessageQuoteFirst; private long highlightMessageQuoteFirstTime; public String highlightMessageQuote; public Integer highlightTaskId; public int highlightMessageQuoteOffset = -1; 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; public ProfileChannelCell.ChannelMessageFetcher profileChannelMessageFetcher; public ProfileBirthdayEffect.BirthdayEffectFetcher birthdayAssetsFetcher; private LongSparseArray botInfo = new LongSparseArray<>(); private String botUser; private long inlineReturn; private String voiceChatHash; private boolean openVideoChat; private boolean livestream; private String attachMenuBotToOpen; private String attachMenuBotStartCommand; private MessageObject botButtons; private MessageObject botReplyButtons; private int botsCount; private boolean hasBotsCommands; private boolean hasQuickReplies; 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 Bitmap scrimBlurBitmap; private BitmapShader scrimBlurBitmapShader; private Paint scrimBlurBitmapPaint; private Matrix scrimBlurMatrix; private Paint scrimPaint; private Paint actionBarBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private float scrimPaintAlpha = 0f; private boolean scrimProgressDirection; private View scrimView; private float scrimViewAlpha = 1f; private float scrimViewProgress = 0f; private Integer scrimViewReaction; private Integer scrimViewTask; private int scrimViewReactionOffset; private boolean scrimViewReactionAnimated; 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 final 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 remainingStr; if (remaining < 24 * 60 * 60) { remainingStr = AndroidUtilities.formatDuration(remaining, false, true); } else { remainingStr = LocaleController.formatPluralString("Days", Math.round(remaining / (24 * 60 * 60.0f))); } menuDeleteItem.setSubtext(LocaleController.formatString(R.string.AutoDeleteIn, remainingStr)); AndroidUtilities.runOnUIThread(updateDeleteItemRunnable, 1000); } }; private ChatActivityDelegate chatActivityDelegate; private RecyclerAnimationScrollHelper chatScrollHelper; private int postponedScrollMinMessageId; private int postponedScrollToLastMessageQueryIndex; private int postponedScrollMessageId; private boolean fakePostponedScroll; private boolean postponedScrollIsCanceled; private static ArrayList textSelectionHelpersCache; private ChatActivityTextSelectionHelper textSelectionHelper; private ChatMessageCell slidingView; private boolean maybeStartTrackingSlidingView; private boolean startedTrackingSlidingView; private boolean canShowPagedownButton; private TextSelectionHint textSelectionHint; private boolean textSelectionHintWasShowed; private float lastTouchY; ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate; private ChatMessageCell dummyMessageCell; protected 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 boolean openImport; public float chatListViewPaddingTop; public float paddingTopHeight; public int chatListViewPaddingVisibleOffset; private int contentPaddingTop; private float contentPanTranslation; private float contentPanTranslationT; private float floatingDateViewOffset; private float floatingTopicViewOffset; private float topChatPanelViewOffset; private float topChatPanelView2Offset; private float pinnedMessageEnterOffset; private float topViewOffset; private TLRPC.Document preloadedGreetingsSticker; private boolean forceHistoryEmpty; private boolean invalidateChatListViewTopPadding; private long activityResumeTime; private int transitionAnimationIndex; private int transitionAnimationGlobalIndex; 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 QuickShareSelectorOverlayLayout quickShareSelectorOverlay; private ChatSelectionReactionMenuOverlay selectionReactionsOverlay; private SecretVoicePlayer secretVoicePlayer; private boolean isPauseOnThemePreview; private ChatThemeBottomSheet chatThemeBottomSheet; private ThemeDelegate parentThemeDelegate; private ChatActivity parentChatActivity; public ThemeDelegate themeDelegate; private ChatActivityMemberRequestsDelegate pendingRequestsDelegate; private final ChatMessagesMetadataController chatMessagesMetadataController = new ChatMessagesMetadataController(this); private TLRPC.TL_channels_sendAsPeers sendAsPeersObj; private TL_account.resolvedBusinessChatLinks resolvedChatLink; private boolean switchFromTopics; private boolean switchingFromTopics; private float switchingFromTopicsProgress; public final static int OPTION_RETRY = 0; public final static int OPTION_DELETE = 1; public final static int OPTION_FORWARD = 2; public final static int OPTION_COPY = 3; public final static int OPTION_SAVE_TO_GALLERY = 4; public final static int OPTION_APPLY_LOCALIZATION_OR_THEME = 5; public final static int OPTION_SHARE = 6; public final static int OPTION_SAVE_TO_GALLERY2 = 7; public final static int OPTION_REPLY = 8; public final static int OPTION_ADD_TO_STICKERS_OR_MASKS = 9; public final static int OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC = 10; public final static int OPTION_ADD_TO_GIFS = 11; public final static int OPTION_EDIT = 12; public final static int OPTION_PIN = 13; public final static int OPTION_UNPIN = 14; public final static int OPTION_ADD_CONTACT = 15; public final static int OPTION_COPY_PHONE_NUMBER = 16; public final static int OPTION_CALL = 17; public final static int OPTION_CALL_AGAIN = 18; public final static int OPTION_RATE_CALL = 19; public final static int OPTION_ADD_STICKER_TO_FAVORITES = 20; public final static int OPTION_DELETE_STICKER_FROM_FAVORITES = 21; public final static int OPTION_COPY_LINK = 22; public final static int OPTION_REPORT_CHAT = 23; public final static int OPTION_CANCEL_SENDING = 24; public final static int OPTION_UNVOTE = 25; public final static int OPTION_STOP_POLL_OR_QUIZ = 26; public final static int OPTION_VIEW_REPLIES_OR_THREAD = 27; public final static int OPTION_STATISTICS = 28; public final static int OPTION_TRANSLATE = 29; public final static int OPTION_TRANSCRIBE = 30; public final static int OPTION_HIDE_SPONSORED_MESSAGE = 31; public final static int OPTION_VIEW_IN_TOPIC = 32; public final static int OPTION_ABOUT_REVENUE_SHARING_ADS = 33; public final static int OPTION_REPORT_AD = 34; public final static int OPTION_REMOVE_ADS = 35; public final static int OPTION_SEND_NOW = 100; public final static int OPTION_EDIT_SCHEDULE_TIME = 102; public final static int OPTION_SPEED_PROMO = 103; public final static int OPTION_OPEN_PROFILE = 104; public final static int OPTION_FACT_CHECK = 106; public final static int OPTION_EDIT_PRICE = 107; public final static int OPTION_GIFT = 108; public final static int OPTION_EDIT_TODO = 109; public final static int OPTION_ADD_TO_TODO = 110; public final static int OPTION_SUGGESTION_EDIT_PRICE = 111; public final static int OPTION_SUGGESTION_EDIT_TIME = 112; public final static int OPTION_SUGGESTION_EDIT_MESSAGE = 113; public final static int OPTION_SUGGESTION_ADD_OFFER = 114; private final static int[] allowedNotificationsDuringChatListAnimations = new int[]{ NotificationCenter.messagesRead, NotificationCenter.threadMessagesRead, NotificationCenter.monoForumMessagesRead, 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.savedMessagesDialogsUpdate, NotificationCenter.didApplyNewTheme, NotificationCenter.messageReceivedByServer2 }; 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; public EmojiAnimationsOverlay emojiAnimationsOverlay; public float drawingChatListViewYoffset; public int blurredViewTopOffset; public int blurredViewBottomOffset; public ChatMessageSharedResources sharedResources; private ValueAnimator searchExpandAnimator; private float searchExpandProgress; public static ChatActivity of(long dialogId) { Bundle bundle = new Bundle(); if (dialogId >= 0) { bundle.putLong("user_id", dialogId); } else { bundle.putLong("chat_id", -dialogId); } return new ChatActivity(bundle); } public static ChatActivity of(long dialogId, int messageId) { Bundle bundle = new Bundle(); if (dialogId >= 0) { bundle.putLong("user_id", dialogId); } else { bundle.putLong("chat_id", -dialogId); } bundle.putInt("message_id", messageId); return new ChatActivity(bundle); } 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); UndoView undoView = getUndoView(); if (undoView == null) { return; } undoView.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); } } if (avatarContainer != null) { avatarContainer.ignoreTouches = !show; } } public long getTopicId() { return isTopic || chatMode == MODE_SAVED || chatMode == MODE_QUICK_REPLIES || chatMode == MODE_SUGGESTIONS ? threadMessageId : 0L; } public int getQuickReplyId() { return chatMode == MODE_QUICK_REPLIES ? (int) threadMessageId : 0; } public long getSavedDialogId() { return chatMode == MODE_SAVED ? threadMessageId : 0L; } public boolean isForumInViewAsMessagesMode() { return ChatObject.isForum(currentChat) && !isTopic || ChatObject.isMonoForum(currentChat) && getTopicId() == 0L && !isSubscriberSuggestions; } @Override public List onGetDebugItems() { List items = new ArrayList<>(); if (ChatObject.isChannel(currentChat)) { items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugShareAlert))); String mode; switch (shareAlertDebugMode) { default: mode = LocaleController.getString(R.string.DebugShareAlertDialogsModeNormal); break; case DEBUG_SHARE_ALERT_MODE_LESS: mode = LocaleController.getString(R.string.DebugShareAlertDialogsModeLess); break; case DEBUG_SHARE_ALERT_MODE_MORE: mode = LocaleController.getString(R.string.DebugShareAlertDialogsModeMore); break; } items.add(new FloatingDebugController.DebugItem(LocaleController.formatString(R.string.DebugShareAlertSwitchDialogsMode, mode), () -> { shareAlertDebugMode++; shareAlertDebugMode %= 3; })); items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugShareAlertTopicsSlowMotion), ()-> shareAlertDebugTopicsSlowMotion = !shareAlertDebugTopicsSlowMotion)); } if (currentUser == null) { items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugMessageSkeletons))); items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugMessageSkeletonsLightOverlayAlpha), 0, 255, new AnimationProperties.FloatProperty("") { @Override public void setValue(Object object, float value) { SKELETON_LIGHT_OVERLAY_ALPHA = (int) value; } @Override public Object get(Object object) { return (float) SKELETON_LIGHT_OVERLAY_ALPHA; } })); items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugMessageSkeletonsSaturation), 1f, 10f, new AnimationProperties.FloatProperty("") { @Override public void setValue(Object object, float value) { SKELETON_SATURATION = value; skeletonColorMatrix.setSaturation(value); skeletonServicePaint.setColorFilter(new ColorMatrixColorFilter(skeletonColorMatrix)); } @Override public Object get(Object object) { return SKELETON_SATURATION; } })); } return items; } public boolean allowSendPhotos() { if (currentChat != null && !ChatObject.canSendPhoto(currentChat)) { return false; } else { return true; } } public ThemeDelegate createThemeDelegate() { return new ThemeDelegate(); } public void updateMessages(ArrayList messageObjects, boolean replace) { for (int i = 0; i < messageObjects.size(); i++) { chatAdapter.updateRowWithMessageObject(messageObjects.get(i), false, replace); } } public TextView getOrCreateWebBotTitleView() { if (webBotTitle == null) { webBotTitle = new TextView(getContext()); webBotTitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); webBotTitle.setTypeface(AndroidUtilities.bold()); webBotTitle.setGravity(Gravity.CENTER_VERTICAL); webBotTitle.setSingleLine(true); webBotTitle.setEllipsize(TextUtils.TruncateAt.END); actionBar.addView(webBotTitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 72, 0, 72 + 34, 0)); } return webBotTitle; } private interface ChatActivityDelegate { default void openReplyMessage(int mid) { } default void openHashtagSearch(String hashtag) { } default void onUnpin(boolean all, boolean hide) { } default void onReport() { } } MessagePreviewView forwardingPreviewView; private PhotoViewer.PhotoViewerProvider photoViewerProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview, boolean closing) { return ChatActivity.this.getPlaceForPhoto(messageObject, fileLocation, index, needPreview, false); } @Override public boolean validateGroupId(long groupId) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(groupId); return groupedMessages != null && groupedMessages.messages.size() > 1; } }; private PhotoViewer.PhotoViewerProvider photoViewerPaidMediaProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview, boolean closing) { return ChatActivity.this.getPlaceForPhoto(messageObject, fileLocation, index, needPreview, false); } @Override public boolean validateGroupId(long groupId) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(groupId); return groupedMessages != null && groupedMessages.messages.size() > 1; } @Override public boolean forceAllInGroup() { return true; } }; private ArrayList botContextResults; private PhotoViewer.PhotoViewerProvider botContextProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview, boolean closing) { 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]; // object.clipTopAddition = (int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4)); object.parentView = mentionContainer.getListView(); object.imageReceiver = imageReceiver; object.thumb = imageReceiver.getBitmapSafe(); object.radius = imageReceiver.getRoundRadius(true); return object; } } return null; } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, int scheduleRepeatPeriod, boolean forceDocument) { if (index < 0 || index >= botContextResults.size()) { return; } sendBotInlineResult((TLRPC.BotInlineResult) botContextResults.get(index), notify, scheduleDate, 0); } }; 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 chat_menu_search = -1; private final static int chat_menu_options = -2; private final static int chat_menu_edit_text_options = -3; 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 tag_message = 28; private final static int boost_group = 29; 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 text_quote = 58; private final static int view_as_topics = 59; private final static int search = 40; private final static int topic_close = 60; private final static int open_forum = 61; private final static int translate = 62; private final static int scheduled = 63; private final static int edit_quick_reply = 64; private final static int copy_business_link = 65; private final static int share_business_link = 66; private final static int rename_business_link = 67; private final static int delete_business_link = 68; private final static int share = 69; private final static int open_direct = 70; private final static int remove_fee = 71; private final static int charge_fee = 72; 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.isInSelectionMode() || inPreviewMode || isInsideContainer) { return false; } wasManualScroll = true; boolean result = true; boolean showMenu = true; if (view instanceof ChatActionCell) { ChatActionCell actionCell = (ChatActionCell) view; MessageObject messageObject = actionCell.getMessageObject(); if (messageObject == null) return false; showMenu = messageObject.messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL || actionCell.getMessageObject().type == MessageObject.TYPE_SUGGEST_PHOTO || actionCell.getMessageObject().isWallpaperAction() || actionCell.getMessageObject().type == MessageObject.TYPE_GIFT_STARS; } if (!actionBar.isActionModeShowed() && (!isReport() || showMenu)) { result = createMenu(view, false, true, x, y, true); } else { boolean outside = false; if (view instanceof ChatMessageCell) { outside = !((ChatMessageCell) view).isInsideBackground(x, y); } processRowSelect(view, outside, x, y); } if (view instanceof ChatMessageCell && (((ChatMessageCell) view).getMessageObject() != null && ((ChatMessageCell) view).getMessageObject().type != MessageObject.TYPE_JOINED_CHANNEL)) { startMultiselect(position); result = true; } return result; } }; public RecyclerListView getChatListView() { return chatListView; } private void startMultiselect(int position) { if (isInsideContainer) { return; } 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) { if (isInsideContainer) { return; } Bundle bundle = new Bundle(); int date = ((ChatActionCell) view).getMessageObject().messageOwner.date; bundle.putLong("dialog_id", dialog_id); bundle.putLong("topic_id", getTopicId()); bundle.putInt("type", CalendarActivity.TYPE_CHAT_ACTIVITY); CalendarActivity calendarActivity = new CalendarActivity(bundle, SharedMediaLayout.FILTER_PHOTOS_AND_VIDEOS, date); calendarActivity.setChatActivity(ChatActivity.this); presentFragment(calendarActivity); return; } if (view instanceof ChatActionCell && ((ChatActionCell) view).getMessageObject() != null && ((ChatActionCell) view).getMessageObject().messageOwner.action instanceof TLRPC.TL_messageActionBoostApply) { getNotificationCenter().postNotificationName(NotificationCenter.openBoostForUsersDialog, dialog_id); return; } if (view instanceof ChatActionCell && ((ChatActionCell) view).getMessageObject() != null && ((ChatActionCell) view).getMessageObject().messageOwner.action instanceof TLRPC.TL_messageActionSetSameChatWallPaper) { int messageId = ((ChatActionCell) view).getMessageObject().getReplyMsgId(); AndroidUtilities.runOnUIThread(() -> { scrollToMessageId(messageId, 0, true, 0, true, 0); }, 16); return; } if (actionBar.isActionModeShowed() || isReport()) { 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; } if (view instanceof ChatMessageCell) { MessageObject msg = ((ChatMessageCell) view).getMessageObject(); if (msg != null && msg.type == MessageObject.TYPE_JOINED_CHANNEL) { msg.toggleChannelRecommendations(); msg.forceUpdate = true; ((ChatMessageCell) view).forceResetMessageObject(); view.requestLayout(); if (position >= 0) { chatAdapter.notifyItemChanged(position); } return; } } createMenu(view, true, false, x, y, false); } @Override public boolean hasDoubleTap(View view, int position) { if (chatMode == MODE_QUICK_REPLIES) return false; String reactionStringSetting = getMediaDataController().getDoubleTapReaction(); TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(reactionStringSetting); if (reaction == null && (reactionStringSetting == null || !reactionStringSetting.startsWith("animated_"))) { return false; } boolean available = dialog_id >= 0; if (!available && chatInfo != null) { available = ChatObject.reactionIsAvailable(chatInfo, reaction == null ? reactionStringSetting : reaction.reaction); } if (!available) { return false; } MessageObject messageObject; if (view instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) view).getPrimaryMessageObject(); } else if (view instanceof ChatActionCell) { messageObject = ((ChatActionCell) view).getMessageObject(); } else { return false; } return messageObject != null && !messageObject.isDateObject && !messageObject.isSending() && messageObject.canSetReaction() && !messageObject.isEditing() && !actionBar.isActionModeShowed() && !isSecretChat() && !isInScheduleMode() && !messageObject.isSponsored(); } @Override public void onDoubleTap(View view, int position, float x, float y) { if (getParentActivity() == null || isSecretChat() || isInScheduleMode() || isInPreviewMode() || chatMode == MODE_QUICK_REPLIES) { return; } MessageObject messageObject; if (view instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) view).getPrimaryMessageObject(); } else if (view instanceof ChatActionCell) { messageObject = ((ChatActionCell) view).getMessageObject(); if (messageObject.isDateObject) { return; } } else { return; } if (messageObject.isSecret() || !messageObject.canSetReaction() || messageObject.isExpiredStory() || messageObject.type == MessageObject.TYPE_JOINED_CHANNEL) { return; } ReactionsEffectOverlay.removeCurrent(false); String reactionString = getMediaDataController().getDoubleTapReaction(); if (reactionString.startsWith("animated_")) { boolean available = dialog_id >= 0; if (!available && chatInfo != null) { available = ChatObject.reactionIsAvailable(chatInfo, reactionString); } if (!available) { return; } selectReaction(view, messageObject, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reactionString), true, false, false, false); } else { TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(reactionString); if (reaction == null || messageObject.isSponsored()) { return; } boolean available = dialog_id >= 0; if (!available && chatInfo != null) { available = ChatObject.reactionIsAvailable(chatInfo, reaction.reaction); } if (!available) { return; } selectReaction(view, messageObject, null, null, x, y, ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(reaction), true, false, false, false); } } }; private class ChatActivityEnterViewDelegate implements 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, int scheduleRepeatPeriod, long payStars) { 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 (messagePreviewParams != null && messagePreviewParams.forwardMessages != null && !messagePreviewParams.forwardMessages.messages.isEmpty()) { scheduledMessagesCount += messagePreviewParams.forwardMessages.messages.size(); } updateScheduledInterface(false); } if (!TextUtils.isEmpty(message) && messagePreviewParams != null && messagePreviewParams.forwardMessages != null && !messagePreviewParams.forwardMessages.messages.isEmpty() && messagePreviewParams.quote == null && payStars <= 0) { final ArrayList messagesToForward = new ArrayList<>(); messagePreviewParams.forwardMessages.getSelectedMessages(messagesToForward); boolean showReplyHint = messagesToForward.size() > 0; TLRPC.Peer toPeer = getMessagesController().getPeer(dialog_id); for (int i = 0; i < messagesToForward.size(); ++i) { MessageObject msg = messagesToForward.get(i); if (msg != null && msg.messageOwner != null && !MessageObject.peersEqual(msg.messageOwner.peer_id, toPeer)) { showReplyHint = false; break; } } if (showReplyHint) { Bulletin bulletin = BulletinFactory.of(ChatActivity.this) .createSimpleBulletin( R.raw.hint_swipe_reply, LocaleController.getString(R.string.SwipeToReplyHint), LocaleController.getString(R.string.SwipeToReplyHintMessage) ); RLottieImageView imageView = ((Bulletin.TwoLineLottieLayout) bulletin.getLayout()).imageView; imageView.setScaleX(1.8f); imageView.setScaleY(1.8f); bulletin.show(true); } } if (ChatObject.isForum(currentChat) && !isTopic && replyingMessageObject != null) { long topicId = replyingMessageObject.replyToForumTopic != null ? replyingMessageObject.replyToForumTopic.id : MessageObject.getTopicId(currentAccount, replyingMessageObject.messageOwner, true); if (topicId != 0) { getMediaDataController().cleanDraft(dialog_id, topicId, false); } } hideFieldPanel(notify, scheduleDate, payStars, true); if (chatActivityEnterView != null && chatActivityEnterView.getEmojiView() != null) { chatActivityEnterView.getEmojiView().onMessageSend(); } if (!getMessagesController().premiumFeaturesBlocked() && getMessagesController().transcribeAudioTrialWeeklyNumber <= 0 && !getMessagesController().didPressTranscribeButtonEnough() && !getUserConfig().isPremium() && !TextUtils.isEmpty(message) && messages != null) { for (int i = 1; i < Math.min(5, messages.size()); ++i) { MessageObject msg = messages.get(i); if (msg != null && !msg.isOutOwner() && (msg.isVoice() || msg.isRoundVideo()) && msg.isContentUnread()) { TranscribeButton.showOffTranscribe(msg); } } } } @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 boolean checkCanRemoveRestrictionsByBoosts() { return ChatActivity.this.checkCanRemoveRestrictionsByBoosts(); } @Override public void onTextSelectionChanged(int start, int end) { if (editTextItem == null) { return; } ActionBarMenu menu = actionBar.createMenu(); 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 == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && !isReport()) { editTextItem.setVisibility(View.VISIBLE); checkEditTextItemMenu(); if (headerItem != null) { headerItem.setVisibility(View.GONE); } if (attachItem != null) { attachItem.setVisibility(View.GONE); } } else { ValueAnimator valueAnimator = ValueAnimator.ofFloat(AndroidUtilities.dp(48), 0); valueAnimator.setDuration(220); valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { actionBar.setMenuOffsetSuppressed(true); checkEditTextItemMenu(); 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 == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId() || chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && !isReport()) { editTextItem.setVisibility(View.GONE); // if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { // if (headerItem != null) { // headerItem.setVisibility(View.GONE); // } // if (attachItem != null) { // attachItem.setVisibility(View.VISIBLE); // } // } else { if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } if (attachItem != null) { 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, boolean fromDraft) { 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 { checkEditLinkRemoved(text); waitingForCharaterEnterRunnable = new Runnable() { @Override public void run() { if (this == waitingForCharaterEnterRunnable) { searchLinks(text, false); waitingForCharaterEnterRunnable = null; } } }; AndroidUtilities.runOnUIThread(waitingForCharaterEnterRunnable, AndroidUtilities.WEB_URL == null ? 3000 : 1000); } } if (emojiAnimationsOverlay != null) { emojiAnimationsOverlay.cancelAllAnimations(); } ReactionsEffectOverlay.dismissAll(); if (!fromDraft) { if ((scheduledOrNoSoundHint != null && scheduledOrNoSoundHint.getVisibility() == View.VISIBLE) || (scheduledHint != null && scheduledHint.getVisibility() == View.VISIBLE)) { hideSendButtonHints(); } else { showScheduledHint(); } } } @Override public void onTextSpansChanged(CharSequence text) { searchLinks(text, true); } @Override public void needSendTyping() { if (chatMode == MODE_QUICK_REPLIES || chatMode == MODE_EDIT_BUSINESS_LINK || chatMode == MODE_SUGGESTIONS) return; 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.VISIBLE); } // 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 && !isInPreviewMode()) { 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(0, null); } openAttachMenu(); } @Override public void didPressSuggestionButton() { new MessageSuggestionOfferSheet(getContext(), currentAccount, dialog_id, messageSuggestionParams != null ? messageSuggestionParams: MessageSuggestionParams.empty(), ChatActivity.this, getResourceProvider(), MessageSuggestionOfferSheet.MODE_INPUT, ChatActivity.this::showFieldPanelForSuggestionParams).show(); } @Override public void toggleVideoRecordingPause() { if (instantCameraView != null) { instantCameraView.togglePause(); } } @Override public boolean isVideoRecordingPaused() { return instantCameraView != null && instantCameraView.isPaused(); } @Override public void needStartRecordVideo(int state, boolean notify, int scheduleDate, int scheduleRepeatPeriod, int ttl, long effectId, long stars) { checkInstantCameraView(); if (instantCameraView != null) { if (state == 0) { instantCameraView.showCamera(false); chatListView.stopScroll(); chatAdapter.updateRowsSafe(); } else if (state == 1 || state == 3 || state == 4) { instantCameraView.send(state, notify, scheduleDate, 0, ttl, effectId, stars); } 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() || isInPreviewMode() ? 0 : 1f).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } if (suggestEmojiPanel != null) { suggestEmojiPanel.setVisibility(View.VISIBLE); suggestEmojiPanel.animate().alpha(chatActivityEnterView.isStickersExpanded() || isInPreviewMode() ? 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() { if (getMessagesController().isForum(getDialogId()) && !isTopic) { return false; } return scheduledMessagesCount > 0 && (chatMode == 0 || chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId()); } @Override public void onSendLongClick() { if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } if (scheduledHint != null) { scheduledHint.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; } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); updateTextureViewPosition(false, 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 messagePreviewParams != null && messagePreviewParams.forwardMessages != null && !messagePreviewParams.forwardMessages.messages.isEmpty(); } @Override public void onKeyboardRequested() { checkAdjustResize(); } @Override public boolean onceVoiceAvailable() { return currentUser != null && !UserObject.isUserSelf(currentUser) && !currentUser.bot && currentEncryptedChat == null && chatMode == 0; } @Override public ReplyQuote getReplyQuote() { return replyingQuote; } } 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() == null || chatActivityEnterView.getEditField().getText().length() < 5) { return; } SharedConfig.increaseScheduledOrNoSoundHintShowed(); if (scheduledOrNoSoundHint == null) { scheduledOrNoSoundHint = new HintView(getParentActivity(), 4, themeDelegate); scheduledOrNoSoundHint.createCloseButton(); scheduledOrNoSoundHint.setAlpha(0); scheduledOrNoSoundHint.setVisibility(View.INVISIBLE); scheduledOrNoSoundHint.setText(getString(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); scheduledOrNoSoundHintShown = true; }; private final Runnable showScheduledHintRunnable = () -> { if (getParentActivity() == null || fragmentView == null || chatActivityEnterView == null || forwardingPreviewView != null || getMessagesController().getSendPaidMessagesStars(getDialogId()) > 0) { return; } View anchor = chatActivityEnterView.getSendButton(); if (anchor == null || chatActivityEnterView.getEditField() == null || chatActivityEnterView.getEditField().getText().length() == 0) { return; } SharedConfig.increaseScheduledHintShowed(); if (scheduledHint == null) { scheduledHint = new HintView(getParentActivity(), 4, themeDelegate); scheduledHint.createCloseButton(); scheduledHint.setAlpha(0); scheduledHint.setVisibility(View.INVISIBLE); scheduledHint.setText(LocaleController.getString(R.string.ScheduledHint)); contentView.addView(scheduledHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); } scheduledHint.showForView(anchor, true); scheduledHintShown = true; }; public boolean isInsideContainer; public boolean reversed; private long wallpaperRandomSeed; public ChatActivity(Bundle args) { super(args); navbarContentSourceWallpaper = new BlurredBackgroundSourceWrapped(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && SharedConfig.chatBlurEnabled()) { scrollableViewNoiseSuppressor = new DownscaleScrollableNoiseSuppressor(); recommendedAdditionalSizeY = dp(48); glassBackgroundSourceFrostedRenderNode = new BlurredBackgroundSourceRenderNode(navbarContentSourceWallpaper); glassBackgroundSourceFrostedRenderNode.setOnDrawablesRelativePositionChangeListener(this::invalidateMergedVisibleBlurredPositionsAndSourcesPositions); navbarContentSourceMessages = new BlurredBackgroundSourceRenderNode(null); navbarContentSourceMessages.setOnDrawablesRelativePositionChangeListener(this::invalidateMergedVisibleBlurredPositionsAndSourcesPositions); navbarContentSourceMessagesDrawable = navbarContentSourceMessages.createDrawable(); glassBackgroundDrawableFactoryFrosted = new BlurredBackgroundDrawableViewFactory(glassBackgroundSourceFrostedRenderNode); glassBackgroundDrawableFactoryFrosted.setLiquidGlassEffectAllowed(LiteMode.isEnabled(LiteMode.FLAG_LIQUID_GLASS)); if (LiteMode.isEnabled(LiteMode.FLAG_LIQUID_GLASS)) { glassBackgroundSourceRenderNode = new BlurredBackgroundSourceRenderNode(navbarContentSourceWallpaper); glassBackgroundSourceRenderNode.setOnDrawablesRelativePositionChangeListener(this::invalidateMergedVisibleBlurredPositionsAndSourcesPositions); glassBackgroundDrawableFactory = new BlurredBackgroundDrawableViewFactory(glassBackgroundSourceRenderNode); glassBackgroundDrawableFactory.setLiquidGlassEffectAllowed(LiteMode.isEnabled(LiteMode.FLAG_LIQUID_GLASS)); navbarContentSourceWallpaperAndMessagesRenderNode = null; navbarContentDrawableFactory = new BlurredBackgroundDrawableViewFactory(navbarContentSourceWallpaper); } else { glassBackgroundSourceRenderNode = null; glassBackgroundDrawableFactory = glassBackgroundDrawableFactoryFrosted; navbarContentSourceWallpaperAndMessagesRenderNode = new BlurredBackgroundSourceRenderNode(null); navbarContentSourceWallpaperAndMessagesRenderNode.setOnDrawablesRelativePositionChangeListener(this::invalidateMergedVisibleBlurredPositionsAndSourcesPositions); navbarContentDrawableFactory = new BlurredBackgroundDrawableViewFactory(navbarContentSourceWallpaperAndMessagesRenderNode); } } else { scrollableViewNoiseSuppressor = null; recommendedAdditionalSizeY = 0; glassBackgroundSourceRenderNode = null; glassBackgroundSourceFrostedRenderNode = null; navbarContentSourceMessages = null; navbarContentSourceMessagesDrawable = null; navbarContentSourceWallpaperAndMessagesRenderNode = null; glassBackgroundDrawableFactory = new BlurredBackgroundDrawableViewFactory(navbarContentSourceWallpaper); glassBackgroundDrawableFactoryFrosted = new BlurredBackgroundDrawableViewFactory(navbarContentSourceWallpaper); navbarContentDrawableFactory = new BlurredBackgroundDrawableViewFactory(navbarContentSourceWallpaper); } navbarContentDrawableFactory.setLinkedViewsRef(glassAttachedViews); glassBackgroundDrawableFactory.setLinkedViewsRef(glassAttachedViews); glassBackgroundDrawableFactoryFrosted.setLinkedViewsRef(glassAttachedViews); } @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); quickReplyShortcut = arguments.getString("quick_reply", null); voiceChatHash = arguments.getString("voicechat", null); openVideoChat = arguments.getBoolean("videochat", false); 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); final String inlineQuery = arguments.getString("inline_query"); textToSet = arguments.getString("start_text"); premiumInvoiceBot = arguments.getBoolean("premium_bot", false); startLoadFromMessageId = arguments.getInt("message_id", 0); highlightTaskId = arguments.containsKey("task_id") ? arguments.getInt("task_id", 0) : null; startReplyTo = arguments.getInt("reply_to", 0); startLoadFromDate = arguments.getInt("start_from_date", 0); startFromVideoTimestamp = arguments.getInt("video_timestamp", -1); threadUnreadMessagesCount = arguments.getInt("unread_count", 0); convertingToast = arguments.getBoolean("converting_toast", false); convertingToastMessageId = arguments.getInt("converting_toast_from", 0); isSubscriberSuggestions = arguments.getBoolean("isSubscriberSuggestions", false); if (startFromVideoTimestamp >= 0) { startFromVideoMessageId = startLoadFromMessageId; } reportTitle = arguments.getString("reportTitle", null); reportOption = arguments.getByteArray("reportOption"); reportMessage = arguments.getString("reportMessage", null); pulled = arguments.getBoolean("pulled", false); historyPreloaded = arguments.getBoolean("historyPreloaded", false); if (highlightMessageId != 0 && highlightMessageId != Integer.MAX_VALUE) { startLoadFromMessageId = highlightMessageId; } migrated_to = arguments.getInt("migrated_to", 0); scrollToTopOnResume = arguments.getBoolean("scrollToTopOnResume", false); needRemovePreviousSameChatActivity = arguments.getBoolean("need_remove_previous_same_chat_activity", true); justCreatedChat = arguments.getBoolean("just_created_chat", false); wallpaperRandomSeed = Utilities.random.nextLong(); if (quickReplyShortcut != null) { QuickRepliesController.QuickReply quickReply = QuickRepliesController.getInstance(currentAccount).findReply(quickReplyShortcut); if (quickReply != null) { setQuickReplyId(quickReply.id); } } 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; } } if (ChatObject.isMonoForum(currentChat)) { chatMode = MODE_SUGGESTIONS; isSubscriberSuggestions = !ChatObject.canManageMonoForum(currentAccount, currentChat); } dialog_id = -chatId; if (ChatObject.isChannel(currentChat)) { if (ChatObject.isNotInChat(currentChat) && !ChatObject.isMonoForum(currentChat) && !isThreadChat() && !isInScheduleMode()) { waitingForGetDifference = true; getMessagesController().startShortPoll(currentChat, classGuid, false, isGettingDifference -> { waitingForGetDifference = isGettingDifference; if (!waitingForGetDifference) { firstLoadMessages(); } }); } else { 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; } hasQuickReplies = false; if (currentUser != null && chatMode == 0 && !currentUser.bot) { QuickRepliesController.getInstance(currentAccount).load(); // hasQuickReplies = QuickRepliesController.getInstance(currentAccount).hasReplies(); } } 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 if (chatMode == MODE_EDIT_BUSINESS_LINK) { String businessLinkArgument = arguments.getString("business_link"); if (businessLinkArgument == null) { return false; } businessLink = BusinessLinksController.getInstance(currentAccount).findLink(businessLinkArgument); if (businessLink == null) { return false; } forceEmptyHistory(); } else if (chatMode == MODE_SEARCH) { searchType = arguments.getInt("searchType", 0); searchingHashtag = arguments.getString("searchHashtag", null); searchingQuery = searchingHashtag; if (searchType == 0 || searchingHashtag == null) { return false; } } else { return false; } dialog_id_Long = dialog_id; transitionAnimationGlobalIndex = NotificationCenter.getGlobalInstance().setAnimationInProgress(transitionAnimationGlobalIndex, new int[0]); 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.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); if (isTopic) { getNotificationCenter().addObserver(this, NotificationCenter.updateMentionsCount); getNotificationCenter().addObserver(this, NotificationCenter.didLoadPinnedMessages); } } getNotificationCenter().addObserver(this, NotificationCenter.monoForumMessagesRead); getNotificationCenter().addObserver(this, NotificationCenter.botKeyboardDidLoad); 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); getNotificationCenter().addObserver(this, NotificationCenter.availableEffectsUpdate); getNotificationCenter().addObserver(this, NotificationCenter.starReactionAnonymousUpdate); if (currentEncryptedChat != null) { getNotificationCenter().addObserver(this, NotificationCenter.didVerifyMessagesStickers); } } getNotificationCenter().addObserver(this, NotificationCenter.premiumFloodWaitReceived); getNotificationCenter().addObserver(this, NotificationCenter.messagesDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.loadingMessagesFailed); 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); getNotificationCenter().addObserver(this, NotificationCenter.userIsPremiumBlockedUpadted); 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.closeChatActivity); 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.groupRestrictionsUnlockedByBoosts); getNotificationCenter().addObserver(this, NotificationCenter.customStickerCreated); 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); getNotificationCenter().addObserver(this, NotificationCenter.topicsDidLoaded); getNotificationCenter().addObserver(this, NotificationCenter.chatWasBoostedByUser); 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.savedReactionTagsUpdate); getNotificationCenter().addObserver(this, NotificationCenter.updateAllMessages); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateExtendedMedia); 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); getNotificationCenter().addObserver(this, NotificationCenter.dialogTranslate); getNotificationCenter().addObserver(this, NotificationCenter.dialogIsTranslatable); getNotificationCenter().addObserver(this, NotificationCenter.messageTranslated); getNotificationCenter().addObserver(this, NotificationCenter.messageTranslating); getNotificationCenter().addObserver(this, NotificationCenter.onReceivedChannelDifference); getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().addObserver(this, NotificationCenter.channelRecommendationsLoaded); getNotificationCenter().addObserver(this, NotificationCenter.updateTranscriptionLock); getNotificationCenter().addObserver(this, NotificationCenter.savedMessagesDialogsUpdate); getNotificationCenter().addObserver(this, NotificationCenter.quickRepliesDeleted); getNotificationCenter().addObserver(this, NotificationCenter.quickRepliesUpdated); getNotificationCenter().addObserver(this, NotificationCenter.factCheckLoaded); getNotificationCenter().addObserver(this, NotificationCenter.messagesFeeUpdated); getNotificationCenter().addObserver(this, NotificationCenter.starBalanceUpdated); getNotificationCenter().addObserver(this, NotificationCenter.botForumTopicDidCreate); getNotificationCenter().addObserver(this, NotificationCenter.botForumDraftUpdate); getNotificationCenter().addObserver(this, NotificationCenter.botForumDraftDelete); if (chatMode == MODE_EDIT_BUSINESS_LINK) { getNotificationCenter().addObserver(this, NotificationCenter.businessLinksUpdated); } if (chatMode == MODE_SEARCH) { getNotificationCenter().addObserver(this, NotificationCenter.hashtagSearchUpdated); } if (actionBarSearchTags != null) { actionBarSearchTags.attach(); } 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() && !isTopic) { if (highlightMessageId == startLoadFromMessageId) { needSelectFromMessageId = true; } } else { getMessagesController().setLastCreatedDialogId(dialog_id, chatMode == MODE_SCHEDULED, true); if (chatMode == 0 || chatMode == MODE_SAVED) { if (currentEncryptedChat == null) { getMediaDataController().loadBotKeyboard(MessagesStorage.TopicKey.of(dialog_id, getTopicId())); } getMessagesController().loadPeerSettings(currentUser, currentChat); if (startLoadFromMessageId == 0) { SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); int messageId = sharedPreferences.getInt("diditem" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), 0); if (messageId != 0) { wasManualScroll = true; loadingFromOldPosition = true; startLoadFromMessageOffset = sharedPreferences.getInt("diditemo" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), 0); startLoadFromMessageId = messageId; } } else { showScrollToMessageError = true; needSelectFromMessageId = true; } } } loadInfo = false; if (currentChat != null) { chatInfo = getMessagesController().getChatFull(currentChat.id); groupCall = getMessagesController().getGroupCall(currentChat.id, true); if (ChatObject.isChannel(currentChat) && !getMessagesController().isChannelAdminsLoaded(currentChat.id) && !ChatObject.isMonoForum(currentChat)) { 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); gotChatInfo(); } 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; loading = false; checkDispatchHideSkeletons(false); } if (chatMode != MODE_PINNED && !forceHistoryEmpty) { if (SharedConfig.deviceIsHigh()) { initialMessagesSize = (isThreadChat() && !isTopic) ? 30 : 25; } else { initialMessagesSize = (isThreadChat() && !isTopic) ? 20 : 15; } if (!waitingForGetDifference) { firstLoadMessages(); } } if (chatMode == 0) { if (userId != 0 && currentUser.bot) { AndroidUtilities.runOnUIThread(()-> 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() && !isComments) { getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, getTopicId(), 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, null); } } if (currentUser != null) { TLRPC.UserFull userFull = getMessagesController().getUserFull(currentUser.id); if (userFull != null && userFull.theme != null) { ChatThemeController.getInstance(currentAccount).putThemeIfNeeded(userFull.theme); } } themeDelegate = parentThemeDelegate != null ? parentThemeDelegate : new ThemeDelegate(); if (themeDelegate.isThemeChangeAvailable(false)) { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.needSetDayNightTheme); } if (chatInvite != null) { int timeout = chatInvite.expires - getConnectionsManager().getCurrentTime(); if (timeout < 0) { timeout = 10; } AndroidUtilities.runOnUIThread(chatInviteRunnable = () -> { chatInviteRunnable = null; if (getParentActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { builder.setMessage(getString(R.string.JoinByPeekChannelText)); builder.setTitle(getString(R.string.JoinByPeekChannelTitle)); } else { builder.setMessage(getString(R.string.JoinByPeekGroupText)); builder.setTitle(getString(R.string.JoinByPeekGroupTitle)); } builder.setPositiveButton(getString(R.string.JoinByPeekJoin), (dialogInterface, i) -> { if (bottomOverlayChatText != null) { bottomOverlayChatText.callOnClick(); } }); builder.setNegativeButton(LocaleController.getString(R.string.Cancel), (dialogInterface, i) -> finishFragment()); showDialog(builder.create()); }, timeout * 1000L); } if (ChatObject.isMonoForum(currentChat)) { // reload balance if needed StarsController.getTonInstance(currentAccount).canUseTon(); } if (isTopic || getMessagesController().isMonoForumWithManageRights(dialog_id) && getTopicId() != 0) { getMessagesController().getTopicsController().getTopicRepliesCount(dialog_id, getTopicId()); } if (chatMode != MODE_EDIT_BUSINESS_LINK) { getMessagesController().getSavedMessagesController().preloadDialogs(false); } if (chatMode == MODE_SAVED) { getMessagesController().getSavedMessagesController().checkSavedDialogCount(getTopicId()); } return true; } protected void updateSearchingHashtag(String hashtag) { if (chatMode != MODE_SEARCH) { return; } if (!TextUtils.equals(searchingHashtag, hashtag)) { showMessagesSearchListView(true); searchingHashtag = hashtag; searchingQuery = searchingHashtag; checkHashtagStories(false); clearChatData(true); startMessageAppearTransitionMs = 0; firstMessagesLoaded = false; HashtagSearchController.getInstance(currentAccount).clearSearchResults(searchType); messagesSearchAdapter.notifyDataSetChanged(); messagesSearchListView.requestLayout(); if (messagesSearchListView.getLayoutManager() != null) { messagesSearchListView.getLayoutManager().scrollToPosition(0); } updateSearchListEmptyView(); hashtagSearchEmptyView.showProgress(true); firstLoadMessages(); } } public void resetForReload() { getConnectionsManager().cancelRequestsForGuid(classGuid); getMessagesStorage().cancelTasksForGuid(classGuid); classGuid = ConnectionsManager.generateClassGuid(); startLoadFromMessageId = 0; firstMessagesLoaded = false; clearOnLoad = true; waitingForLoad.clear(); } public void savePositionForTopicChange(long intoTopic) { if (chatListView == null || chatLayoutManager == null || chatLayoutManager.hasPendingScrollPosition()) { clearOnLoadAndScrollMessageId = -1; return; } int centerY = 0;//(chatListView.getHeight() / 2) - chatListView.getPaddingBottom() - chatListView.getPaddingTop(); int top = 0; int messageId = -1; int bestDistance = Integer.MAX_VALUE; for (int i = chatListView.getChildCount() - 1; i >= 0; i--) { final View v = chatListView.getChildAt(i); final int vposition = chatListView.getChildAdapterPosition(v); if (vposition < 0) continue; if (v instanceof ChatMessageCell) { final MessageObject messageObject = ((ChatMessageCell) v).getMessageObject(); if (messageObject == null || messageObject.getTopicId() != intoTopic) continue; final int thisTop = getScrollingOffsetForView(v); final int distance = Math.abs(thisTop + centerY); if (distance < bestDistance) { messageId = messageObject.getId(); top = thisTop; bestDistance = distance; } } } clearOnLoadAndScrollMessageId = messageId; clearOnLoadAndScrollOffset = top; } public void firstLoadMessages() { if (firstMessagesLoaded) { return; } firstMessagesLoaded = true; final Runnable load = () -> { waitingForLoad.add(lastLoadIndex); if (chatMode == MODE_SEARCH) { HashtagSearchController.getInstance(currentAccount).searchHashtag(searchingHashtag, classGuid, searchType, lastLoadIndex++); } else if (startLoadFromDate != 0) { getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, startLoadFromDate, true, 0, classGuid, 4, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } else if (startLoadFromMessageId != 0 && (!isThreadChat() || startLoadFromMessageId == highlightMessageId || isTopic)) { startLoadFromMessageIdSaved = startLoadFromMessageId; if (migrated_to != 0) { mergeDialogId = migrated_to; getMessagesController().loadMessages(mergeDialogId, 0, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, MessagesController.LOAD_AROUND_MESSAGE, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } else { getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, MessagesController.LOAD_AROUND_MESSAGE, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } else { if (historyPreloaded) { lastLoadIndex++; } else { getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } if ((chatMode == 0 || chatMode == MODE_SAVED && getSavedDialogId() == getUserConfig().getClientUserId()) && (!isThreadChat() || isTopic)) { waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, chatMode == MODE_SAVED ? 0 : threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } }; getMessagesController().checkSensitive(this, dialog_id, load, this::finishFragment); } 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.getFragmentStack() == null) { return 0; } int cur = parentLayout.getFragmentStack().indexOf(this); if (cur == -1) { cur = parentLayout.getFragmentStack().size(); } int i = cur; for (int a = 0; a < parentLayout.getFragmentStack().size(); a++) { BaseFragment fragment = parentLayout.getFragmentStack().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 onBeginSlide() { super.onBeginSlide(); if (selectionReactionsOverlay != null && selectionReactionsOverlay.isVisible()) { selectionReactionsOverlay.setHiddenByScroll(true); } } @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(); } ContentPreviewViewer.getInstance().clearDelegate(contentPreviewViewerDelegate); getNotificationCenter().onAnimationFinish(transitionAnimationIndex); NotificationCenter.getGlobalInstance().onAnimationFinish(transitionAnimationGlobalIndex); 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); getNotificationCenter().removeObserver(this, NotificationCenter.loadingMessagesFailed); getNotificationCenter().removeObserver(this, NotificationCenter.premiumFloodWaitReceived); 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.userIsPremiumBlockedUpadted); getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages); getNotificationCenter().removeObserver(this, NotificationCenter.closeChats); getNotificationCenter().removeObserver(this, NotificationCenter.closeChatActivity); getNotificationCenter().removeObserver(this, NotificationCenter.messagesRead); getNotificationCenter().removeObserver(this, NotificationCenter.threadMessagesRead); getNotificationCenter().removeObserver(this, NotificationCenter.monoForumMessagesRead); 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.groupRestrictionsUnlockedByBoosts); getNotificationCenter().removeObserver(this, NotificationCenter.customStickerCreated); 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); getNotificationCenter().removeObserver(this, NotificationCenter.topicsDidLoaded); getNotificationCenter().removeObserver(this, NotificationCenter.chatWasBoostedByUser); 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.savedReactionTagsUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.updateAllMessages); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateExtendedMedia); 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); getNotificationCenter().removeObserver(this, NotificationCenter.dialogTranslate); getNotificationCenter().removeObserver(this, NotificationCenter.dialogIsTranslatable); getNotificationCenter().removeObserver(this, NotificationCenter.messageTranslated); getNotificationCenter().removeObserver(this, NotificationCenter.messageTranslating); getNotificationCenter().removeObserver(this, NotificationCenter.onReceivedChannelDifference); getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.channelRecommendationsLoaded); getNotificationCenter().removeObserver(this, NotificationCenter.updateTranscriptionLock); getNotificationCenter().removeObserver(this, NotificationCenter.savedMessagesDialogsUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.quickRepliesDeleted); getNotificationCenter().removeObserver(this, NotificationCenter.quickRepliesUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.availableEffectsUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.starReactionAnonymousUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.factCheckLoaded); getNotificationCenter().removeObserver(this, NotificationCenter.messagesFeeUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.starBalanceUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.botForumTopicDidCreate); getNotificationCenter().removeObserver(this, NotificationCenter.botForumDraftUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.botForumDraftDelete); if (chatMode == MODE_EDIT_BUSINESS_LINK) { getNotificationCenter().removeObserver(this, NotificationCenter.businessLinksUpdated); } if (chatMode == MODE_SEARCH) { getNotificationCenter().removeObserver(this, NotificationCenter.hashtagSearchUpdated); } if (actionBarSearchTags != null) { actionBarSearchTags.detach(); } 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, getTopicId(), true); } if (currentUser != null) { MediaController.getInstance().stopMediaObserver(); } if (flagSecure != null) { flagSecure.detach(); } 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; INavigationLayout parentLayout = getParentLayout(); if (parentLayout != null && parentLayout.getFragmentStack() != null) { BackButtonMenu.clearPulledDialogs(this, parentLayout.getFragmentStack().indexOf(this) - (replacingChatActivity ? 0 : 1)); } replacingChatActivity = false; if (progressDialogCurrent != null) { progressDialogCurrent.cancel(); progressDialogCurrent = null; } chatMessagesMetadataController.onFragmentDestroy(); if (birthdayAssetsFetcher != null) { birthdayAssetsFetcher.detach(true); birthdayAssetsFetcher = null; } if (starReactionsOverlay != null) { starReactionsOverlay.setMessageCell(null); AndroidUtilities.removeFromParent(starReactionsOverlay); starReactionsOverlay = null; } } private static class ChatActivityTextSelectionHelper extends TextSelectionHelper.ChatListTextSelectionHelper { ChatActivity chatActivity; public void setChatActivity(ChatActivity chatActivity) { cancelAllAnimators(); clear(); textSelectionOverlay = null; this.chatActivity = chatActivity; } @Override public int getParentTopPadding() { return chatActivity == null ? 0 : (int) chatActivity.chatListViewPaddingTop; } @Override public int getParentBottomPadding() { return chatActivity == null ? 0 : chatActivity.blurredViewBottomOffset; } @Override protected int getThemedColor(int key) { return Theme.getColor(key, chatActivity.themeDelegate); } @Override protected Theme.ResourcesProvider getResourcesProvider() { if (chatActivity != null) { return chatActivity.themeDelegate; } return null; } @Override protected boolean canShowQuote() { if (chatActivity != null && chatActivity.getDialogId() == UserObject.VERIFY) { return false; } final boolean noforwards = ( chatActivity != null && chatActivity.getMessagesController().isChatNoForwards(chatActivity.getCurrentChat()) || selectedView != null && selectedView.getMessageObject() != null && selectedView.getMessageObject().messageOwner != null && selectedView.getMessageObject().messageOwner.noforwards ); return !isFactCheck && ( chatActivity != null && chatActivity.getCurrentEncryptedChat() == null && (selectedView == null || selectedView.getMessageObject() != null && selectedView.getMessageObject().type != MessageObject.TYPE_STORY && !selectedView.getMessageObject().isVoiceTranscriptionOpen() && !selectedView.getMessageObject().isInvoice() && !chatActivity.textSelectionHelper.isDescription ) && !chatActivity.getMessagesController().getTranslateController().isTranslatingDialog(chatActivity.dialog_id) && !UserObject.isService(chatActivity.dialog_id) && (!noforwards || (chatActivity.getCurrentChat() == null || ChatObject.canWriteToChat(chatActivity.getCurrentChat()))) ); } @Override protected boolean canCopy() { if (chatActivity != null && chatActivity.getDialogId() == UserObject.VERIFY) { return true; } return chatActivity == null || !( chatActivity.getDialogId() < 0 && chatActivity.getMessagesController().isChatNoForwards(-chatActivity.getDialogId()) || selectedView != null && selectedView.getMessageObject() != null && (selectedView.getMessageObject().messageOwner != null && selectedView.getMessageObject().messageOwner.noforwards) ); } @Override protected void onQuoteClick(MessageObject messageObject, int start, int end, CharSequence text) { if (messageObject == null) { return; } if (chatActivity != null) { end = Math.min(end, start + chatActivity.getMessagesController().quoteLengthMax); if (messageObject.getGroupId() != 0) { MessageObject.GroupedMessages group = chatActivity.getGroup(messageObject.getGroupId()); if (group != null && !group.isDocuments) { messageObject = group.captionMessage; } } if (messageObject == null) { return; } ReplyQuote quote = ReplyQuote.from(messageObject, start, end); if (quote.getText() == null) { return; } if (chatActivity.chatActivityEnterView == null || chatActivity.chatActivityEnterView.getVisibility() != View.VISIBLE) { chatActivity.replyingQuote = quote; chatActivity.replyingMessageObject = messageObject; chatActivity.forbidForwardingWithDismiss = false; chatActivity.messagePreviewParams = new MessagePreviewParams(chatActivity.currentEncryptedChat != null, chatActivity.getMessagesController().isChatNoForwards(chatActivity.currentChat), ChatObject.isMonoForum(chatActivity.currentChat)); chatActivity.messagePreviewParams.updateReply(chatActivity.replyingMessageObject, chatActivity.getGroup(messageObject.getGroupId()), chatActivity.getDialogId(), chatActivity.replyingQuote); Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); args.putBoolean("quote", true); args.putInt("messagesCount", 1); args.putBoolean("canSelectTopics", true); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(chatActivity); chatActivity.presentFragment(fragment); } else { if (chatActivity.actionBar != null && chatActivity.actionBar.isActionModeShowed()) { chatActivity.clearSelectionMode(); } chatActivity.showFieldPanelForReplyQuote(messageObject, quote); if (chatActivity.chatActivityEnterView != null) { chatActivity.chatActivityEnterView.openKeyboard(); } } } } } @Override public View createView(Context context) { Timer t = Timer.create("ChatActivity.createView"); blurredBackgroundColorProvider = new BlurredBackgroundColorProviderThemed(themeDelegate, Theme.key_chat_messagePanelBackground); blurredBackgroundColorProviderWhite = new BlurredBackgroundColorProviderThemed(themeDelegate, Theme.key_windowBackgroundWhite); if (textSelectionHelper == null) { if (textSelectionHelpersCache != null && !textSelectionHelpersCache.isEmpty()) { textSelectionHelper = textSelectionHelpersCache.remove(0); } else { Timer.Task t1 = Timer.start(t, "new ChatActivityTextSelectionHelper"); textSelectionHelper = new ChatActivityTextSelectionHelper(); Timer.done(t1); } textSelectionHelper.setChatActivity(this); } if (isReport()) { 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)); } if (isInsideContainer) { actionBar.setVisibility(View.GONE); } actionBarBackgroundPaint.setColor(getThemedColor(Theme.key_actionBarDefault)); sharedResources = new ChatMessageSharedResources(context); ArrayList chatMessagesCache = chatMessageCellsCache.get(currentAccount); if (chatMessagesCache == null) { chatMessageCellsCache.put(currentAccount, chatMessagesCache = new ArrayList<>()); } if (chatMessagesCache.size() < 10) { int n = 15 - chatMessagesCache.size(); Timer.Task t2 = Timer.start(t, "create ChatMessageCell n=" + n); for (int a = 0; a < n; a++) { chatMessagesCache.add(new ChatMessageCell(context, currentAccount,true, sharedResources, themeDelegate)); } Timer.done(t2); } for (int a = 1; a >= 0; a--) { selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } scheduledOrNoSoundHint = null; scheduledHint = null; infoTopView = null; aspectRatioFrameLayout = null; videoTextureView = null; mediaBanTooltip = null; noSoundHintView = null; forwardHintView = null; checksHintView = null; textSelectionHint = null; emojiButtonRed = null; gifHintTextView = null; emojiHintTextView = 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(isReport())); } actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(final int id) { if (id == -1) { if (actionBar.isActionModeShowed()) { clearSelectionMode(); } else { if (chatMode == MODE_QUICK_REPLIES && (messages.isEmpty() || threadMessageId == 0)) { showQuickRepliesRemoveAlert(); return; } if (chatMode == MODE_EDIT_BUSINESS_LINK && chatActivityEnterView.businessLinkHasChanges()) { showBusinessLinksDiscardAlert(() -> { finishFragment(); }); return; } if (!checkRecordLocked(true, true)) { finishFragment(); } } } else if (id == view_as_topics) { if (getUserConfig().getClientUserId() == dialog_id) { getMessagesController().setSavedViewAs(true); avatarContainer.openProfile(false, true, true); } else { getMessagesController().getTopicsController().toggleViewForumAsMessages(-dialog_id, false); TopicsFragment.prepareToSwitchAnimation(ChatActivity.this); } } else if (id == copy) { SpannableStringBuilder str = new SpannableStringBuilder(); long previousUid = 0; 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); createUndoView(); 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 == share) { share(); } else if (id == open_direct) { if (currentChat == null) return; presentFragment(ChatActivity.of(-currentChat.linked_monoforum_id)); } else if (id == charge_fee ) { long user_id = dialog_id; long parent_id = 0; if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { user_id = getThreadId(); parent_id = dialog_id; } StarsController.getInstance(currentAccount).stopPaidMessages(user_id, parent_id, false, false); } else if (id == remove_fee) { long _user_id = dialog_id; long _parent_id = 0; if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { _user_id = getThreadId(); _parent_id = dialog_id; } final long user_id = _user_id; final long parent_id = _parent_id; StarsController.getInstance(currentAccount).getPaidRevenue(user_id, parent_id, revenue -> { if (getContext() == null) return; AlertsCreator.showAlertWithCheckbox( getContext(), getString(R.string.RemoveMessageFeeTitle), AndroidUtilities.replaceTags(formatString(ChatObject.isMonoForum(currentChat) ? R.string.RemoveMessageFeeMessageChannel : R.string.RemoveMessageFeeMessage, DialogObject.getShortName(user_id))), revenue > 0 ? formatPluralStringComma("RemoveMessageFeeRefund", (int) (long) revenue) : null, getString(R.string.Confirm), refund -> StarsController.getInstance(currentAccount).stopPaidMessages(user_id, parent_id, revenue > 0 && refund, true), resourceProvider ); }); } else if (id == tag_message) { if (tagSelector == null) { showTagSelector(); } else { hideTagSelector(); } } else if (id == save_to) { ArrayList messageObjects = new ArrayList<>(); for (int a = 1; a >= 0; a--) { 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; } if (id == clear_history && ChatObject.isMonoForum(currentChat)) { if (getThreadId() != 0) { final TLRPC.User user = getMessagesController().getUser(getThreadId()); if (user != null) { AlertsCreator.createClearDaysDialogAlert(ChatActivity.this, -1, user, currentChat, true, revoke -> { if (user.id != getThreadId()) { return; } performHistoryClear(false, true); }, getResourceProvider()); } } 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 || ChatObject.isPublic(currentChat))) { 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 != null && 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, MediaDataController.SHORTCUT_TYPE_USER_OR_CHAT); } catch (Exception e) { FileLog.e(e); } } else if (id == boost_group) { if (ChatObject.hasAdminRights(currentChat)) { BoostsActivity boostsActivity = new BoostsActivity(dialog_id); boostsActivity.setBoostsStatus(boostsStatus); presentFragment(boostsActivity); } else { getNotificationCenter().postNotificationName(NotificationCenter.openBoostForUsersDialog, dialog_id); } } else if (id == report) { ReportBottomSheet.openChat(ChatActivity.this); } 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(); } if (messageObject != null && messageObject.isTodo()) { selectedObject = messageObject; processSelectedOption(OPTION_EDIT_TODO); } else { startEditingMessageObject(messageObject); } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } else if (id == edit_quick_reply) { QuickRepliesController.QuickReply currentQuickReply = QuickRepliesController.getInstance(currentAccount).findReply(getQuickReplyId()); QuickRepliesActivity.openRenameReplyAlert(getContext(), currentAccount, quickReplyShortcut, currentQuickReply, getResourceProvider(), false, name -> { if (currentQuickReply != null) { QuickRepliesController.getInstance(currentAccount).renameReply(currentQuickReply.id, name); } quickReplyShortcut = name; avatarContainer.setTitle(name); }); } else if (id == chat_menu_attach) { ActionBarMenuSubItem attach = new ActionBarMenuSubItem(context, false, true, true, getResourceProvider()); attach.setTextAndIcon(LocaleController.getString(R.string.AttachMenu), R.drawable.input_attach); attach.setOnClickListener(view -> { headerItem.closeSubMenu(); if (chatAttachAlert != null) { chatAttachAlert.setEditingMessageObject(0, null); } openAttachMenu(); }); headerItem.toggleSubMenu(attach, attachItem.createView()); } else if (id == bot_help) { getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of("/help", dialog_id, null, null, null, false, null, null, null, true, 0, 0, null, false)); } else if (id == bot_settings) { getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of("/settings", dialog_id, null, null, null, false, null, null, null, true, 0, 0, null, false)); } else if (id == search) { openSearchWithText(isSupportedTags() ? "" : null); } else if (id == translate) { getMessagesController().getTranslateController().setHideTranslateDialog(getDialogId(), false, true); if (!getMessagesController().getTranslateController().toggleTranslatingDialog(getDialogId(), true)) { updateTopPanel(true); } } 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() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedBold(); } } else if (id == text_italic) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedItalic(); } } else if (id == text_spoiler) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedSpoiler(); } } else if (id == text_quote) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedQuote(); } } else if (id == text_mono) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedMono(); } } else if (id == text_strike) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedStrike(); } } else if (id == text_underline) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedUnderline(); } } else if (id == text_link) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedUrl(); } } else if (id == text_regular) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedRegular(); } } else if (id == change_colors) { showChatThemeBottomSheet(); } else if (id == topic_close) { if (forumTopic == null) return; getMessagesController().getTopicsController().toggleCloseTopic(currentChat.id, forumTopic.id, forumTopic.closed = true); updateTopicButtons(); updateBottomOverlay(); updateTopPanel(true); } else if (id == open_forum) { TopicsFragment.prepareToSwitchAnimation(ChatActivity.this); // Bundle bundle = new Bundle(); // bundle.putLong("chat_id", -dialog_id); // presentFragment(new TopicsFragment(bundle)); } else if (id == copy_business_link) { AndroidUtilities.addToClipboard(businessLink.link); BulletinFactory.of(LaunchActivity.getLastFragment()).createCopyLinkBulletin().show(); } else if (id == share_business_link) { Runnable shareTask = () -> { Intent intent = new Intent(getContext(), LaunchActivity.class); intent.setAction(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, businessLink.link); startActivityForResult(intent, 500); }; if (chatActivityEnterView.businessLinkHasChanges()) { showBusinessLinksDiscardAlert(shareTask); } else { shareTask.run(); } } else if (id == rename_business_link) { BusinessLinksActivity.openRenameAlert(getContext(), currentAccount, businessLink, resourceProvider, false); } else if (id == delete_business_link) { AlertDialog dialog = new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(getString(R.string.BusinessLinksDeleteTitle)) .setMessage(getString(R.string.BusinessLinksDeleteMessage)) .setPositiveButton(getString(R.string.Remove), (di, w) -> { finishFragment(); getNotificationCenter().postNotificationName(NotificationCenter.needDeleteBusinessLink, businessLink); }) .setNegativeButton(getString(R.string.Cancel), null) .create(); showDialog(dialog); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(getThemedColor(Theme.key_text_RedBold)); } } } }); View backButton = actionBar.getBackButton(); backButton.setOnTouchListener(new LongPressListenerWithMovingGesture() { @Override public void onLongPress() { scrimPopupWindow = BackButtonMenu.show(ChatActivity.this, backButton, dialog_id, getTopicId(), themeDelegate); if (scrimPopupWindow != null) { setSubmenu(scrimPopupWindow); scrimPopupWindow.setOnDismissListener(() -> { setSubmenu(null); scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); if (scrimPopupWindowHideDimOnDismiss) { dimBehindView(false); } else { scrimPopupWindowHideDimOnDismiss = true; } if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != 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() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(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) { @Override protected boolean useAnimatedSubtitle() { return chatMode == MODE_SAVED; } @Override protected boolean canSearch() { return !isInsideContainer && !isInPreviewMode() && !inBubbleMode && searchItem != null && !searching && (!isThreadChat() || isTopic); } @Override protected void openSearch() { openSearchWithText(isSupportedTags() ? "" : null); } }; avatarContainer.allowShorterStatus = true; avatarContainer.premiumIconHiddable = true; avatarContainer.allowDrawStories = dialog_id < 0 && !isTopic; avatarContainer.setClipChildren(false); AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 1f, false); updateTopicTitleIcon(); if (inPreviewMode || inBubbleMode || isInsideContainer) { avatarContainer.setOccupyStatusBar(false); } if (isReport()) { actionBar.setTitle(reportTitle); actionBar.setSubtitle(getString(R.string.ReportSelectMessages)); } else if (startLoadFromDate != 0) { final int date = startLoadFromDate; actionBar.setOnClickListener((v) -> { jumpToDate(date); }); actionBar.setTitle(LocaleController.formatDateChat(startLoadFromDate, false)); actionBar.setSubtitle(getString(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(getString(R.string.NoMessagesForThisDay)); } }); } }); } else { actionBar.setSubtitle(getString(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 (chatMode == MODE_QUICK_REPLIES && !QuickRepliesController.isSpecial(quickReplyShortcut)) { menu.addItem(edit_quick_reply, R.drawable.group_edit).setContentDescription(LocaleController.getString(R.string.Edit)); } if (currentEncryptedChat == null && (chatMode == 0 || chatMode == MODE_SAVED || chatMode == MODE_SUGGESTIONS) && !isReport()) { searchIconItem = menu.addItem(search, isSupportedTags() ? R.drawable.navbar_search_tag : R.drawable.ic_ab_search); searchIconItem.setContentDescription(LocaleController.getString(R.string.Search)); searchItem = menu.addItem(chat_menu_search, R.drawable.ic_ab_search, themeDelegate); searchItem.setIsSearchField(true); searchItem.setActionBarMenuItemSearchListener(getSearchItemListener()); searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString(R.string.SavedTagSearchHint) : LocaleController.getString(R.string.Search)); if (chatMode == MODE_SAVED || chatMode == MODE_SUGGESTIONS || threadMessageId == 0 && !UserObject.isReplyUser(currentUser) || threadMessageObject != null && threadMessageObject.getRepliesCount() < 10) { searchItem.setVisibility(View.GONE); } else { searchItem.setVisibility(View.VISIBLE); } searchItemVisible = false; } if (chatMode == 0 && (threadMessageId == 0 || isTopic) && !UserObject.isReplyUser(currentUser) && !isReport()) { TLRPC.UserFull userFull = null; if (currentUser != null) { audioCallIconItem = menu.lazilyAddItem(call, R.drawable.ic_call, themeDelegate); audioCallIconItem.setContentDescription(LocaleController.getString(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); } if (avatarContainer != null) { avatarContainer.setTitleExpand(showAudioCallAsIcon); } } } editTextItem = menu.lazilyAddItem(chat_menu_edit_text_options, R.drawable.ic_ab_other, themeDelegate); editTextItem.setContentDescription(LocaleController.getString(R.string.AccDescrMoreOptions)); editTextItem.setTag(null); editTextItem.setVisibility(View.GONE); if (((chatMode == 0 && (threadMessageId == 0 || isTopic)) || chatMode == MODE_SUGGESTIONS) && !UserObject.isReplyUser(currentUser) && !isReport()) { TLRPC.UserFull userFull = null; if (currentUser != null) { userFull = getMessagesController().getUserFull(currentUser.id); } headerItem = menu.addItem(chat_menu_options, R.drawable.ic_ab_other, themeDelegate); headerItem.setContentDescription(LocaleController.getString(R.string.AccDescrMoreOptions)); if (currentUser != null && currentUser.self && chatMode != MODE_SAVED) { savedChatsItem = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString(R.string.SavedViewAsChats)); savedChatsGap = headerItem.lazilyAddColoredGap(); savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); } else if (chatMode != MODE_SAVED && (currentUser == null || !currentUser.self)) { chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, headerItem.getPopupLayout().getSwipeBack(), false, false, new ChatNotificationsPopupWrapper.Callback() { @Override public void dismiss() { headerItem.toggleSubMenu(); } @Override public void toggleSound() { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); boolean enabled = !preferences.getBoolean("sound_enabled_" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), true); preferences.edit().putBoolean("sound_enabled_" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), 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, getTopicId())) { 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, getTopicId(), 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 && chatMode != MODE_SAVED) { if (currentUser != null) { getMessagesController().putUser(currentUser, true); } Bundle args = new Bundle(); args.putLong("dialog_id", dialog_id); if (getTopicId() != 0) { args.putLong("topic_id", getTopicId()); } presentFragment(new ProfileNotificationsActivity(args, themeDelegate)); } } @Override public void toggleMute() { ChatActivity.this.toggleMute(true); BulletinFactory.createMuteBulletin(ChatActivity.this, getMessagesController().isDialogMuted(dialog_id, getTopicId()), themeDelegate).show(); } }, getResourceProvider()); muteItem = headerItem.lazilyAddSwipeBackItem(R.drawable.msg_mute, null, null, chatNotificationsPopupWrapper.windowLayout); muteItem.setOnClickListener(view -> { boolean muted = MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id, getTopicId()); if (muted) { updateTitleIcons(true); AndroidUtilities.runOnUIThread(() -> { ChatActivity.this.toggleMute(true); }, 150); headerItem.toggleSubMenu(); if (ChatActivity.this.getParentActivity() != null) { BulletinFactory.createMuteBulletin(ChatActivity.this, false, themeDelegate).show(); } } else { muteItem.openSwipeBack(); } }); muteItemGap = headerItem.lazilyAddColoredGap(); } if (currentChat != null) { headerItem.lazilyAddSubItem(open_direct, R.drawable.msg_markunread, getString(R.string.ChannelOpenDirect)); headerItem.setSubItemShown(open_direct, ChatObject.isChannel(currentChat) && !ChatObject.isMonoForum(currentChat) && currentChat.linked_monoforum_id != 0 && ChatObject.canManageMonoForum(currentAccount, -currentChat.linked_monoforum_id)); } if (currentUser != null && chatMode != MODE_SAVED) { headerItem.lazilyAddSubItem(call, R.drawable.msg_callback, LocaleController.getString(R.string.Call)); headerItem.lazilyAddSubItem(video_call, R.drawable.msg_videocall, LocaleController.getString(R.string.VideoCall)); 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.lazilyAddSubItem(search, R.drawable.msg_search, LocaleController.getString(R.string.Search)); } if (ChatObject.isBoostSupported(currentChat) && (getUserConfig().isPremium() || ChatObject.isBoosted(chatInfo) || ChatObject.hasAdminRights(currentChat))) { RLottieDrawable drawable = new RLottieDrawable(R.raw.boosts, "" + R.raw.boosts, dp(24), dp(24)); headerItem.lazilyAddSubItem(boost_group, drawable, LocaleController.getString(ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.BoostingBoostChannelMenu : R.string.BoostingBoostGroupMenu)); } translateItem = headerItem.lazilyAddSubItem(translate, R.drawable.msg_translate, LocaleController.getString(R.string.TranslateMessage)); updateTranslateItemVisibility(); if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) { headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString(R.string.ReportChat)); } if (currentUser != null && currentUser.id != UserObject.VERIFY && currentUser.id != UserObject.REPLY_BOT) { addContactItem = headerItem.lazilyAddSubItem(share_contact, R.drawable.msg_addcontact, LocaleController.getString(R.string.AddToContacts)); } if (currentEncryptedChat != null) { timeItem2 = headerItem.lazilyAddSubItem(chat_enc_timer, R.drawable.msg_autodelete, LocaleController.getString(R.string.SetTimer)); } if (currentChat != null && !isTopic) { viewAsTopics = headerItem.lazilyAddSubItem(view_as_topics, R.drawable.msg_topics, LocaleController.getString(R.string.TopicViewAsTopics)); } if (themeDelegate.isThemeChangeAvailable(true)) { headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_background, LocaleController.getString(R.string.SetWallpapers)); } if (currentUser != null && currentUser.self && getDialogId() != UserObject.VERIFY) { headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString(R.string.AddShortcut)); } if (!isTopic && !ChatObject.isMonoForum(currentChat)) { clearHistoryItem = headerItem.lazilyAddSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString(R.string.ClearHistory)); } boolean addedSettings = false; if (!isTopic) { if (ChatObject.isChannel(currentChat) && !currentChat.creator) { if (!ChatObject.isNotInChat(currentChat)) { if (currentChat.monoforum) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveConversationMenu)); } else if (currentChat.megagroup) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveMegaMenu)); } else { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveChannelMenu)); } } } else if (!ChatObject.isChannel(currentChat) && getDialogId() != UserObject.VERIFY) { if (currentChat != null) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.DeleteAndExit)); } else if (currentUser != null && currentUser.bot) { headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString(R.string.BotSettings)); addedSettings = true; headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString(R.string.BotHelp)); if (!MessagesController.isSupportUser(currentUser)) { headerItem.lazilyAddSubItem(report, R.drawable.msg_report, LocaleController.getString(R.string.ReportBot)).setColors(getThemedColor(Theme.key_text_RedRegular), getThemedColor(Theme.key_text_RedRegular)); } headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_text_RedRegular), getThemedColor(Theme.key_text_RedRegular)); updateBotButtons(); } else { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString(R.string.DeleteChatUser)); } } } if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { headerItem.lazilyAddSubItem(remove_fee, R.drawable.menu_paid_off, getString(R.string.DirectRemoveFee)); headerItem.lazilyAddSubItem(charge_fee, R.drawable.menu_feature_paid, getString(R.string.DirectChargeFee)); headerItem.setSubItemShown(remove_fee, false); headerItem.setSubItemShown(charge_fee, false); feeItemGap = headerItem.lazilyAddColoredGap(); feeItemText = headerItem.lazilyAddText("", 13); feeItemGap.setVisibility(View.GONE); feeItemText.setVisibility(View.GONE); } } else if (chatMode == MODE_EDIT_BUSINESS_LINK) { headerItem = menu.addItem(chat_menu_options, R.drawable.ic_ab_other, themeDelegate); headerItem.setContentDescription(LocaleController.getString(R.string.AccDescrMoreOptions)); headerItem.lazilyAddSubItem(copy_business_link, R.drawable.msg_copy, getString(R.string.Copy)); headerItem.lazilyAddSubItem(share_business_link, R.drawable.msg_share, getString(R.string.LinkActionShare)); headerItem.lazilyAddSubItem(rename_business_link, R.drawable.msg_edit, getString(R.string.Rename)); headerItem.lazilyAddSubItem(delete_business_link, R.drawable.msg_delete, getString(R.string.Delete)).setColors(Theme.getColor(Theme.key_text_RedRegular), Theme.getColor(Theme.key_text_RedRegular)); } if (ChatObject.isForum(currentChat) && isTopic && getParentLayout() != null && getParentLayout().getFragmentStack() != null && chatMode == MODE_DEFAULT) { boolean hasMyForum = false; for (int i = 0; i < getParentLayout().getFragmentStack().size(); ++i) { BaseFragment fragment = getParentLayout().getFragmentStack().get(i); if (fragment instanceof TopicsFragment && ((TopicsFragment) fragment).getDialogId() == dialog_id) { hasMyForum = true; break; } } if (!hasMyForum) { openForumItem = headerItem.lazilyAddSubItem(open_forum, R.drawable.msg_discussion, LocaleController.getString(R.string.OpenAllTopics)); } } if (currentChat != null && forumTopic != null && chatMode == 0) { closeTopicItem = headerItem.lazilyAddSubItem(topic_close, R.drawable.msg_topic_close, LocaleController.getString(R.string.CloseTopic)); closeTopicItem.setVisibility(currentChat != null && ChatObject.canManageTopic(currentAccount, currentChat, forumTopic) && forumTopic != null && !forumTopic.closed ? View.VISIBLE : View.GONE); } menu.setVisibility(inMenuMode ? View.GONE : View.VISIBLE); updateTitle(false); avatarContainer.updateOnlineCount(); avatarContainer.updateSubtitle(); updateTitleIcons(); // if (chatMode == 0 && (!isThreadChat() || isTopic) && !isReport()) { // attachItem = menu.lazilyAddItem(chat_menu_attach, R.drawable.ic_ab_other, themeDelegate); // attachItem.setOverrideMenuClick(true); // attachItem.setAllowCloseAnimation(false); // attachItem.setContentDescription(LocaleController.getString(R.string.AccDescrMoreOptions)); // attachItem.setVisibility(View.GONE); // } if (inPreviewMode) { if (headerItem != null) { headerItem.setAlpha(0.0f); } if (attachItem != null) { attachItem.setAlpha(0.0f); } } actionModeViews.clear(); selectedMessagesCountTextView = null; checkActionBarMenu(false); scrimPaint = new Paint(); if (chatListThanosEffect != null) { AndroidUtilities.removeFromParent(chatListThanosEffect); chatListThanosEffect = null; } removingFromParent = false; fragmentView = contentView = new ChatActivityFragmentView(context, parentLayout); invalidateBlurredSourcesView = new OnPostDrawView(context, this::invalidateMergedVisibleBlurredPositionsAndSourcesImpl); contentView.addView(invalidateBlurredSourcesView); final ViewPositionWatcher viewPositionWatcher = new ViewPositionWatcher(contentView); glassBackgroundDrawableFactory.setSourceRootView(viewPositionWatcher, contentView); glassBackgroundDrawableFactoryFrosted.setSourceRootView(viewPositionWatcher, contentView); navbarContentDrawableFactory.setSourceRootView(viewPositionWatcher, contentView); contentView.needBlur = false; contentView.needBlurBottom = false; contentView.setOccupyStatusBar(!inBubbleMode && !isInsideContainer && !inPreviewMode); BlurredBackgroundWithFadeDrawable fadeDrawable = new BlurredBackgroundWithFadeDrawable( navbarContentDrawableFactory.create(chatInputViewsContainer, null)); if (!SharedConfig.chatBlurEnabled() || LiteMode.isEnabled(LiteMode.FLAG_LIQUID_GLASS)) { fadeDrawable.setFadeHeight(dp(72), true); } chatInputViewsContainer = new ChatInputViewsContainer(context); chatInputViewsContainer.setClipChildren(false); chatInputViewsContainer.setBackgroundWithFadeDrawable(fadeDrawable); chatInputViewsContainer.setWindowInsetsProvider(windowInsetsStateHolder); chatInputViewsContainer.setInputIslandBubbleDrawable( glassBackgroundDrawableFactory.create(chatInputViewsContainer, blurredBackgroundColorProvider)); chatInputViewsContainer.setUnderKeyboardBackgroundDrawable( glassBackgroundDrawableFactoryFrosted.create(chatInputViewsContainer, blurredBackgroundColorProvider)); chatInputBubbleContainer = chatInputViewsContainer.getInputIslandBubbleContainer(); chatInputBubbleContainer.setClipChildren(false); chatInputInAppContainer = chatInputViewsContainer.getInAppKeyboardBubbleContainer(); updateBackground(); emptyViewContainer = null; 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 ChatListRecyclerView(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 drawReactionsAfter = new ArrayList<>(); private final ArrayList drawingGroups = new ArrayList<>(10); private int startedTrackingX; private int startedTrackingY; private int startedTrackingPointerId; private long lastTrackingAnimationTime; private float trackAnimationProgress; private float endTrackingX; private boolean wasTrackingVibrate; private float springMultiplier = 2000f; private Paint outlineActionBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint outlineActionBackgroundDarkenPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private FloatValueHolder slidingDrawableVisibilityProgress = new FloatValueHolder(0); private SpringAnimation slidingDrawableVisibilitySpring = new SpringAnimation(slidingDrawableVisibilityProgress) .setMinValue(0f) .setMaxValue(springMultiplier) .setSpring(new SpringForce(0) .setStiffness(SpringForce.STIFFNESS_MEDIUM) .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)) .addUpdateListener((animation, value, velocity) -> invalidate()); private FloatValueHolder slidingFillProgress = new FloatValueHolder(0); private SpringAnimation slidingFillProgressSpring = new SpringAnimation(slidingFillProgress) .setMinValue(0f) .setSpring(new SpringForce(0) .setStiffness(400f) .setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY)) .addUpdateListener((animation, value, velocity) -> invalidate()); private FloatValueHolder slidingOuterRingProgress = new FloatValueHolder(0); private SpringAnimation slidingOuterRingSpring = new SpringAnimation(slidingOuterRingProgress) .setMinValue(0f) .setSpring(new SpringForce(0) .setStiffness(200f) .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)) .addUpdateListener((animation, value, velocity) -> invalidate()); private boolean slidingBeyondMax; private Path path = new Path(); private boolean ignoreLayout; private boolean invalidated; int lastH = 0; { outlineActionBackgroundPaint.setStyle(Paint.Style.STROKE); outlineActionBackgroundPaint.setStrokeCap(Paint.Cap.ROUND); outlineActionBackgroundPaint.setStrokeWidth(AndroidUtilities.dp(2)); outlineActionBackgroundDarkenPaint.setStyle(Paint.Style.STROKE); outlineActionBackgroundDarkenPaint.setStrokeCap(Paint.Cap.ROUND); outlineActionBackgroundDarkenPaint.setStrokeWidth(AndroidUtilities.dp(2)); } @Override public void requestLayout() { if (ignoreLayout) { return; } super.requestLayout(); } @Override public void setTranslationY(float translationY) { if (translationY != getTranslationY()) { super.setTranslationY(translationY); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } } @Override protected boolean allowSelectChildAtPosition(View child) { if (child != null && (child.getVisibility() == View.INVISIBLE || child.getVisibility() == View.GONE)) return false; return super.allowSelectChildAtPosition(child); } @Override protected void onMeasure(int widthSpec, int heightSpec) { // saveScrollPosition(); super.onMeasure(widthSpec, heightSpec); } @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) { if (lastWidth != 0) { hideHints(false); } lastWidth = r - l; } 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.isInSelectionMode()) { textSelectionHelper.invalidate(); } invalidateClipRectForBackgroundAndChatList(); isSkeletonVisible(); } 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; } if (quickShareSelectorOverlay != null && quickShareSelectorOverlay.isActive()) { return false; } boolean result = super.onInterceptTouchEvent(e); if (actionBar.isActionModeShowed() || isReport()) { 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 || Thread.currentThread() != Looper.getMainLooper().getThread()) { return; } Paint chatActionBackgroundPaint = getThemedPaint(Theme.key_paint_chatActionBackground); Paint chatActionBackgroundDarkenPaint = Theme.chat_actionBackgroundGradientDarkenPaint; if (outlineActionBackgroundPaint.getColor() != chatActionBackgroundPaint.getColor()) { outlineActionBackgroundPaint.setColor(chatActionBackgroundPaint.getColor()); } if (outlineActionBackgroundDarkenPaint.getColor() != chatActionBackgroundDarkenPaint.getColor()) { outlineActionBackgroundDarkenPaint.setColor(chatActionBackgroundDarkenPaint.getColor()); } if (outlineActionBackgroundPaint.getShader() != chatActionBackgroundPaint.getShader()) { outlineActionBackgroundPaint.setShader(chatActionBackgroundPaint.getShader()); } if (outlineActionBackgroundDarkenPaint.getShader() != chatActionBackgroundDarkenPaint.getShader()) { outlineActionBackgroundDarkenPaint.setShader(chatActionBackgroundDarkenPaint.getShader()); } float fillProgress = slidingFillProgress.getValue() / springMultiplier; int wasDarkenColor = outlineActionBackgroundDarkenPaint.getColor(); if (fillProgress > 1) { slidingBeyondMax = true; } float translationX = slidingView.getNonAnimationTranslationX(false); if (slidingDrawableVisibilityProgress.getValue() == 0) { slidingFillProgressSpring.cancel(); slidingFillProgressSpring.getSpring().setFinalPosition(0); slidingFillProgress.setValue(0f); slidingOuterRingSpring.cancel(); slidingOuterRingSpring.getSpring().setFinalPosition(0); slidingOuterRingProgress.setValue(0f); slidingBeyondMax = false; } float progress; if (slidingFillProgressSpring.getSpring().getFinalPosition() != springMultiplier) { progress = androidx.core.math.MathUtils.clamp((-translationX - AndroidUtilities.dp(20)) / AndroidUtilities.dp(30), 0, 1); } else { progress = 1f; } if (progress == 1f && slidingFillProgressSpring.getSpring().getFinalPosition() != springMultiplier) { slidingFillProgressSpring.getSpring().setFinalPosition(springMultiplier); slidingFillProgressSpring.start(); slidingOuterRingSpring.getSpring().setFinalPosition(springMultiplier); slidingOuterRingSpring.start(); } boolean visible = translationX <= -AndroidUtilities.dp(20); float endVisibleValue = visible ? springMultiplier : 0; if (endVisibleValue != slidingDrawableVisibilitySpring.getSpring().getFinalPosition()) { slidingDrawableVisibilitySpring.getSpring().setFinalPosition(endVisibleValue); if (!slidingDrawableVisibilitySpring.isRunning()) { slidingDrawableVisibilitySpring.start(); } } float iconProgress = slidingDrawableVisibilityProgress.getValue() / springMultiplier; float x = getMeasuredWidth() + translationX * (slidingView.getMessageObject() != null && slidingView.getMessageObject().isOut() ? 0.5f : 1f); float y = slidingView.getTop() + slidingView.getMeasuredHeight() / 2f; float scale = slidingBeyondMax ? fillProgress : iconProgress; float clearScale = slidingBeyondMax ? 0f : 1f - fillProgress; boolean isDark = ColorUtils.calculateLuminance(getThemedColor(Theme.key_windowBackgroundWhite)) <= 0.5f; if (iconProgress != 0) { AndroidUtilities.rectTmp.set((int) (x - AndroidUtilities.dp(16) * scale + outlineActionBackgroundPaint.getStrokeWidth() / 2f), (int) (y - AndroidUtilities.dp(16) * scale + outlineActionBackgroundPaint.getStrokeWidth() / 2f), (int) (x + AndroidUtilities.dp(16) * scale - outlineActionBackgroundPaint.getStrokeWidth() / 2f), (int) (y + AndroidUtilities.dp(16) * scale - outlineActionBackgroundPaint.getStrokeWidth() / 2f)); Theme.applyServiceShaderMatrix(getMeasuredWidth(), AndroidUtilities.displaySize.y, 0, getY() + AndroidUtilities.rectTmp.top); if (fillProgress == 0) { int outlineAlpha = outlineActionBackgroundPaint.getAlpha(); outlineActionBackgroundPaint.setAlpha((int) (outlineAlpha * iconProgress)); canvas.drawArc(AndroidUtilities.rectTmp, -90, 360 * progress, false, outlineActionBackgroundPaint); outlineActionBackgroundPaint.setAlpha(outlineAlpha); if (themeDelegate.hasGradientService()) { outlineAlpha = outlineActionBackgroundDarkenPaint.getAlpha(); if (isDark) { outlineActionBackgroundDarkenPaint.setColor(Color.WHITE); } outlineActionBackgroundDarkenPaint.setAlpha((int) (outlineAlpha * iconProgress)); canvas.drawArc(AndroidUtilities.rectTmp, -90, 360 * progress, false, outlineActionBackgroundDarkenPaint); } } } 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); path.rewind(); path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16) * scale, AndroidUtilities.dp(16) * scale, Path.Direction.CW); int wasAlpha = chatActionBackgroundPaint.getAlpha(); chatActionBackgroundPaint.setAlpha((int) (iconProgress * 0.6f * progress * wasAlpha)); canvas.drawPath(path, chatActionBackgroundPaint); chatActionBackgroundPaint.setAlpha(wasAlpha); if (themeDelegate.hasGradientService()) { wasAlpha = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); if (isDark) { Theme.chat_actionBackgroundGradientDarkenPaint.setColor(Color.WHITE); } Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (iconProgress * 0.6f * progress * wasAlpha)); canvas.drawPath(path, Theme.chat_actionBackgroundGradientDarkenPaint); Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(wasAlpha); } if (clearScale != 0f) { AndroidUtilities.rectTmp.set((int) (x - AndroidUtilities.dp(16) * clearScale), (int) (y - AndroidUtilities.dp(16) * clearScale), (int) (x + AndroidUtilities.dp(16) * clearScale), (int) (y + AndroidUtilities.dp(16) * clearScale)); path.rewind(); path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Path.Direction.CW); canvas.save(); canvas.clipPath(path, Region.Op.DIFFERENCE); } 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); path.rewind(); path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16) * scale, AndroidUtilities.dp(16) * scale, Path.Direction.CW); wasAlpha = chatActionBackgroundPaint.getAlpha(); chatActionBackgroundPaint.setAlpha((int) (iconProgress * 0.4f * wasAlpha)); canvas.drawPath(path, chatActionBackgroundPaint); chatActionBackgroundPaint.setAlpha(wasAlpha); if (themeDelegate.hasGradientService()) { wasAlpha = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); if (isDark) { Theme.chat_actionBackgroundGradientDarkenPaint.setColor(Color.WHITE); } Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (iconProgress * 0.4f * wasAlpha)); canvas.drawPath(path, Theme.chat_actionBackgroundGradientDarkenPaint); Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(wasAlpha); } if (clearScale != 0f) { canvas.restore(); } float outerRingProgress = slidingOuterRingProgress.getValue() / springMultiplier; if (outerRingProgress != 0 && outerRingProgress != 1) { float outScale = 1f + outerRingProgress; float wasWidth = outlineActionBackgroundPaint.getStrokeWidth(); float width = (1f - outerRingProgress) * wasWidth; if (width != 0f) { AndroidUtilities.rectTmp.set((int) (x - AndroidUtilities.dp(16) * outScale + width), (int) (y - AndroidUtilities.dp(16) * outScale + width), (int) (x + AndroidUtilities.dp(16) * outScale - width), (int) (y + AndroidUtilities.dp(16) * outScale - width)); Theme.applyServiceShaderMatrix(getMeasuredWidth(), AndroidUtilities.displaySize.y, 0, getY() + AndroidUtilities.rectTmp.top); wasAlpha = outlineActionBackgroundPaint.getAlpha(); outlineActionBackgroundPaint.setAlpha((int) (wasAlpha * iconProgress)); outlineActionBackgroundPaint.setStrokeWidth(width); canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16) * outScale, AndroidUtilities.dp(16) * outScale, outlineActionBackgroundPaint); outlineActionBackgroundPaint.setStrokeWidth(wasWidth); outlineActionBackgroundPaint.setAlpha(wasAlpha); if (themeDelegate.hasGradientService()) { wasAlpha = outlineActionBackgroundDarkenPaint.getAlpha(); if (isDark) { outlineActionBackgroundDarkenPaint.setColor(Color.WHITE); } outlineActionBackgroundDarkenPaint.setAlpha((int) (wasAlpha * iconProgress)); outlineActionBackgroundDarkenPaint.setStrokeWidth(width); canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(16) * outScale, AndroidUtilities.dp(16) * outScale, outlineActionBackgroundDarkenPaint); outlineActionBackgroundDarkenPaint.setStrokeWidth(wasWidth); } } } int alpha = (int) (iconProgress * 0xFF); Drawable replyIconDrawable = getThemedDrawable(Theme.key_drawable_replyIcon); replyIconDrawable.setAlpha(alpha); replyIconDrawable.setBounds((int) (x - replyIconDrawable.getIntrinsicWidth() / 2 * scale), (int) (y - replyIconDrawable.getIntrinsicHeight() / 2 * scale), (int) (x + replyIconDrawable.getIntrinsicWidth() / 2 * scale), (int) (y + replyIconDrawable.getIntrinsicHeight() / 2 * scale)); replyIconDrawable.draw(canvas); replyIconDrawable.setAlpha(255); outlineActionBackgroundDarkenPaint.setColor(wasDarkenColor); chatActionBackgroundDarkenPaint.setColor(wasDarkenColor); } 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(); boolean allowReplyOnOpenTopic = canSendMessageToTopic(message); if ( chatMode != 0 && chatMode != MODE_QUICK_REPLIES && chatMode != MODE_SUGGESTIONS && (chatMode != MODE_SAVED || threadMessageId != getUserConfig().getClientUserId()) || threadMessageObjects != null && threadMessageObjects.contains(message) || getMessageType(message) == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || currentEncryptedChat == null && message.getId() < 0 || bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE && !(bottomOverlayChatWaitsReply && allowReplyOnOpenTopic || message.wasJustSent) || currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat) || (ChatObject.isForum(currentChat) && !allowReplyOnOpenTopic)) || textSelectionHelper.isInSelectionMode() ) { 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, 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) { animatorPullingDownContainerVisibility.setValue(false, true); } 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) { animatorPullingDownContainerVisibility.setValue(false, true); } 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() || isReport()) { 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, false); } if (trackAnimationProgress == 1f || trackAnimationProgress == 0f) { slidingView.setSlidingOffset(0); slidingView = null; } invalidate(); } drawReplyButton(c); } if (pullingDownOffset != 0 && !isInPreviewMode() && !isInsideContainer && chatMode != MODE_SAVED && chatMode != MODE_SCHEDULED) { 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, getTopicId(), themeDelegate); pullingDownDrawable.progressToBottomPanel = animatorPullingDownContainerVisibility.getFloatValue(); if (nextChannels != null && !nextChannels.isEmpty()) { pullingDownDrawable.updateDialog(nextChannels.get(0)); } else if (isTopic) { pullingDownDrawable.updateTopic(); } else { pullingDownDrawable.updateDialog(); } pullingDownDrawable.onAttach(); } pullingDownDrawable.setWidth(getMeasuredWidth() - (isSideMenued() ? dp(SIDE_MENU_WIDTH) : 0)); float progress = Math.min(1f, pullingDownOffset / AndroidUtilities.dp(110)); c.translate(isSideMenued() ? lerp(dp(32), dp(SIDE_MENU_WIDTH), getSideMenuAlpha()) : 0, -(windowInsetsStateHolder.getAnimatedMaxBottomInset() + dp(10) + chatInputViewsContainer.getInputBubbleHeight())); 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 public void draw(Canvas canvas) { if ((startMessageAppearTransitionMs == 0 || System.currentTimeMillis() - startMessageAppearTransitionMs <= SKELETON_DISAPPEAR_MS) && !AndroidUtilities.isTablet() && !isComments && currentUser == null) { boolean noAvatar = (currentChat == null || ChatObject.isChannelAndNotMegaGroup(currentChat)) && chatMode != MODE_SEARCH; if (pullingDownOffset != 0) { canvas.save(); canvas.translate(0, -pullingDownOffset); } updateSkeletonColors(); updateSkeletonGradient(); int lastTop = getHeight() - blurredViewBottomOffset - (int) windowInsetsStateHolder.getAnimatedMaxBottomInset() - dp(44 + 7 + 9 - 3); int j = 0; int childMaxTop = Integer.MAX_VALUE; for (int i = 0; i < getChildCount(); i++) { int top = getChildAt(i).getTop(); if (top < childMaxTop) { childMaxTop = top; } } if (startMessageAppearTransitionMs == 0 && childMaxTop <= 0) { checkDispatchHideSkeletons(fragmentBeginToShow); } Paint servicePaint = getThemedPaint(Theme.key_paint_chatActionBackground); if (skeletonServicePaint.getColor() != servicePaint.getColor()) { skeletonServicePaint.setColor(servicePaint.getColor()); } if (skeletonServicePaint.getShader() != servicePaint.getShader()) { skeletonServicePaint.setShader(servicePaint.getShader()); skeletonColorMatrix.setSaturation(SKELETON_SATURATION); skeletonServicePaint.setColorFilter(new ColorMatrixColorFilter(skeletonColorMatrix)); } for (int i = 0; i < getChildCount(); i++) { View v = getChildAt(i); // if (v instanceof ChatMessageCell) { // ChatMessageCell cell = (ChatMessageCell) v; // if ((cell.getCurrentMessagesGroup() == null || cell.getCurrentMessagesGroup().findPrimaryMessageObject() == cell.getMessageObject())) { // if (cell.shouldDrawAlphaLayer() || System.currentTimeMillis() - startMessageAppearTransitionMs >= SKELETON_DISAPPEAR_MS) { // float progress = cell.getAlpha(); // // MessageSkeleton skeleton; // if (j >= messageSkeletons.size()) { // skeleton = getNewSkeleton(noAvatar); // messageSkeletons.add(skeleton); // } else { // skeleton = messageSkeletons.get(j); // } // // Rect bounds = cell.getCurrentBackgroundDrawable(true).getBounds(); // MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); // // int alpha = skeletonPaint.getAlpha(); // int wasServiceAlpha = servicePaint.getAlpha(); // servicePaint.setAlpha((int) (wasServiceAlpha * 0.4f * (1f - progress))); // skeletonPaint.setAlpha((int) (alpha * (1f - progress))); // int bottom = (int) AndroidUtilities.lerp(Math.min(skeleton.lastBottom, lastTop - AndroidUtilities.dp(3f)), v.getBottom() + (group != null ? group.transitionParams.top + group.transitionParams.offsetTop : 0), progress); // int left = noAvatar ? AndroidUtilities.dp(3f) : AndroidUtilities.dp(51); // int top = (int) AndroidUtilities.lerp(bottom - skeleton.height, bounds.top + v.getTop() + (group != null ? group.transitionParams.top + group.transitionParams.offsetTop : 0), progress); // int right = skeleton.width; // // boolean lerp = cell.getMessageObject() == null || !cell.getMessageObject().isOut(); // skeletonBackgroundDrawable.setBounds(lerp ? AndroidUtilities.lerp(left, cell.getBackgroundDrawableLeft(), progress) : left, top, // lerp ? AndroidUtilities.lerp(right, cell.getBackgroundDrawableRight(), progress) : right, bottom); // Theme.applyServiceShaderMatrix(getMeasuredWidth(), AndroidUtilities.displaySize.y, 0, getY() + skeletonBackgroundDrawable.getBounds().top); // skeletonBackgroundDrawable.drawCached(canvas, skeletonBackgroundCacheParams, servicePaint); // skeletonBackgroundDrawable.drawCached(canvas, skeletonBackgroundCacheParams, skeletonPaint); // if (!noAvatar) { // Theme.applyServiceShaderMatrix(getMeasuredWidth(), AndroidUtilities.displaySize.y, 0, getY() + bottom - AndroidUtilities.dp(42)); // canvas.drawCircle(AndroidUtilities.dp(48 - 21), bottom - AndroidUtilities.dp(21), AndroidUtilities.dp(21), servicePaint); // canvas.drawCircle(AndroidUtilities.dp(48 - 21), bottom - AndroidUtilities.dp(21), AndroidUtilities.dp(21), skeletonPaint); // } // servicePaint.setAlpha(wasServiceAlpha); // skeletonPaint.setAlpha(alpha); // j++; // // if (top < lastTop) { // lastTop = top; // } // // continue; // } // j++; // } // } if (v instanceof ChatMessageCell) { MessageObject.GroupedMessages group = ((ChatMessageCell) v).getCurrentMessagesGroup(); Rect bounds = ((ChatMessageCell) v).getCurrentBackgroundDrawable(true).getBounds(); int newTop = (int) (v.getTop() + bounds.top + (group != null ? group.transitionParams.top + group.transitionParams.offsetTop : 0)); int top = startMessageAppearTransitionMs == 0 && isSkeletonVisible() ? lerp(lastTop, newTop, v.getAlpha()) : v.getAlpha() == 1f ? newTop : lastTop; if (top < lastTop) { lastTop = top; } } else if (v instanceof ChatActionCell) { int top = startMessageAppearTransitionMs == 0 && isSkeletonVisible() ? lerp(lastTop, v.getTop(), v.getAlpha()) : v.getAlpha() == 1f ? v.getTop() : lastTop; if (top < lastTop) { lastTop = top; } } } if (isSkeletonVisible()) { boolean drawService = SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW && Theme.hasGradientService(); boolean darkOverlay = ColorUtils.calculateLuminance(getThemedColor(Theme.key_windowBackgroundWhite)) <= 0.7f && Theme.hasGradientService(); boolean blackOverlay = ColorUtils.calculateLuminance(getThemedColor(Theme.key_windowBackgroundWhite)) <= 0.01f && Theme.hasGradientService(); if (drawService) { Theme.applyServiceShaderMatrix(getMeasuredWidth(), AndroidUtilities.displaySize.y, 0, getY() - contentPanTranslation); } int wasDarkenAlpha = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); if (blackOverlay) { Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (wasDarkenAlpha * 4f)); } float topSkeletonAlpha = startMessageAppearTransitionMs != 0 ? 1f - (System.currentTimeMillis() - startMessageAppearTransitionMs) / (float) SKELETON_DISAPPEAR_MS : 1f; int alpha = skeletonPaint.getAlpha(); int wasServiceAlpha = skeletonServicePaint.getAlpha(); int wasOutlineAlpha = skeletonOutlinePaint.getAlpha(); float adaptDark = 1f; if (themeDelegate != null && themeDelegate.isDark && skeletonServicePaint.getShader() != null) { adaptDark *= .3f; } skeletonServicePaint.setAlpha((int) (0xFF * topSkeletonAlpha * adaptDark)); skeletonPaint.setAlpha((int) (topSkeletonAlpha * adaptDark * alpha)); skeletonOutlinePaint.setAlpha((int) (topSkeletonAlpha * alpha)); while (lastTop > blurredViewTopOffset) { lastTop -= AndroidUtilities.dp(3f); MessageSkeleton skeleton; if (j >= messageSkeletons.size()) { skeleton = getNewSkeleton(noAvatar); messageSkeletons.add(skeleton); } else { skeleton = messageSkeletons.get(j); } skeleton.lastBottom = startMessageAppearTransitionMs != 0 ? messages.size() <= 2 ? Math.min(skeleton.lastBottom, lastTop) : skeleton.lastBottom : lastTop; lastTop -= skeleton.height; j++; } lastTop = messageSkeletons.isEmpty() ? getHeight() - blurredViewBottomOffset : messageSkeletons.get(0).lastBottom + AndroidUtilities.dp(3f); int left = dp(noAvatar ? 3 : 51); if (isSideMenued()) { left = lerp(left, dp(SIDE_MENU_WIDTH), getSideMenuAlpha()); } for (int i = 0; i < messageSkeletons.size() && lastTop > blurredViewTopOffset; i++) { lastTop -= dp(3f); MessageSkeleton skeleton = messageSkeletons.get(i); int bottom = skeleton.lastBottom; skeletonBackgroundDrawable.setBounds(left, bottom - skeleton.height, skeleton.width, bottom); if (drawService) { skeletonBackgroundDrawable.drawCached(canvas, skeletonBackgroundCacheParams, skeletonServicePaint); } skeletonBackgroundDrawable.drawCached(canvas, skeletonBackgroundCacheParams, skeletonPaint); if (darkOverlay) { skeletonBackgroundDrawable.drawCached(canvas, skeletonBackgroundCacheParams, Theme.chat_actionBackgroundGradientDarkenPaint); } skeletonBackgroundDrawable.drawCached(canvas, skeletonBackgroundCacheParams, skeletonOutlinePaint); if (!noAvatar) { if (drawService) { canvas.drawCircle(dp(48 - 21), bottom - dp(21), dp(21), skeletonServicePaint); } canvas.drawCircle(dp(48 - 21), bottom - dp(21), dp(21), skeletonPaint); if (darkOverlay) { canvas.drawCircle(dp(48 - 21), bottom - dp(21), dp(21), Theme.chat_actionBackgroundGradientDarkenPaint); } canvas.drawCircle(dp(48 - 21), bottom - dp(21), dp(21), skeletonOutlinePaint); } lastTop -= skeleton.height; } skeletonServicePaint.setAlpha(wasServiceAlpha); skeletonPaint.setAlpha(alpha); skeletonOutlinePaint.setAlpha(wasOutlineAlpha); Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(wasDarkenAlpha); invalidated = false; invalidate(); } else if (System.currentTimeMillis() - startMessageAppearTransitionMs > SKELETON_DISAPPEAR_MS) { messageSkeletons.clear(); } lastSkeletonCount = messageSkeletons.size(); lastSkeletonMessageCount = messages.size(); if (pullingDownOffset != 0) { canvas.restore(); } } super.draw(canvas); } private void updateSkeletonColors() { boolean dark = ColorUtils.calculateLuminance(getThemedColor(Theme.key_windowBackgroundWhite)) <= 0.7f; int color0 = ColorUtils.blendARGB(getThemedColor(Theme.key_listSelector), Color.argb(dark ? 0x21 : 0x03, 0xFF, 0xFF, 0xFF), dark ? 0.9f : 0.5f); int color1 = ColorUtils.setAlphaComponent(getThemedColor(Theme.key_listSelector), dark ? 24 : SKELETON_LIGHT_OVERLAY_ALPHA); if (skeletonColor1 != color1 || skeletonColor0 != color0) { skeletonColor0 = color0; skeletonColor1 = color1; skeletonGradient = new LinearGradient(0, 0, skeletonGradientWidth = AndroidUtilities.dp(200), 0, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); skeletonTotalTranslation = -skeletonGradientWidth * 2; skeletonPaint.setShader(skeletonGradient); int outlineColor = Color.argb(dark ? 0x2B : 0x60, 0xFF, 0xFF, 0xFF); skeletonOutlineGradient = new LinearGradient(0, 0, skeletonGradientWidth, 0, new int[]{Color.TRANSPARENT, outlineColor, outlineColor, Color.TRANSPARENT}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); skeletonOutlinePaint.setShader(skeletonOutlineGradient); } } private void updateSkeletonGradient() { long newUpdateTime = SystemClock.elapsedRealtime(); long dt = Math.abs(skeletonLastUpdateTime - newUpdateTime); if (dt > 17) { dt = 16; } if (dt < 4) { dt = 0; } int width = getWidth(); skeletonLastUpdateTime = newUpdateTime; skeletonTotalTranslation += dt * width / 400.0f; if (skeletonTotalTranslation >= width * 2) { skeletonTotalTranslation = -skeletonGradientWidth * 2; } skeletonMatrix.setTranslate(skeletonTotalTranslation, 0); if (skeletonGradient != null) { skeletonGradient.setLocalMatrix(skeletonMatrix); } skeletonOutlineMatrix.setTranslate(skeletonTotalTranslation, 0); if (skeletonOutlineGradient != null) { skeletonOutlineGradient.setLocalMatrix(skeletonOutlineMatrix); } } @Override protected void dispatchDraw(Canvas canvas) { drawLaterRoundProgressCell = null; invalidated = false; canvas.save(); if ((fragmentTransition == null || (fromPullingDownTransition && !toPullingDownTransition)) && !isInsideContainer) { // canvas.clipRect(0, chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4), getMeasuredWidth(), getMeasuredHeight() - blurredViewBottomOffset); } selectorRect.setEmpty(); if (pullingDownOffset != 0) { int restoreToCount = canvas.save(); float transitionOffset = 0; if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; } canvas.translate(0, drawingChatListViewYoffset = -pullingDownOffset - transitionOffset); drawChatBackgroundElements(canvas); super.dispatchDraw(canvas); drawChatForegroundElements(canvas); canvas.restoreToCount(restoreToCount); } else { drawChatBackgroundElements(canvas); super.dispatchDraw(canvas); drawChatForegroundElements(canvas); } canvas.restore(); } protected 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.getPaddingTop()); 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() + cell.getPaddingTop(); 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() + cell.getPaddingTop(); 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(); } size = drawReactionsAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawReactionsAfter.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() + cell.getPaddingTop(); 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 (!selectionOnly && cell.getTransitionParams().wasDraw) { canvas.translate(canvasOffsetX, canvasOffsetY); cell.setInvalidatesParent(true); cell.drawReactionsLayout(canvas, alpha, null); cell.drawCommentLayout(canvas, alpha); cell.setInvalidatesParent(false); } canvas.restore(); } drawReactionsAfter.clear(); } } protected void drawChatBackgroundElements(Canvas canvas) { final int count = getChildCount(); MessageObject.GroupedMessages lastDrawnGroup = null; for (int a = 0; a < count; a++) { View child = getChildAt(a); if (child.getVisibility() == View.INVISIBLE || child.getVisibility() == View.GONE) { continue; } 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 UserInfoCell) { UserInfoCell cell = (UserInfoCell) child; float top = (getMeasuredHeight() - chatListViewPaddingTop - blurredViewBottomOffset) / 2 - child.getMeasuredHeight() / 2 + chatListViewPaddingTop; if (!cell.animating() && !chatListView.fastScrollAnimationRunning) { if (child.getTop() > top) { child.setTranslationY(top - child.getTop()); } else { child.setTranslationY(0); } } } 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 || scrimViewTask != null) && group == null && cell.drawBackgroundInParent()) { canvas.save(); canvas.translate(cell.getX(), cell.getY() + cell.getPaddingTop()); 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() + cell.getPaddingTop()); canvas.scale(cell.getScaleX(), cell.getScaleY(), cell.getMeasuredWidth() / 2f, cell.getMeasuredHeight() / 2f); canvas.translate(getSideMenuWidth() / 2f, 0); cell.drawBackground(canvas, true); cell.drawReactions(canvas, true, null); 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 || cell.getVisibility() == View.GONE) { 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.getPaddingTop() + cell.getBackgroundDrawableTop()); int bottom = (cell.getTop() + cell.getPaddingTop() + 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++) { final 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 - dp(20)) { t = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - dp(20); } */ if (b > chatListView.getMeasuredHeight() + dp(20)) { b = chatListView.getMeasuredHeight() + 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, 0); if (group != scrimGroup) { 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) { if (isSkeletonVisible()) { invalidated = false; invalidate(); } int clipLeft = 0; int clipBottom = 0; boolean skipDraw = child == scrimView && scrimViewTask == null; ChatMessageCell cell; ChatActionCell actionCell = null; float cilpTop = 0; // chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4); boolean isAnimatingBounds = false; if (child instanceof ChatMessageCell) { cell = (ChatMessageCell) child; isAnimatingBounds = cell.transitionParams.animateBackgroundBoundsInner; } if (!SizeNotifierFrameLayout.drawingBlur && (child.getY() > getMeasuredHeight() || child.getY() + child.getMeasuredHeight() < cilpTop) && !isAnimatingBounds || child.getVisibility() == View.INVISIBLE || child.getVisibility() == View.GONE) { 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 && scrimViewTask == null) { ChatMessageCell cell2 = (ChatMessageCell) scrimView; if (cell2.getCurrentMessagesGroup() != null && cell2.getCurrentMessagesGroup() == group) { skipDraw = true; } } if (skipDraw) { cell.getPhotoImage().skipDraw(); } } else if (child instanceof ChatActionCell) { actionCell = (ChatActionCell) child; cell = null; } else { cell = null; } if (clipLeft != 0) { canvas.save(); } else if (clipBottom != 0) { canvas.save(); } if (skipDraw) { /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (DownscaleScrollableNoiseSuppressor.isRecordingCanvas(canvas)) { skipDraw = false; } }*/ skipDraw = false; } boolean result; if (!skipDraw) { boolean clipToGroupBounds = (cell != null && !cell.transitionParams.needsStopClipping) && (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 && cell.transitionParams.needsStopClipping) { canvas.save(); canvas.translate(cell.getX(), cell.getY()); cell.drawInternal(canvas); canvas.restore(); result = cell.transitionParams.animateChange; } else 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.getPaddingTopAnimated()); cell.drawOutboundsContent(canvas); canvas.restore(); } else if (actionCell != null) { canvas.save(); canvas.translate(actionCell.getX(), actionCell.getY()); actionCell.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 & cell.captionFlag()) != 0) { drawCaptionAfter.add(cell); } if (position == null || (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (position.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { drawReactionsAfter.add(cell); } } } if (videoPlayerContainer != null && (message.isRoundVideo() || message.isVideo()) && !message.isVoiceTranscriptionOpen() && MediaController.getInstance().isPlayingMessage(message)) { ImageReceiver imageReceiver = cell.getPhotoImage(); float newX = imageReceiver.getImageX() + cell.getX(); float newY = cell.getY() + cell.getPaddingTop() + 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 && getSideMenuAlpha() < 1.f) { MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); boolean updateVisibility = !cell.getMessageObject().deleted && chatListView.getChildAdapterPosition(cell) != RecyclerView.NO_POSITION; boolean replaceAnimation = chatListView.isFastScrollAnimationRunning() || (groupedMessages != null && groupedMessages.transitionParams.backgroundChangeBounds); int top = (replaceAnimation ? child.getTop() : (int) child.getY()) + child.getPaddingTop(); 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()) + (child instanceof ChatMessageCell ? ((ChatMessageCell) child).getPaddingTopAnimated() : child.getPaddingTop()) + cell.getLayoutHeight() + cell.getTransitionParams().deltaBottom); int maxY = chatListView.getMeasuredHeight() - chatListView.getPaddingBottom(); boolean canUpdateTx = cell.isCheckBoxVisible() && tx == 0; 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() + view.getPaddingTop(); if (view instanceof ChatMessageCell) { cell = (ChatMessageCell) view; float newTx = cell.getSlidingOffsetX() + cell.getCheckBoxTranslation(); if (canUpdateTx && newTx > 0) { tx = newTx; } if (!cell.drawPinnedTop()) { break; } else { p = prevPosition; } } else { break; } } else { break; } } else { ViewHolder holder = chatListView.findViewHolderForAdapterPosition(prevPosition); if (holder != null) { top = holder.itemView.getTop() + holder.itemView.getPaddingTop(); if (holder.itemView instanceof ChatMessageCell) { cell = (ChatMessageCell) holder.itemView; float newTx = cell.getSlidingOffsetX() + cell.getCheckBoxTranslation(); if (canUpdateTx && newTx > 0) { tx = newTx; } if (!cell.drawPinnedTop()) { break; } else { p = prevPosition; } } else { break; } } else { break; } } } } } if (y - dp(48) < top) { y = top + 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(); } } if (updateVisibility) { imageReceiver.setImageY(y - dp(44)); } if (cell.shouldDrawAlphaLayer()) { imageReceiver.setAlpha((1f - getSideMenuAlpha()) * cell.getAlpha()); canvas.scale( cell.getScaleX(), cell.getScaleY(), cell.getX() + cell.getPivotX(), cell.getY() + (cell.getHeight() >> 1) ); } else { imageReceiver.setAlpha(1f - getSideMenuAlpha()); } if (updateVisibility) { imageReceiver.setVisible(true, false); } if (getSideMenuAlpha() > 0f) { canvas.scale(1f - getSideMenuAlpha(), 1f - getSideMenuAlpha(), imageReceiver.getImageX2(), imageReceiver.getImageY2()); canvas.translate(dp(24) * getSideMenuAlpha(), 0f); } 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); 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(); } }; if (currentEncryptedChat != null) { chatListView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } chatListView.setHideIfEmpty(false); 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); if (ChatObject.isMonoForum(currentChat) || ChatObject.areTabsEnabled(currentChat)) { chatListView.setClipChildren(false); } chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); chatListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); chatListViewPaddingsAnimator = new ChatListViewPaddingsAnimator(chatListView); chatListViewPaddingTop = 0; paddingTopHeight = 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() { 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); finishRunnable = null; } AndroidUtilities.runOnUIThread(finishRunnable = () -> { finishRunnable = null; 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 = () -> { finishRunnable = null; if (scrollAnimationIndex != -1) { getNotificationCenter().onAnimationFinish(scrollAnimationIndex); scrollAnimationIndex = -1; } if (BuildVars.LOGS_ENABLED) { FileLog.d("chatItemAnimator enable notifications"); } }); } }; chatListItemAnimator.setOnSnapMessage(this::supportsThanosEffect, this::getChatThanosEffect); } chatLayoutManager = new GridLayoutManagerFixed(context, 1000, LinearLayoutManager.VERTICAL, !reversed) { boolean computingScroll; @Override public int getStartForFixGap() { int padding = (int) chatListViewPaddingTop; 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 < chatAdapter.getMessages().size()) { MessageObject message = chatAdapter.getMessages().get(index); MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { MessageObject.GroupedMessagePosition pos = group.getPosition(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 (chatListView.getChildAdapterPosition(child) == (reversed ? 0 : 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 || isTopic && !UserObject.isBotForum(currentUser)) && chatMode != MODE_SAVED && chatMode != MODE_SCHEDULED && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && !isReport()) { if (pullingDownOffset == 0 && pullingDownDrawable != null) { if (nextChannels != null && !nextChannels.isEmpty()) { pullingDownDrawable.updateDialog(nextChannels.get(0)); } else if (isTopic) { pullingDownDrawable.updateTopic(); } else { 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)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && scrollableViewNoiseSuppressor != null) { scrollableViewNoiseSuppressor.onScrolled(0, (dy * k)); } chatListView.invalidate(); } if (pullingDownOffset == 0) { chatListView.setOverScrollMode(View.OVER_SCROLL_ALWAYS); } else { chatListView.setOverScrollMode(View.OVER_SCROLL_NEVER); } if (pullingDownDrawable != null) { animatorPullingDownContainerVisibility.setValue(pullingDownOffset > 0 && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING, true); } 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 < chatAdapter.getMessages().size()) { MessageObject message = chatAdapter.getMessages().get(idx); MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { return groupedMessages.getPosition(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; } } } } }); 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; scrollingFloatingTopic = false; scrollingChatListView = false; checkTextureViewPosition = false; hideFloatingDateView(true); hideFloatingTopicView(true); if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { scrolling = true; NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startSpoilers); chatListView.setOverScrollMode(RecyclerView.OVER_SCROLL_ALWAYS); textSelectionHelper.stopScrolling(); updateVisibleRows(); invalidateMergedVisibleBlurredPositionsAndSources(BLUR_INVALIDATE_FLAG_SCROLL); scrollByTouch = false; } else { if (groupEmojiPackHint != null && groupEmojiPackHint.shown()) { groupEmojiPackHint.hide(); } if (searchOtherButton != null && searchOtherButton.getVisibility() == View.VISIBLE && isKeyboardVisible()) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } if (newState == RecyclerView.SCROLL_STATE_SETTLING) { wasManualScroll = true; scrollingChatListView = true; } else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { pollHintCell = null; wasManualScroll = true; scrollingFloatingDate = true; scrollingFloatingTopic = true; checkTextureViewPosition = true; scrollingChatListView = true; } if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { scrolling = false; NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopSpoilers); if (selectionReactionsOverlay != null && selectionReactionsOverlay.isVisible()) { selectionReactionsOverlay.setHiddenByScroll(true); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { chatListView.invalidate(); if (contentView != null) { contentView.updateBlurContent(); } if (chatListThanosEffect != null) { chatListThanosEffect.scroll(dx, dy); } 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) { invalidateMergedVisibleBlurredPositionsAndSources(BLUR_INVALIDATE_FLAG_SCROLL); contentView.invalidateBlur(); hideHints(true); } if (dy != 0 && scrollingFloatingDate && !currentFloatingTopIsNotMessage) { if (highlightMessageId != Integer.MAX_VALUE) { removeSelectedMessageHighlight(); updateVisibleRows(); } showFloatingDateView(true); } if (isAllChats() && dy != 0 && scrollingFloatingTopic && !currentFloatingTopIsNotMessage) { if (highlightMessageId != Integer.MAX_VALUE) { removeSelectedMessageHighlight(); updateVisibleRows(); } showFloatingTopicView(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 { final boolean isPageDownButtonVisible = sideControlsButtonsLayout.isButtonVisible( ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN); if (dy > 0) { if (!isPageDownButtonVisible) { totalDy += dy; if (totalDy > scrollValue) { totalDy = 0; canShowPagedownButton = true; updatePagedownButtonVisibility(true); pagedownButtonShowedByScroll = true; } } } else { if (pagedownButtonShowedByScroll && isPageDownButtonVisible) { totalDy += dy; if (totalDy < -scrollValue) { canShowPagedownButton = false; updatePagedownButtonVisibility(true); totalDy = 0; } } } } } invalidateMessagesVisiblePart(); textSelectionHelper.onParentScrolled(); emojiAnimationsOverlay.onScrolled(dy); ReactionsEffectOverlay.onScrolled(dy); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && scrollableViewNoiseSuppressor != null) { scrollableViewNoiseSuppressor.onScrolled(dx, dy); } checkTranslation(false); if (savedMessagesTagHint != null) { if (savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); } else if (!savedMessagesTagHintShown) { lastScrollTime = System.currentTimeMillis(); AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkSavedMessagesTagHint); AndroidUtilities.runOnUIThread(ChatActivity.this::checkSavedMessagesTagHint, 2000); } } if (videoConversionTimeHint != null && videoConversionTimeHint.shown()) { videoConversionTimeHint.hide(); } if (botMessageHint != null && botMessageHint.shown()) { botMessageHint.hide(); } else { AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkBotMessageHint); AndroidUtilities.runOnUIThread(ChatActivity.this::checkBotMessageHint, 2000); } if (factCheckHint != null) { factCheckHint.hide(); } if (chatActivityEnterView != null) { chatActivityEnterView.hideHints(); } if (starReactionsOverlay != null) { starReactionsOverlay.invalidate(); } } }); contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (getDialogId() != getUserConfig().getClientUserId()) { selectionReactionsOverlay = new ChatSelectionReactionMenuOverlay(this, context); contentView.addView(selectionReactionsOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } 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) { private final RectF rect = new RectF(); @Override protected void dispatchDraw(Canvas canvas) { rect.set(0, 0, getWidth(), getHeight()); applyServiceShaderMatrix(); canvas.drawRoundRect(rect, dp(18), dp(18), getThemedPaint(Theme.key_paint_chatActionBackground)); if (themeDelegate != null ? themeDelegate.hasGradientService() : Theme.hasGradientService()) { canvas.drawRoundRect(rect, dp(18), dp(18), getThemedPaint(Theme.key_paint_chatActionBackgroundDarken)); } super.dispatchDraw(canvas); } public void applyServiceShaderMatrix() { applyServiceShaderMatrix(getMeasuredWidth(), getServiceHeight(this), getX(), getServiceTop(this)); } private void applyServiceShaderMatrix(int measuredWidth, int backgroundHeight, float x, float viewTop) { if (themeDelegate != null) { themeDelegate.applyServiceShaderMatrix(measuredWidth, backgroundHeight, x, viewTop); } else { Theme.applyServiceShaderMatrix(measuredWidth, backgroundHeight, x, viewTop); } } }; 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)); floatingTopicSeparator = new TopicSeparator.Cell(context, currentAccount, themeDelegate) { @Override public void setTranslationY(float translationY) { if (getTranslationY() != translationY) { invalidate(); } super.setTranslationY(translationY); } @Override public boolean onTouchEvent(MotionEvent event) { if (getAlpha() == 0 || actionBar.isActionModeShowed() || isReport()) { return false; } return super.onTouchEvent(event); } }; floatingTopicSeparator.setOnTopicClickListener(topicId -> { if (topicsTabs != null) { topicsTabs.selectTopic(topicId, true); } }); floatingTopicSeparator.setAlpha(0.f); contentView.addView(floatingTopicSeparator, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 4, 0, 0)); floatingDateView = new ChatActionCell(context, false, themeDelegate) { @Override public boolean isFloating() { return true; } @Override public void setTranslationY(float translationY) { if (getTranslationY() != translationY) { invalidate(); } super.setTranslationY(translationY); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (getAlpha() == 0 || actionBar.isActionModeShowed() || isReport()) { return false; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { if (getAlpha() == 0 || actionBar.isActionModeShowed() || isReport()) { return false; } return super.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { if (scrimBlurBitmap != null) return; 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() || isReport()) { 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, contentView, currentChat, this::invalidateChatListViewTopPadding); pendingRequestsDelegate.setChatInfo(chatInfo, false); contentView.addView(pendingRequestsDelegate.getView(), ViewGroup.LayoutParams.MATCH_PARENT, pendingRequestsDelegate.getViewHeight()); pendingRequestsDelegate.setLeftMargin(getSideMenuWidth()); } pinnedMessageView = null; undoView = null; topUndoView = null; topChatPanelView = null; topChatPanelView2 = null; reportSpamButton = null; emojiStatusSpamHint = null; topViewSeparator1 = null; topViewSeparator2 = null; topViewSeparator3 = null; addToContactsButton = null; restartTopicButton = null; closeReportSpam = null; translateButton = null; topicsTabs = null; botAdView = null; bizBotButton = null; topButtonsLayout = new ChatActivitySideControlsButtonsLayout(context, resourceProvider, blurredBackgroundColorProvider, glassBackgroundDrawableFactory); topButtonsLayout.setOnClickListener(this::onSideControlButtonOnClick); topButtonsLayout.setOnLongClickListener(this::onSideControlButtonOnLongClick); topButtonsLayout.setGravity(Gravity.TOP | Gravity.RIGHT); contentView.addView(topButtonsLayout, LayoutHelper.createFrame(57, 300, Gravity.RIGHT | Gravity.TOP)); sideControlsButtonsLayout = new ChatActivitySideControlsButtonsLayout(context, resourceProvider, blurredBackgroundColorProvider, glassBackgroundDrawableFactory); sideControlsButtonsLayout.setOnClickListener(this::onSideControlButtonOnClick); sideControlsButtonsLayout.setOnLongClickListener(this::onSideControlButtonOnLongClick); contentView.addView(sideControlsButtonsLayout, LayoutHelper.createFrame(57, 300, Gravity.RIGHT | Gravity.BOTTOM)); updateMessageListAccessibilityVisibility(); 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(R.string.AppName)); builder.setMessage(LocaleController.getString(R.string.SecretChatContextBotAlert)); builder.setPositiveButton(LocaleController.getString(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(ChatActivity.this, 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, null, null, false, false); } } private boolean wasAtTop = true; @Override protected void onScrolled(boolean atTop, boolean atBottom) { if (wasAtTop != atTop) { AndroidUtilities.updateViewShow(suggestEmojiPanel, !isInPreviewMode() && atTop, false, true); wasAtTop = atTop; } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (getAlpha() <= 0f) return false; return super.dispatchTouchEvent(ev); } }; if (isInPreviewMode()) { mentionContainer.setAlpha(0f); } mentionContainer.setDialogId(dialog_id); mentionContainer.setBackgroundDrawable(glassBackgroundDrawableFactoryFrosted.create(mentionContainer, blurredBackgroundColorProviderWhite)); contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker(TLRPC.Document sticker, String query, Object parent, boolean notify, int scheduleDate, int scheduleRepeatPeriod) { chatActivityEnterView.onStickerSelected(sticker, query, parent, null, true, notify, scheduleDate, scheduleRepeatPeriod); } @Override public boolean needSend(int contentType) { return true; } @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, false); alert.setCalcMandatoryInsets(isKeyboardVisible()); alert.setClearsInputField(clearsInputField); showDialog(alert); } @Override public long getDialogId() { return dialog_id; } }; mentionContainer.getListView().setOnTouchListener((v, event) -> 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 (mentionContainer.getAdapter().isLocalHashtagHint(position)) { chatActivityEnterView.replaceWithText(start, len, mentionContainer.getAdapter().getHashtagHint() + "@" + ChatObject.getPublicUsername(currentChat) + " ", false); return; } else if (mentionContainer.getAdapter().isGlobalHashtagHint(position)) { chatActivityEnterView.replaceWithText(start, len, mentionContainer.getAdapter().getHashtagHint() + " ", false); return; } if (object instanceof QuickRepliesController.QuickReply) { if (!getUserConfig().isPremium()) { showDialog(new PremiumFeatureBottomSheet(this, getContext(), currentAccount, true, PremiumPreviewFragment.PREMIUM_FEATURE_BUSINESS_QUICK_REPLIES, false, null)); return; } AlertsCreator.ensurePaidMessageConfirmation(currentAccount, dialog_id, Math.max(1, ((QuickRepliesController.QuickReply) object).getMessagesCount()), payStars -> { TLRPC.TL_messages_sendQuickReplyMessages req = new TLRPC.TL_messages_sendQuickReplyMessages(); req.peer = getMessagesController().getInputPeer(dialog_id); req.shortcut_id = ((QuickRepliesController.QuickReply) object).id; getConnectionsManager().sendRequest(req, null); if (chatActivityEnterView != null) { chatActivityEnterView.setFieldText(null); } }); } else if (object instanceof TLRPC.TL_document) { if (chatMode == 0 && checkSlowMode(view)) { return; } MessageObject.SendAnimationData sendAnimationData; if (view instanceof StickerCell) { sendAnimationData = ((StickerCell) view).getSendAnimationData(); } else { sendAnimationData = null; } TLRPC.TL_document document = (TLRPC.TL_document) object; Object parent = mentionContainer.getAdapter().getItemParent(position); String query = MessageObject.findAnimatedEmojiEmoticon(document); AlertsCreator.ensurePaidMessageConfirmation(currentAccount, getDialogId(), 1, price -> { if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate, scheduleRepeatPeriod) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, null, notify, scheduleDate, 0, false, parent, quickReplyShortcut, getQuickReplyId(), 0, getSendMonoForumPeerId(), getSendMessageSuggestionParams()), themeDelegate); } else { getSendMessagesHelper().sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, sendAnimationData, true, 0, 0, false, parent, quickReplyShortcut, getQuickReplyId(), price, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); } hideFieldPanel(false); chatActivityEnterView.addStickerToRecent(document); chatActivityEnterView.setFieldText(""); }); } else if (object instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) object; if (searchingForUser && searchContainer != null && searchContainer.getVisibility() == View.VISIBLE) { searchUserMessages(null, chat); } else { String username = ChatObject.getPublicUsername(chat); if (username != null) { chatActivityEnterView.replaceWithText(start, len, "@" + username + " ", false); } } } else if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; if (searchingForUser && searchContainer != null && searchContainer.getVisibility() == View.VISIBLE) { searchUserMessages(user, null); } else { if (UserObject.getPublicUsername(user) != null) { chatActivityEnterView.replaceWithText(start, len, "@" + UserObject.getPublicUsername(user) + " ", 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, scheduleRepeatPeriod) -> { getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of((String) object, dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, notify, scheduleDate, 0, null, false)); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); }, themeDelegate); } else { if (checkSlowMode(view)) { return; } AlertsCreator.ensurePaidMessageConfirmation(currentAccount, dialog_id, 1, payStars -> { final SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of((String) object, dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, 0, null, false); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.payStars = payStars; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; getSendMessagesHelper().sendMessage(params); 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(R.string.SendMessageTitle)); if (error == 1) { builder.setMessage(LocaleController.getString(R.string.GameCantSendSecretChat)); } else { builder.setMessage(LocaleController.getString(R.string.InvoiceCantSendSecretChat)); } builder.setNegativeButton(LocaleController.getString(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(ChatActivity.this, themeDelegate); PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionContainer.getAdapter().getItemPosition(position), 3, false, botContextProvider, ChatActivity.this); } else { AlertsCreator.ensurePaidMessageConfirmation(currentAccount, getDialogId(), 1, price -> { if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate, scheduleRepeatPeriod) -> sendBotInlineResult(result, notify, scheduleDate, price), themeDelegate); } else { sendBotInlineResult(result, true, 0, price); } }); } } else if (object instanceof TLRPC.TL_inlineBotWebView) { processInlineBotWebView((TLRPC.TL_inlineBotWebView) object); } 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 { Paint.FontMetricsInt fontMetrics = null; try { fontMetrics = chatActivityEnterView.getEditField().getPaint().getFontMetricsInt(); } catch (Exception e) { FileLog.e(e, false); } 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, fontMetrics); } else { span = new AnimatedEmojiSpan(documentId, fontMetrics); } 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; } if (position == 0 || mentionContainer.getAdapter().isBannedInline()) { return false; } position--; 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(R.string.AppName)); builder.setMessage(LocaleController.getString(R.string.ClearSearch)); builder.setPositiveButton(LocaleController.getString(R.string.ClearButton), (dialogInterface, i) -> mentionContainer.getAdapter().clearRecentHashtags()); builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); showDialog(builder.create()); return true; } } return false; }); if (!isInsideContainer) { fragmentLocationContextView = new FragmentContextView(context, this, null, true, themeDelegate); fragmentContextView = new FragmentContextView(context, this, null, false, themeDelegate); 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); } } messagesSearchListContainer = new FrameLayout(context); BlurredBackgroundDrawable searchContainerDrawable = (glassBackgroundDrawableFactoryFrosted != null ? glassBackgroundDrawableFactoryFrosted : glassBackgroundDrawableFactory).create(messagesSearchListContainer, blurredBackgroundColorProviderWhite); searchContainerDrawable.setPadding(dp(5)); searchContainerDrawable.setRadius(dp(22)); messagesSearchListContainer.setBackground(searchContainerDrawable); messagesSearchListContainer.setClipToOutline(true); messagesSearchListContainer.setOutlineProvider(searchContainerDrawable.getViewOutlineProvider()); messagesSearchListContainer.setVisibility(View.GONE); messagesSearchListContainer.setPadding(dp(5), dp(5), dp(5), dp(5)); messagesSearchListContainer.setAlpha(0.0f); contentView.addView(messagesSearchListContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); messagesSearchListView = new RecyclerListView(context, themeDelegate) { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (messagesSearchAdapter != null) { messagesSearchAdapter.attach(); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (messagesSearchAdapter != null) { messagesSearchAdapter.detach(); } } }; LinearLayoutManager messagesSearchLayoutManager = new LinearLayoutManager(context); messagesSearchLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); messagesSearchListView.setLayoutManager(messagesSearchLayoutManager); messagesSearchListView.setAdapter(messagesSearchAdapter = new MessagesSearchAdapter(context, this, themeDelegate, searchType, dialog_id == getUserConfig().getClientUserId())); checkHashtagStories(true); DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); itemAnimator.setSupportsChangeAnimations(false); itemAnimator.setDelayAnimations(false); itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); itemAnimator.setDurations(350); messagesSearchListView.setItemAnimator(itemAnimator); messagesSearchListContainer.addView(messagesSearchListView, LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT); messagesSearchListView.setOnItemClickListener((view, position) -> { if (chatMode == MODE_SEARCH) { Object obj = messagesSearchAdapter.getItem(position); if (position == 0 && messagesSearchAdapter.containsStories && messagesSearchAdapter.storiesList != null) { Bundle args = new Bundle(); args.putInt("type", MediaActivity.TYPE_STORIES_SEARCH); args.putString("hashtag", messagesSearchAdapter.storiesList.query); if (messagesSearchAdapter.storiesList.username != null) { args.putString("username", messagesSearchAdapter.storiesList.username); } args.putInt("storiesCount", messagesSearchAdapter.storiesList.getCount()); presentFragment(new MediaActivity(args, null)); } else if (obj instanceof MessageObject) { openMessageInOriginalDialog((MessageObject) obj); } } else if (searchingReaction != null) { if (position < 0 || position >= getMediaDataController().searchResultMessages.size()) return; MessageObject msg = getMediaDataController().searchResultMessages.get(position); setFilterMessages(searchingFiltered = false, true, false); getMediaDataController().setSearchedPosition(position); updateSearchButtons(getMediaDataController().getMask(), getMediaDataController().getSearchPosition(), getMediaDataController().getSearchCount()); AndroidUtilities.runOnUIThread(() -> { scrollToMessageId(msg.getId(), 0, true, 0, true, 0, null, () -> { progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, themeDelegate); progressDialog.setOnShowListener(dialogInterface -> showPinnedProgress(false)); progressDialog.setOnCancelListener(postponedScrollCancelListener); progressDialog.showDelayed(500); }); if (waitingForLoad.isEmpty()) { showMessagesSearchListView(false); } }); } else { getMediaDataController().jumpToSearchedMessage(classGuid, position); showMessagesSearchListView(false); } }); messagesSearchListView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { AndroidUtilities.hideKeyboard(contentView); } int lastVisibleItem = messagesSearchLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; if (visibleItemCount > 0 && lastVisibleItem > messagesSearchAdapter.loadedCount - 5) { if (chatMode == MODE_SEARCH) { if (!loading && !endReached[0]) { loading = true; waitingForLoad.add(lastLoadIndex); HashtagSearchController.getInstance(currentAccount).searchHashtag(searchingHashtag, classGuid, searchType, lastLoadIndex++); } } else { getMediaDataController().loadMoreSearchMessages(true); } } } }); hashtagLoadingView = new FlickerLoadingView(context, themeDelegate); hashtagLoadingView.setViewType(FlickerLoadingView.DIALOG_CELL_TYPE); hashtagSearchEmptyView = new StickerEmptyView(getContext(), hashtagLoadingView, StickerEmptyView.STICKER_TYPE_SEARCH); hashtagSearchEmptyView.setClickable(true); hashtagSearchEmptyView.title.setText(LocaleController.getString(R.string.NoResult)); hashtagSearchEmptyView.setVisibility(View.GONE); hashtagSearchEmptyView.addView(hashtagLoadingView, 0); hashtagSearchEmptyView.showProgress(true, false); messagesSearchListContainer.addView(hashtagSearchEmptyView, new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); if (parentThemeDelegate == null && !isInsideContainer) { searchViewPager = new ViewPagerFixed(context, resourceProvider) { @Override public boolean onTouchEvent(MotionEvent ev) { return false; } @Override protected boolean canScroll(MotionEvent e) { return hashtagSearchTabs != null && hashtagSearchTabs.shown(); } @Override public void onTabAnimationUpdate(boolean manual) { super.onTabAnimationUpdate(manual); contentView.invalidateBlur(); contentView.updateBlurContent(); } @Override protected void onTabScrollEnd(int position) { super.onTabScrollEnd(position); if (position == 0 && requestClearSearchPages) { requestClearSearchPages = false; searchViewPager.clearViews(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (child instanceof ChatActivityContainer) { int p = actionBar.getHeight(); // + hashtagSearchTabs.getHeight(); ChatActivity chatActivity = ((ChatActivityContainer) child).chatActivity; if (chatActivity.contentView != null) { chatActivity.contentView.setPadding(0, p, 0, 0); } } } } }; searchViewPager.setAdapter(new ViewPagerFixed.Adapter() { @Override public int getItemCount() { return 3; } @Override public int getItemViewType(int position) { return position; } @Override public View createView(int viewType) { if (viewType == SEARCH_THIS_CHAT) { return new FirstViewPage(context); } else { Bundle args = new Bundle(); args.putInt("chatMode", ChatActivity.MODE_SEARCH); args.putInt("searchType", viewType); args.putString("searchHashtag", searchingHashtag); ChatActivityContainer container = new ChatActivityContainer(context, getParentLayout(), args) { boolean activityCreated = false; @Override protected void initChatActivity() { if (!activityCreated) { activityCreated = true; super.initChatActivity(); } } }; container.chatActivity.navbarContentSourceWallpaper.setSource(navbarContentSourceWallpaper); container.chatActivity.parentThemeDelegate = themeDelegate; container.chatActivity.parentChatActivity = ChatActivity.this; container.chatActivity.chatActivityDelegate = new ChatActivityDelegate() { @Override public void openHashtagSearch(String hashtag) { ChatActivity.this.openHashtagSearch(hashtag); } }; return container; } } @Override public void bindView(View view, int position, int viewType) { if (view instanceof ChatActivityContainer) { ((ChatActivityContainer) view).chatActivity.updateSearchingHashtag(searchingHashtag); } else if (view instanceof PublicStoriesList) { ((PublicStoriesList) view).setTabs(parentChatActivity != null ? parentChatActivity.hashtagSearchTabs.isShown() : hashtagSearchTabs.isShown()); ((PublicStoriesList) view).setQuery("", searchingHashtag); } ViewCompat.requestApplyInsets(view); } @Override public String getItemTitle(int position) { switch (position) { case SEARCH_MY_MESSAGES: return LocaleController.getString(R.string.SearchMyMessages); case SEARCH_PUBLIC_POSTS: return LocaleController.getString(R.string.SearchPublicPosts); default: case SEARCH_THIS_CHAT: return LocaleController.getString(R.string.SearchThisChat); } } }); searchViewPager.setAllowDisallowInterceptTouch(false); contentView.addView(searchViewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); hashtagSearchTabs = new ChatSearchTabs(context, contentView) { @Override protected void onShownUpdate(boolean finish) { setBackgroundColor(actionBar.getBackgroundColor()); if (tagSelector != null) { tagSelector.setTranslationY(contentPanTranslation + getCurrentHeight()); } if (finish) { invalidateChatListViewTopPadding = true; updateChatListViewTopPadding(); } else { invalidateChatListViewTopPadding(); } } }; hashtagSearchTabs.setVisibility(View.GONE); hashtagSearchTabs.setTabs(searchViewPager.createTabsView(true, 8)); contentView.addView(hashtagSearchTabs, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.FILL_HORIZONTAL | Gravity.TOP)); } contentView.addView(actionBar); overlayView = new View(context); overlayView.setOnTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_DOWN) { checkRecordLocked(true, 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 = null; chatActivityEnterView = new ChatActivityEnterView(getParentActivity(), contentView, this, chatMode != MODE_EDIT_BUSINESS_LINK, themeDelegate) { int lastContentViewHeight; int messageEditTextPredrawHeigth; int messageEditTextPredrawScrollY; @Override protected void onChangedIslandTotalHeight(float h) { checkUi_inputIslandHeight(); } @Override public void setAlpha(float alpha) { super.setAlpha(alpha); } @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 openKeyboard() { if (forwardingPreviewView != null) { return; } super.openKeyboard(); } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); bottomViewsVisibilityController.setViewVisible(MESSAGE_INPUT_CONTAINER, visibility == VISIBLE, getMeasuredWidth() > 0); } @Override public void checkAnimation() { if (actionBar.isActionModeShowed() || isReport()) { 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; setAnimatedTop(dy); messageEditTextContainer.invalidate(); if (changeBoundAnimator != null) { changeBoundAnimator.removeAllListeners(); changeBoundAnimator.cancel(); } // chatListView.setTranslationY(dy); if (topView != null && topView.getVisibility() == View.VISIBLE) { topView.setTranslationY(animatedTop + (1f - getTopViewEnterProgress()) * topView.getLayoutParams().height); } changeBoundAnimator = ValueAnimator.ofFloat(dy, 0); changeBoundAnimator.addUpdateListener(a -> { float top = (float) a.getAnimatedValue(); setAnimatedTop((int) top); if (topView != null && topView.getVisibility() == View.VISIBLE) { topView.setTranslationY(top + (1f - getTopViewEnterProgress()) * topView.getLayoutParams().height); } else { invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } messageEditTextContainer.invalidate(); invalidate(); }); changeBoundAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { setAnimatedTop(0); if (topView != null && topView.getVisibility() == View.VISIBLE) { topView.setTranslationY(animatedTop + (1f - getTopViewEnterProgress()) * topView.getLayoutParams().height); } 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) { if (chatListView != null && (searchExpandProgress > 0 || actionBar != null && actionBar.isActionModeShowed())) { return; } shouldAnimateEditTextWithBounds = true; messageEditTextPredrawHeigth = messageEditText.getMeasuredHeight(); messageEditTextPredrawScrollY = messageEditText.getScrollY(); contentView.invalidate(); chatActivityEnterViewAnimateFromTop = chatActivityEnterView.getBackgroundTop(); } } @Override public void hideTopView(boolean animated) { super.hideTopView(animated); if (onHideFieldPanelRunnable != null) { AndroidUtilities.runOnUIThread(onHideFieldPanelRunnable); onHideFieldPanelRunnable = null; } } }; chatActivityEnterView.setVisibility(View.VISIBLE); chatActivityEnterView.getEditField().adaptiveCreateLinkDialog = true; if (chatMode == MODE_EDIT_BUSINESS_LINK) { chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override public void onMessageSend(CharSequence message, boolean notify, int scheduleDate, int scheduleRepeatPeriod, long payStars) {} @Override public void needSendTyping() {} @Override public void onTextChanged(CharSequence text, boolean bigChange, boolean fromDraft) {} @Override public void onTextSelectionChanged(int start, int end) {} @Override public void onTextSpansChanged(CharSequence text) {} @Override public void onAttachButtonHidden() {} @Override public void onAttachButtonShow() {} @Override public void onWindowSizeChanged(int size) {} @Override public void onStickersTab(boolean opened) {} @Override public void onMessageEditEnd(boolean loading) {} @Override public void didPressAttachButton() {} @Override public void needStartRecordVideo(int state, boolean notify, int scheduleDate, int scheduleRepeatPeriod, int ttl, long effectId, long stars) {} @Override public void toggleVideoRecordingPause() {} @Override public boolean isVideoRecordingPaused() { return false; } @Override public void needChangeVideoPreviewState(int state, float seekProgress) {} @Override public void onSwitchRecordMode(boolean video) {} @Override public void onPreAudioVideoRecord() {} @Override public void needStartRecordAudio(int state) {} @Override public void needShowMediaBanHint() {} @Override public void onStickersExpandedChange() {} @Override public void onUpdateSlowModeButton(View button, boolean show, CharSequence time) {} @Override public void onSendLongClick() {} @Override public void onAudioVideoInterfaceUpdated() {} }); } else { chatActivityEnterView.setDelegate(new ChatActivityEnterViewDelegate()); } chatActivityEnterView.setSideButtonsForAttach(topButtonsLayout); chatActivityEnterView.setInAppInsetsController(windowInsetsStateHolder); chatActivityEnterView.setDialogId(dialog_id, currentAccount); if (chatInfo != null) { chatActivityEnterView.setChatInfo(chatInfo); } chatActivityEnterView.setId(id_chat_compose_panel); chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands, hasQuickReplies, false); chatActivityEnterView.updateBotWebView(false); chatActivityEnterView.setMinimumHeight(AndroidUtilities.dp(51)); chatActivityEnterView.setAllowStickersAndGifs(true, true, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); chatActivityEnterView.shouldDrawBackground = false; if (textToSet != null) { chatActivityEnterView.setFieldText(textToSet); textToSet = null; } if (inPreviewMode || isInsideContainer) { chatActivityEnterView.setVisibility(View.INVISIBLE); } if (!ChatObject.isChannel(currentChat) || currentChat.megagroup) { chatActivityEnterView.setBotInfo(botInfo, false); } // contentView.addView(chatActivityEnterView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); chatActivityEnterView.setViewParentForEmoji(chatInputInAppContainer); chatInputBubbleContainer.addView(chatActivityEnterView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 7, 0, 7, 0)); contentView.addView(chatInputViewsContainer.getFadeView(), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); contentView.addView(chatInputViewsContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (chatMode != MODE_EDIT_BUSINESS_LINK) { chatActivityEnterView.checkChannelRights(); } actionsButtonsLayout = new ChatActivityActionsButtonsLayout(context, resourceProvider, blurredBackgroundColorProvider, glassBackgroundDrawableFactory); actionsButtonsLayout.setForwardButtonOnClickListener(v -> openForward(false)); actionsButtonsLayout.setReplyButtonOnClickListener(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(); updateSelectedMessageReactions(); }); bottomViewsVisibilityController.setViewVisible(MESSAGE_ACTION_CONTAINER, false, false); chatInputBubbleContainer.addView(actionsButtonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 106, Gravity.BOTTOM, 0, 0, 0, -56)); chatActivityEnterView.setSuggestionButtonVisible(ChatObject.isMonoForum(currentChat), false); 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); } } } }; chatActivityEnterView.addTopView(chatActivityEnterTopView, 48); if (chatMode == MODE_EDIT_BUSINESS_LINK) { chatActivityEnterView.setEditingBusinessLink(businessLink); } final FrameLayout replyLayout = new FrameLayout(context); chatActivityEnterTopView.addReplyView(replyLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 52, 0)); boolean[] byButtonPress = new boolean[1]; replyLayout.setOnClickListener(v -> { final boolean isButtonPress = byButtonPress[0]; if (isButtonPress) { byButtonPress[0] = false; } if (fieldPanelShown == 5) { new MessageSuggestionOfferSheet(context, currentAccount, dialog_id, messageSuggestionParams != null ? messageSuggestionParams: MessageSuggestionParams.empty(), this, getResourceProvider(), MessageSuggestionOfferSheet.MODE_INPUT, this::showFieldPanelForSuggestionParams).show(); } else if (fieldPanelShown == 1 && editingMessageObject != null) { if (editingMessageObject.needResendWhenEdit() && !isButtonPress) { showSuggestionOfferForEditMessage(messageSuggestionParams != null ? messageSuggestionParams: MessageSuggestionParams.empty()); } else if (editingMessageObject.canEditMedia() && editingMessageObjectReqId == 0) { Utilities.Callback open = type -> { if (chatAttachAlert == null) { createChatAttachView(); } chatAttachAlert.setEditingMessageObject(type, editingMessageObject); openAttachMenu(); }; open.run(ChatAttachAlert.EDITMEDIA_TYPE_ANY); // if (editingMessageObject.hasValidGroupId()) { // open.run(-1); // } else { // ItemOptions.makeOptions(ChatActivity.this, replyLayout, true) // .add(editingMessageObject.isMediaEmpty() ? R.drawable.msg_addphoto : R.drawable.msg_photos, getString(editingMessageObject.isMediaEmpty() ? R.string.MessageAddPhotoVideo : R.string.MessageReplacePhotoVideo), () -> open.run(ChatAttachAlert.EDITMEDIA_TYPE_PHOTOVIDEO)) // .add(editingMessageObject.isMediaEmpty() ? R.drawable.menu_sendfile_plus : R.drawable.msg_sendfile, getString(editingMessageObject.isMediaEmpty() ? R.string.MessageAddFile : R.string.MessageReplaceFile), () -> open.run(ChatAttachAlert.EDITMEDIA_TYPE_FILE)) // .add(editingMessageObject.isMediaEmpty() ? R.drawable.files_music : R.drawable.files_music, getString(editingMessageObject.isMediaEmpty() ? R.string.MessageAddMusic : R.string.MessageReplaceMusic), () -> open.run(ChatAttachAlert.EDITMEDIA_TYPE_MUSIC)) // .setDrawScrim(false).setGravity(Gravity.LEFT).forceTop(true).translate(0, dp(48)) // .show(); // } } else { scrollToMessageId(editingMessageObject.getId(), 0, true, 0, true, 0); } } else if (messagePreviewParams != null) { forbidForwardingWithDismiss = false; if (fieldPanelShown == 2) { if (DialogObject.isEncryptedDialog(dialog_id) || messagePreviewParams.hasSecretMessages || chatMode == MODE_QUICK_REPLIES) { if (replyingMessageObject != null) { scrollToMessageId(replyingMessageObject.getId(), 0, true, 0, true, 0); } } else { forbidForwardingWithDismiss = messagePreviewParams.quote == null; SharedConfig.replyingOptionsHintHintShowed(); openForwardingPreview(MessagePreviewView.TAB_REPLY); } } else if (fieldPanelShown == 3) { SharedConfig.forwardingOptionsHintHintShowed(); openForwardingPreview(MessagePreviewView.TAB_FORWARD); } else if (fieldPanelShown == 4) { openForwardingPreview(MessagePreviewView.TAB_LINK); } } }); replyLayout.setOnLongClickListener(v -> { if (fieldPanelShown == 1 && editingMessageObject != null) { scrollToMessageId(editingMessageObject.getId(), 0, true, 0, true, 0); return true; } else if (messagePreviewParams != null) { if (fieldPanelShown == 2) { if (replyingMessageObject != null) { scrollToMessageId(replyingMessageObject.getId(), 0, true, 0, true, 0); return true; } } } return false; }); 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_glass_defaultIcon), PorterDuff.Mode.MULTIPLY)); replyCloseImageView.setImageResource(R.drawable.input_clear); replyCloseImageView.setScaleType(ImageView.ScaleType.CENTER); 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 -> { messageSuggestionParams = null; if (fieldPanelShown == 2) { replyingQuote = null; replyingMessageObject = null; if (messagePreviewParams != null) { messagePreviewParams.updateReply(null, null, dialog_id, null); } fallbackFieldPanel(); } else if (fieldPanelShown == 3) { openAnotherForward(); } else if (fieldPanelShown == 4) { foundWebPage = null; if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, null, null, replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } chatActivityEnterView.setWebPage(null, false); editResetMediaManual(); fallbackFieldPanel(); } else { if (ChatObject.isForum(currentChat) && !isTopic && replyingMessageObject != null) { long topicId = MessageObject.getTopicId(currentAccount, replyingMessageObject.messageOwner, true); if (topicId != 0) { getMediaDataController().cleanDraft(dialog_id, topicId, false); } } showFieldPanel(false, null, null, null, null, true, 0, null, true, 0, true); } }); replyNameTextView = new SimpleTextView(context); replyNameTextView.setTextSize(14); replyNameTextView.setTextColor(getThemedColor(Theme.key_chat_replyPanelName)); replyNameTextView.setTypeface(AndroidUtilities.bold()); 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_glass_defaultText)); replyObjectTextView.setLinkTextColor(getThemedColor(Theme.key_chat_messageLinkIn)); 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_glass_defaultText)); replyObjectHintTextView.setText(LocaleController.getString(R.string.TapForForwardingOptions)); replyObjectHintTextView.setAlpha(0f); replyLayout.addView(replyObjectHintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 52, 24, 0, 0)); SpoilerEffect replySpoilerEffect = new SpoilerEffect(); replyImageView = new BackupImageView(context) { Path path = new Path(); @Override public void draw(Canvas canvas) { super.draw(canvas); if (replyImageHasMediaSpoiler) { path.rewind(); AndroidUtilities.rectTmp.set(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX2(), imageReceiver.getImageY2()); path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Path.Direction.CW); canvas.save(); canvas.clipPath(path); int sColor = Color.WHITE; replySpoilerEffect.setColor(ColorUtils.setAlphaComponent(sColor, (int) (Color.alpha(sColor) * 0.325f))); replySpoilerEffect.setBounds((int) imageReceiver.getImageX(), (int) imageReceiver.getImageY(), (int) imageReceiver.getImageX2(), (int) imageReceiver.getImageY2()); replySpoilerEffect.draw(canvas); invalidate(); canvas.restore(); } } }; replyImageView.setRoundRadius(AndroidUtilities.dp(2)); replyLayout.addView(replyImageView, LayoutHelper.createFrame(34, 34, Gravity.TOP | Gravity.LEFT, 52, 6, 0, 0)); contentView.addView( suggestEmojiPanel = new SuggestEmojiView(context, currentAccount, chatActivityEnterView, themeDelegate), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 160, Gravity.LEFT | Gravity.BOTTOM, 7, 0, 7, 0) ); suggestEmojiPanel.setVisibility(allowStickersPanel && !isInPreviewMode() && (chatActivityEnterView == null || !chatActivityEnterView.isStickersExpanded()) ? View.VISIBLE : View.GONE); 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.addSpaceView(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.bold()); 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 { byButtonPress[0] = true; replyLayout.callOnClick(); } }); } searchContainer = null; bottomOverlay = new FrameLayout(context) { @Override public void setVisibility(int visibility) { super.setVisibility(visibility); bottomViewsVisibilityController.setViewVisible(BOTTOM_OVERLAY_TEXT_CONTAINER, visibility == VISIBLE, getMeasuredWidth() > 0); } }; bottomOverlay.setWillNotDraw(false); bottomOverlay.setVisibility(View.INVISIBLE); bottomOverlay.setFocusable(true); bottomOverlay.setFocusableInTouchMode(true); bottomOverlay.setClickable(true); chatInputBubbleContainer.addView(bottomOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44, Gravity.BOTTOM, 7, 0, 7, 0)); 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)); bottomOverlayText.setPadding(dp(24), 0, dp(24), 0); bottomOverlay.addView(bottomOverlayText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); bottomChannelButtonsLayout = new ChatActivityChannelButtonsLayout(context, resourceProvider, blurredBackgroundColorProvider, glassBackgroundDrawableFactory) { @Override public void setVisibility(int visibility) { super.setVisibility(visibility); bottomViewsVisibilityController.setViewVisible(BOTTOM_OVERLAY_CHAT_CONTAINER, visibility == VISIBLE, getMeasuredWidth() > 0); } }; bottomChannelButtonsLayout.setVisibility(View.INVISIBLE); bottomChannelButtonsLayout.setClipChildren(false); bottomChannelButtonsLayout.setAccentColor(getThemedColor(Theme.key_featuredStickers_addButton)); bottomChannelButtonsLayout.setButtonOnClickListener(ChatActivityChannelButtonsLayout.BUTTON_SEARCH, v -> { openSearchWithText(isSupportedTags() ? "" : null); }); bottomChannelButtonsLayout.setButtonOnClickListener(ChatActivityChannelButtonsLayout.BUTTON_GIGA_GROUP_INFO, v -> { createUndoView(); undoView.showWithAction(dialog_id, UndoView.ACTION_TEXT_INFO, LocaleController.getString(R.string.BroadcastGroupInfo)); }); bottomChannelButtonsLayout.setButtonOnClickListener(ChatActivityChannelButtonsLayout.BUTTON_GIFT, v -> { MessagesController.getGlobalMainSettings().edit().putInt("channelgifthint", 3).apply(); showDialog(new GiftSheet(getContext(), currentAccount, getDialogId(), null, null)); }); bottomChannelButtonsLayout.setButtonOnClickListener(ChatActivityChannelButtonsLayout.BUTTON_DIRECT, v -> { MessagesController.getGlobalMainSettings().edit().putInt("channelsuggesthint", 3).apply(); if (currentChat != null && currentChat.linked_monoforum_id != 0) { getMessagesController().putMonoForumLinkedChat(currentChat.id, currentChat.linked_monoforum_id); Bundle bundle = new Bundle(); bundle.putLong("chat_id", currentChat.linked_monoforum_id); bundle.putInt("chatMode", MODE_SUGGESTIONS); bundle.putBoolean("isSubscriberSuggestions", true); presentFragment(new ChatActivity(bundle)); } }); bottomChannelButtonsLayout.setButtonOnFullyVisibleListener(ChatActivityChannelButtonsLayout.BUTTON_GIFT, (v, id, firstTime) -> { if (bottomGiftHintView == null && firstTime && MessagesController.getGlobalMainSettings().getInt("channelgifthint", 0) < 2 && (bottomSuggestHintView == null || !bottomSuggestHintView.shown())) { AndroidUtilities.runOnUIThread(() -> { if (getContext() == null) return; final float offset = windowInsetsStateHolder.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom / AndroidUtilities.density; final float translate = (contentView.getWidth() - (v.getX() + v.getWidth()) + v.getWidth() / 2f) / AndroidUtilities.density; bottomGiftHintView = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM); bottomGiftHintView.setPadding(dp(7.33f), 0, dp(7.33f), 0); bottomGiftHintView.setMultilineText(false); bottomGiftHintView.setText(getString(R.string.Gift2ChannelSendHint)); bottomGiftHintView.setJoint(1, -translate + 7.33f); contentView.addView(bottomGiftHintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 100, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 0, offset + 50)); bottomGiftHintView.setOnHiddenListener(() -> AndroidUtilities.removeFromParent(bottomGiftHintView)); bottomGiftHintView.show(); MessagesController.getGlobalMainSettings().edit().putInt("channelgifthint", MessagesController.getGlobalMainSettings().getInt("channelgifthint", 0) + 1).apply(); }, 400); } }); bottomChannelButtonsLayout.setButtonOnFullyVisibleListener(ChatActivityChannelButtonsLayout.BUTTON_DIRECT, (v, id, firstTime) -> { if (bottomSuggestHintView == null && firstTime && MessagesController.getGlobalMainSettings().getInt("channelsuggesthint", 0) < 2) { AndroidUtilities.runOnUIThread(() -> { if (getContext() == null) return; final float offset = windowInsetsStateHolder.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom / AndroidUtilities.density; final float translate = (contentView.getWidth() - (v.getX() + v.getWidth()) + v.getWidth() / 2f) / AndroidUtilities.density; bottomSuggestHintView = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM); bottomSuggestHintView.setPadding(dp(7.33f), 0, dp(7.33f), 0); bottomSuggestHintView.setMultilineText(false); bottomSuggestHintView.setText(getString(R.string.Suggest2ChannelSendHint), true); bottomSuggestHintView.setJoint(1, -translate + 7.33f); contentView.addView(bottomSuggestHintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 100, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 0, offset + 50)); bottomSuggestHintView.setOnHiddenListener(() -> AndroidUtilities.removeFromParent(bottomSuggestHintView)); bottomSuggestHintView.show(); MessagesController.getGlobalMainSettings().edit().putInt("channelsuggesthint", MessagesController.getGlobalMainSettings().getInt("channelsuggesthint", 0) + 1).apply(); }, 400); } }); bottomChannelButtonsLayout.setOnButtonsTotalWidthChanged((l, r) -> { chatInputViewsContainer.setInputBubbleOffsets(l, r); }); chatInputBubbleContainer.addView(bottomChannelButtonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 56, Gravity.BOTTOM, 0, 0, 0, (44 - 56) / 2)); bottomOverlayStartButton = new TextView(context) { CellFlickerDrawable cellFlickerDrawable; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (cellFlickerDrawable == null) { cellFlickerDrawable = new CellFlickerDrawable(); cellFlickerDrawable.drawFrame = false; cellFlickerDrawable.repeatProgress = 2f; } cellFlickerDrawable.setParentWidth(getMeasuredWidth()); AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(22), null); invalidate(); } }; bottomOverlayStartButton.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 22)); bottomOverlayStartButton.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); bottomOverlayStartButton.setText(LocaleController.getString(R.string.BotStart)); bottomOverlayStartButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); bottomOverlayStartButton.setGravity(Gravity.CENTER); bottomOverlayStartButton.setTypeface(AndroidUtilities.bold()); bottomOverlayStartButton.setVisibility(View.GONE); bottomOverlayStartButton.setOnClickListener(v -> bottomOverlayChatText.callOnClick()); bottomChannelButtonsLayout.getContainer().addView(bottomOverlayStartButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.CENTER, 3, 3, 3, 3)); if (currentUser != null && currentUser.bot && currentUser.id != UserObject.VERIFY && !UserObject.isDeleted(currentUser) && !UserObject.isReplyUser(currentUser) && !isInScheduleMode() && chatMode != MODE_PINNED && chatMode != MODE_SAVED && !isReport() && !UserObject.isBotForum(currentUser)) { bottomOverlayStartButton.setVisibility(View.VISIBLE); bottomChannelButtonsLayout.setVisibility(View.VISIBLE); } bottomOverlayLinksText = new LinkSpanDrawable.LinksTextView(context, themeDelegate); bottomOverlayLinksText.setVisibility(View.GONE); bottomOverlayLinksText.setGravity(Gravity.CENTER); bottomOverlayLinksText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); bottomOverlayLinksText.setTextColor(getThemedColor(Theme.key_graySectionText)); bottomOverlayLinksText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); bottomChannelButtonsLayout.getContainer().addView(bottomOverlayLinksText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); bottomOverlayLinksText.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); bottomOverlayLinksText.setOnClickListener(v -> { if (chatMode == MODE_DEFAULT && getMessagesController().freezeUntilDate > getConnectionsManager().getCurrentTime() && !AccountFrozenAlert.isSpamBot(currentAccount, currentUser)) { AccountFrozenAlert.show(getContext(), currentAccount, getResourceProvider()); } }); bottomOverlayChatText = new UnreadCounterTextView(context) { @Override protected void updateCounter() { 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) { setCounter(dialog.unread_count); return; } } setCounter(0); } @Override protected Theme.ResourcesProvider getResourceProvider() { return themeDelegate; } }; bottomChannelButtonsLayout.getContainer().addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0)); bottomOverlayChatText.setOnClickListener(view -> { if (getParentActivity() == null || pullingDownOffset != 0) { return; } if (chatMode == MODE_SAVED) { Bundle args = new Bundle(); long dialogId = getSavedDialogId(); if (dialogId >= 0) { args.putLong("user_id", dialogId); } else { args.putLong("chat_id", -dialogId); } presentFragment(new ChatActivity(args)); } else if (isReport()) { ArrayList ids = new ArrayList<>(); for (int b = 0; b < selectedMessagesIds[0].size(); b++) { ids.add(selectedMessagesIds[0].keyAt(b)); } showBottomOverlayProgress(true, true); ReportBottomSheet.continueReport(this, reportOption, reportMessage, ids, status -> { showBottomOverlayProgress(true, false); if (status) { finishFragment(); } }); } else if (chatMode == MODE_PINNED) { finishFragment(); chatActivityDelegate.onUnpin(true, bottomOverlayChatText.getTag() == null); } else if (currentUser != null && currentUser.id == UserObject.VERIFY) { toggleMute(true); } 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(SendMessagesHelper.SendMessageParams.of("/start", dialog_id, null, null, null, false, null, null, null, true, 0, 0, null, false)); } }); } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setMessage(LocaleController.getString(R.string.AreYouSureUnblockContact)); builder.setPositiveButton(LocaleController.getString(R.string.OK), (dialogInterface, i) -> getMessagesController().unblockPeer(currentUser.id)); builder.setTitle(LocaleController.getString(R.string.AppName)); builder.setNegativeButton(LocaleController.getString(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(SendMessagesHelper.SendMessageParams.of("/start", dialog_id, null, null, null, false, null, null, null, true, 0, 0, null, false)); } 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); bottomChannelButtonsLayout.getContainer().addView(bottomOverlayProgress, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); contentView.addView(messageEnterTransitionContainer = new MessageEnterTransitionContainer(contentView, currentAccount)); 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); createEmptyView(false); chatListView.setEmptyView(emptyViewContainer); } checkBotKeyboard(); updateBottomOverlay(); updateSecretStatus(); updateTopPanel(false); updatePinnedMessageView(false); updateInfoTopView(false); chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager) { @Override public void setScrollDirection(int scrollDirection) { if (reversed) { if (scrollDirection == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN) { scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else if (scrollDirection == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP) { scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN; } } super.setScrollDirection(scrollDirection); } }; chatScrollHelper.setScrollListener(this::invalidateMessagesVisiblePart); chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); flagSecure = new FlagSecureReason(getParentActivity().getWindow(), () -> currentEncryptedChat != null || getMessagesController().isChatNoForwards(currentChat) ); 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(); } createUndoView(); undoView.showWithAction(0, UndoView.ACTION_TEXT_COPIED, null); } }); View overlay = textSelectionHelper.getOverlayView(context); if (overlay != null) { if (overlay.getParent() instanceof ViewGroup) { ((ViewGroup) overlay.getParent()).removeView(overlay); } contentView.addView(overlay); } textSelectionHelper.setParentView(chatListView); hashtagHistoryView = new HashtagHistoryView(context, resourceProvider, currentAccount) { @Override protected void onClick(String hashtag) { openHashtagSearch(hashtag); } @Override protected void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { AndroidUtilities.hideKeyboard(contentView); } } }; hashtagHistoryView.setVisibility(View.GONE); hashtagHistoryView.setAlpha(0f); contentView.addView(hashtagHistoryView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); contentView.addView(fireworksOverlay = new FireworksOverlay(context), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); checkInstantSearch(); if (replyingMessageObject != null) { chatActivityEnterView.setReplyingMessageObject(replyingMessageObject, replyingQuote); } ViewGroup decorView = (ViewGroup) getParentActivity().getWindow().getDecorView(); 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.getPaddingTop()); 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() != null && 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() != null && 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); if (isTopic) { reactionsMentionCount = forumTopic.unread_reactions_count; updateReactionsMentionButton(false); } else { TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id); if (dialog != null) { reactionsMentionCount = dialog.unread_reactions_count; updateReactionsMentionButton(false); } } if (getDialogId() == getUserConfig().getClientUserId() && chatMode != MODE_SAVED) { savedMessagesHint = new HintView2(context, HintView2.DIRECTION_TOP); savedMessagesHint.setMultilineText(true); savedMessagesHint.setTextAlign(Layout.Alignment.ALIGN_CENTER); savedMessagesHint.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.SavedMessagesHint))); savedMessagesHint.setMaxWidthPx(HintView2.cutInFancyHalf(savedMessagesHint.getText(), savedMessagesHint.getTextPaint())); if (AndroidUtilities.isTablet()) { savedMessagesHint.setJoint(0, 77); } else { savedMessagesHint.setJoint(0.5f, 0); } savedMessagesHint.setCloseButton(true); savedMessagesHint.setOnHiddenListener(() -> { if (searchContainer == null || searchContainer.getVisibility() != View.VISIBLE) { if (savedMessagesSearchHint != null) { savedMessagesSearchHint.show(); } } }); savedMessagesHint.setDuration(-1); savedMessagesHint.setPadding(dp(8), 0, dp(8), 0); contentView.addView(savedMessagesHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, -8, 0, 0)); savedMessagesSearchHint = new HintView2(context, HintView2.DIRECTION_TOP) .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_CENTER) .setDuration(-1) .setHideByTouch(true) .useScale(true) .setCloseButton(true) .setJointPx(1, -dp(56)) .setRounding(8); savedMessagesSearchHint.setText(LocaleController.getString(R.string.SavedTagSearchTooltipHint)); contentView.addView(savedMessagesSearchHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, -8, 16, 0)); if (getUserConfig().isPremium()) { savedMessagesTagHint = new HintView2(context, HintView2.DIRECTION_BOTTOM) .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_CENTER) .setDuration(-1) .setHideByTouch(true) .useScale(true) .setCloseButton(true) .setRounding(8); savedMessagesTagHint.setText(LocaleController.getString(R.string.SavedTagLongpressHint)); contentView.addView(savedMessagesTagHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); } } if (getDialogId() == getUserConfig().getClientUserId()) { actionBarSearchTags = new SearchTagsList(context, ChatActivity.this, contentView, currentAccount, getSavedDialogId(), themeDelegate, true) { @Override protected boolean setFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { searchingReaction = reaction; searchingFiltered = reaction != null; if (reaction == null) { getMediaDataController().clearFoundMessageObjects(); setFilterMessages(false); updateSearchButtons(0, 0, -1); } updateSearchUpDownButtonVisibility(true); updatePagedownButtonVisibility(true); searchingQuery = searchItem.getSearchField().getText().toString(); getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, !TextUtils.isEmpty(searchingQuery) || searchingReaction != null, searchingReaction); AndroidUtilities.hideKeyboard(searchItem.getSearchField()); return true; } @Override public void updateTags(boolean notify) { super.updateTags(notify); show(searchItem != null && searchItem.isSearchFieldVisible() && hasFilters() && searchingHashtag == null); } @Override protected void onShownUpdate(boolean finish) { setBackgroundColor(actionBar.getBackgroundColor()); if (tagSelector != null) { tagSelector.setTranslationY(contentPanTranslation + getCurrentHeight()); } if (finish) { invalidateChatListViewTopPadding = true; updateChatListViewTopPadding(); } } }; actionBarSearchTags.setVisibility(View.GONE); actionBarSearchTags.attach(); contentView.addView(actionBarSearchTags, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.FILL_HORIZONTAL | Gravity.TOP)); } if (chatMode == MODE_SEARCH) { messagesSearchListContainer.setVisibility(View.VISIBLE); messagesSearchListContainer.setAlpha(1.0f); messagesSearchListContainer.setTag(1); searchExpandList.setText(LocaleController.getString(R.string.SearchAsChat), false); updateSearchListEmptyView(); } final boolean useTabsView = !isSubscriberSuggestions && ChatObject.isMonoForum(currentChat) || ChatObject.isForum(currentChat) && ChatObject.areTabsEnabled(currentChat) || UserObject.isBotForum(currentUser); if (useTabsView) { createTopicsTabs(); } if (context instanceof LaunchActivity) { windowInsetsStateHolder.setupAnimatedInsetsProvider(((LaunchActivity) context).getRootAnimatedInsetsListener(), fragmentView); } onBottomItemsVisibilityChanged(); ViewCompat.setOnApplyWindowInsetsListener(fragmentView, this::onApplyWindowInsets); Timer.finish(t); return fragmentView; } private boolean lastImeVisible; @NonNull private WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) { windowInsetsStateHolder.setInsets(insets); checkUi_chatListViewPaddings(); final boolean keyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); if (lastImeVisible != keyboardVisible) { lastImeVisible = keyboardVisible; contentView.notifyHeightChanged(); } if (searchViewPager != null) { ViewCompat.dispatchApplyWindowInsets(searchViewPager, insets); } return WindowInsetsCompat.CONSUMED; } private boolean lastInAppInputVisible; private void checkInsets() { chatInputViewsContainer.checkInsets(); updatePagedownButtonsPosition(); updateBotforumTabsBottomMargin(); checkUi_botMenuPosition(); checkUi_BlurHeight(); checkUi_emptyContainerPosition(); checkUi_chatListViewPaddings(); invalidateClipRectForBackgroundAndChatList(); final boolean inAppInputVisible = windowInsetsStateHolder.inAppViewIsVisible(); if (lastInAppInputVisible != inAppInputVisible) { lastInAppInputVisible = inAppInputVisible; checkSystemBarColors(); } } private void checkBotMessageHint() { if (botMessageHint != null) { return; } ChatMessageCell cell = null; for (int i = chatListView.getChildCount() - 1; i >= 0; --i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell messageCell = ((ChatMessageCell) child); MessageObject msg = messageCell.getPrimaryMessageObject(); if (msg != null && msg.messageOwner != null && msg.messageOwner.via_business_bot_id != 0) { cell = messageCell; } } } showBotMessageHint(cell, false); } private boolean bizbothint; private void showBotMessageHint(ChatMessageCell cell, boolean byClick) { if ( getContext() == null || cell == null || cell.timeLayout == null || cell.getPrimaryMessageObject() == null || cell.getPrimaryMessageObject().messageOwner == null || cell.getPrimaryMessageObject().messageOwner.via_business_bot_id == 0) { return; } if (!byClick) { if (getMessagesController().getMainSettings().getBoolean("bizbothint", false)) { return; } getMessagesController().getMainSettings().edit().putBoolean("bizbothint", true).apply(); if (bizbothint) return; bizbothint = true; } if (botMessageHint != null) { if (byClick) { HintView2 hint = botMessageHint; hint.setOnHiddenListener(() -> contentView.removeView(hint)); hint.hide(); botMessageHint = null; } else { return; } } botMessageHint = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM) .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_NORMAL) .setDuration(-1) .setHideByTouch(true) .useScale(true) .setCloseButton(true) .setRounding(8); botMessageHint.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.MessageBizBot))); botMessageHint.setMaxWidthPx(HintView2.cutInFancyHalf(botMessageHint.getText(), botMessageHint.getTextPaint())); contentView.addView(botMessageHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); contentView.post(() -> { int[] loc = new int[2]; cell.getLocationInWindow(loc); botMessageHint.setTranslationY(loc[1] - botMessageHint.getTop() - dp(120) + cell.getTimeY()); botMessageHint.setJointPx(0, -dp(16) + loc[0] + cell.timeX + cell.timeWidth - cell.signWidth / 2f); botMessageHint.show(); }); } private void hideHints() { if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); } if (videoConversionTimeHint != null && videoConversionTimeHint.shown()) { videoConversionTimeHint.hide(); } if (chatActivityEnterView != null) { chatActivityEnterView.hideHints(); } } public void setTagFilter(ReactionsLayoutInBubble.VisibleReaction reaction) { if (actionBarSearchTags != null) { actionBarSearchTags.setChosen(reaction, true); } searchItemVisible = searching = !TextUtils.isEmpty(searchingQuery) || searchingReaction != null; updateBottomOverlay(); updateSearchUpDownButtonVisibility(true); } public void setSearchQuery(String text) { if (searchItem != null) { searchItem.setSearchFieldText(searchingQuery = text, false); } } public void hitSearch() { searchWas = true; updateSearchButtons(0, 0, -1); getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); searchItemVisible = searching = !TextUtils.isEmpty(searchingQuery) || searchingReaction != null; updateBottomOverlay(); updateSearchUpDownButtonVisibility(true); } public void clearSearch() { if (searchItemListener != null) { searchItemListener.onSearchCollapse(); } searching = false; searchItemVisible = false; updateBottomOverlay(); updateSearchUpDownButtonVisibility(true); } protected void onSearchLoadingUpdate(boolean loading) { } private void setFilterMessages(boolean filter) { setFilterMessages(filter, false, true); } private void setFilterMessages(boolean filter, boolean ignoreMessageNotFound, boolean animated) { if (chatAdapter == null || chatAdapter.isFiltered == filter) return; chatAdapter.isFiltered = filter; createEmptyView(true); if (filter) { updateFilteredMessages(false); } if (!saveScrollOnFilterToggle(animated, ignoreMessageNotFound)) { chatAdapter.isFiltered = !filter; } if (searchOtherButton != null) { searchOtherButton.setText(LocaleController.getString(chatAdapter.isFiltered ? R.string.SavedTagShowOtherMessages : R.string.SavedTagHideOtherMessages)); } updateSearchUpDownButtonVisibility(true); showProgressView(!chatAdapter.isFiltered ? loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty()); if (chatListView != null) { createEmptyView(false); if (!(!chatAdapter.isFiltered ? !loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : !getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty())) { emptyViewContainer.setVisibility(View.GONE); chatListView.setEmptyView(null); } else { chatListView.setEmptyView(emptyViewContainer); chatListView.checkIfEmpty(); } } } private boolean saveScrollOnFilterToggle(boolean animated, boolean ignoreMessageNotFound) { final ArrayList newMessagesArray = chatAdapter.getMessages(); int index = -1; int centerId = 0; int centerStableId = 0; int offset = 0; int cy = chatListView.getMeasuredHeight() / 2; ArrayList views = new ArrayList<>(); HashMap distances = new HashMap<>(); for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); // int ccy = (child.getTop() + child.getBottom()) / 2; // views.put(Math.abs(ccy - cy), child); // base on center int dist = (int) (chatListView.getMeasuredHeight() * .97f) - dp(42) - child.getBottom(); if (dist < 0) continue; distances.put(child, dist); views.add(child); } Collections.sort(views, Comparator.comparingInt(distances::get)); HashSet ids = new HashSet(); HashSet stableIds = new HashSet(); for (int i = 0; i < newMessagesArray.size(); ++i) { MessageObject m = newMessagesArray.get(i); if (!m.isDateObject) { ids.add(m.getId()); } stableIds.add(m.stableId); } for (int i = 0; i < views.size(); ++i) { View child = views.get(i); MessageObject msg; if (child instanceof ChatMessageCell) { msg = ((ChatMessageCell) child).getMessageObject(); } else if (child instanceof ChatActionCell) { msg = ((ChatActionCell) child).getMessageObject(); } else { continue; } if (msg == null) continue; int id = msg.getId(); if (ids.contains(id)) { centerId = id; offset = getScrollingOffsetForView(child); break; } else if (stableIds.contains(msg.stableId)) { centerStableId = msg.stableId; offset = getScrollingOffsetForView(child); break; } } if (centerId == 0 && centerStableId == 0) { if (!chatAdapter.isFiltered && !ignoreMessageNotFound) { for (int j = 0; j < views.size(); ++j) { View centerView = views.get(j); MessageObject msg; if (centerView instanceof ChatMessageCell) { msg = ((ChatMessageCell) centerView).getMessageObject(); } else { continue; } if (msg == null) { continue; } int id = msg.getId(); waitingForLoad.clear(); removeSelectedMessageHighlight(); scrollToMessagePosition = -10000; startLoadFromMessageId = id; showScrollToMessageError = false; createUnreadMessageAfterIdLoading = false; postponedScrollIsCanceled = false; waitingForLoad.add(lastLoadIndex); postponedScrollToLastMessageQueryIndex = lastLoadIndex; fakePostponedScroll = true; postponedScrollMinMessageId = minMessageId[0]; postponedScrollMessageId = id; getMessagesController().loadMessages(dialog_id, 0, false, 50, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); return false; } } for (int j = 0; j < views.size(); ++j) { View centerView = views.get(j); MessageObject msg; if (centerView instanceof ChatMessageCell) { msg = ((ChatMessageCell) centerView).getMessageObject(); } else { continue; } if (msg == null) { continue; } int id = msg.getId(); int mid = -1; int leastDist = Integer.MAX_VALUE; for (int i = 0; i < newMessagesArray.size(); ++i) { MessageObject msg2 = newMessagesArray.get(i); if (msg2.getId() == 0) continue; final int dist = Math.abs(msg2.getId() - id); if (dist < leastDist) { leastDist = dist; mid = msg2.getId(); index = i; offset = 0; } } if (mid != -1) { break; } } } if (centerStableId != 0) { for (int i = 0; i < newMessagesArray.size(); ++i) { if (newMessagesArray.get(i).stableId == centerStableId) { index = i; break; } } } else if (centerId != 0) { for (int i = 0; i < newMessagesArray.size(); ++i) { if (newMessagesArray.get(i).getId() == centerId) { index = i; break; } } } chatAdapter.updateRowsSafe(); if (index >= 0) { int newPosition = chatAdapter.messagesStartRow + index; chatLayoutManager.scrollToPositionWithOffset(newPosition, offset); } chatAdapter.notifyDataSetChanged(animated); return true; } private LongSparseArray> filteredMessagesByDays; private LongSparseArray filteredMessagesDict; private void putFilteredDate(int index, MessageObject baseMsg) { TLRPC.Message dateMsg = new TLRPC.TL_message(); dateMsg.message = LocaleController.formatDateChat(baseMsg.messageOwner.date); dateMsg.id = 0; Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(((long) baseMsg.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = 10; dateObj.contentType = 1; dateObj.isDateObject = true; dateObj.stableId = getStableIdForDateObject(baseMsg.dateKeyInt); chatAdapter.filteredMessages.add(index, dateObj); } private void createHint2MessageObject() { if (hint2MessageObject != null) return; TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SAVED) { dateMsg.message = LocaleController.getString(R.string.SavedMessagesProfileHint); } else { dateMsg.message = LocaleController.getString(R.string.BusinessRepliesHint); } dateMsg.id = 0; hint2MessageObject = new MessageObject(currentAccount, dateMsg, false, false); hint2MessageObject.type = 10; hint2MessageObject.contentType = 1; } private void updateFilteredMessages(boolean notify) { ArrayList results = new ArrayList<>(MediaDataController.getInstance(currentAccount).getFoundMessageObjects()); if (filteredMessagesDict == null) { filteredMessagesDict = new LongSparseArray<>(); } if (filteredMessagesByDays == null) { filteredMessagesByDays = new LongSparseArray<>(); } else { filteredMessagesByDays.clear(); } LongSparseArray newGroups = null; LongSparseArray changedGroups = null; chatAdapter.filteredMessages.clear(); filteredMessagesDict.clear(); for (int i = 0; i < results.size(); ++i) { MessageObject msg = results.get(i); MessageObject from = null; if (from == null) { for (int j = 0; j < messages.size(); ++j) { MessageObject m = messages.get(j); if (m.getDialogId() == msg.getDialogId() && m.getId() == msg.getId()) { from = m; break; } } } if (msg.stableId == 0) { if (from == null) { msg.checkMediaExistance(); } else { msg.mediaExists = from.mediaExists; msg.attachPathExists = from.attachPathExists; } } if (from != null) { msg.isSaved = from.isSaved; if (chatAdapter.isFiltered && msg.stableId != 0) { from.copyStableParams(msg); } else { msg.copyStableParams(from); } } else if (msg.stableId == 0) { msg.stableId = lastStableId++; } msg.isOutOwnerCached = null; if (msg.messageOwner != null) { msg.messageOwner.out = true; } msg.isOutOwner(); if (msg.hasValidGroupId()) { MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(msg.getGroupIdForUse()); if (groupedMessages == null) { groupedMessages = new MessageObject.GroupedMessages(); groupedMessages.reversed = reversed; groupedMessages.groupId = msg.getGroupId(); groupedMessagesMap.put(groupedMessages.groupId, groupedMessages); } else if (newGroups == null || newGroups.indexOfKey(msg.getGroupId()) < 0) { if (changedGroups == null) { changedGroups = new LongSparseArray<>(); } changedGroups.put(msg.getGroupId(), groupedMessages); } if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); if (groupedMessages.getPosition(msg) == null) { boolean found = false; for (int j = 0; j < groupedMessages.messages.size(); ++j) { if (groupedMessages.messages.get(j).getId() == msg.getId()) { found = true; break; } } if (!found) { groupedMessages.messages.add(msg); } } } else if (msg.getGroupIdForUse() != 0) { msg.messageOwner.grouped_id = 0; msg.localSentGroupId = 0; } chatAdapter.filteredMessages.add(msg); filteredMessagesDict.put(msg.getId(), msg); } if (newGroups != null) { for (int i = 0; i < newGroups.size(); ++i) { MessageObject.GroupedMessages group = newGroups.valueAt(i); Collections.sort(group.messages, (a, b) -> a.getId() - b.getId()); group.calculate(); } } ArrayList messagesResults = new ArrayList<>(); if (searchingReaction != null && TextUtils.isEmpty(searchingQuery)) { for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); if (msg != null && msg.messageOwner != null && msg.messageOwner.reactions != null && msg.messageOwner.reactions.reactions_as_tags) { for (int j = 0; j < msg.messageOwner.reactions.results.size(); ++j) { if (searchingReaction.isSame(msg.messageOwner.reactions.results.get(j).reaction)) { messagesResults.add(msg); break; } } } } } for (int i = 0; i < messagesResults.size(); ++i) { MessageObject msg = messagesResults.get(i); if (filteredMessagesDict.containsKey(msg.getId())) { continue; } msg.isOutOwnerCached = null; if (msg.messageOwner != null) { msg.messageOwner.out = true; } chatAdapter.filteredMessages.add(msg); filteredMessagesDict.put(msg.getId(), msg); } for (int i = 0; i < chatAdapter.filteredMessages.size(); ++i) { MessageObject obj = chatAdapter.filteredMessages.get(i); if (!obj.hasValidGroupId()) { continue; } MessageObject.GroupedMessages group = groupedMessagesMap.get(obj.getGroupId()); if (group != null) { for (int j = group.messages.size() - 1; j >= 0; --j) { MessageObject groupmsg = group.messages.get(j); if (groupmsg == obj || filteredMessagesDict.containsKey(groupmsg.getId())) continue; chatAdapter.filteredMessages.add(i, groupmsg); filteredMessagesDict.put(groupmsg.getId(), groupmsg); i++; } } else { } } Collections.sort(chatAdapter.filteredMessages, (a, b) -> b.getId() - a.getId()); MessageObject lastFilteredMessage = null; for (int i = 0; i < chatAdapter.filteredMessages.size(); ++i) { MessageObject msg = chatAdapter.filteredMessages.get(i); if (reversed && msg != null && i == 0) { putFilteredDate(i++, msg); } if (!reversed && lastFilteredMessage != null && msg.dateKeyInt != lastFilteredMessage.dateKeyInt) { putFilteredDate(i++, lastFilteredMessage); } ArrayList dayArray = filteredMessagesByDays.get(msg.dateKeyInt); if (dayArray == null) { filteredMessagesByDays.put(msg.dateKeyInt, dayArray = new ArrayList<>()); } dayArray.add(msg); if (reversed && lastFilteredMessage != null && msg.dateKeyInt != lastFilteredMessage.dateKeyInt) { putFilteredDate(i++, msg); } lastFilteredMessage = msg; if (!reversed && lastFilteredMessage != null && i >= chatAdapter.filteredMessages.size() - 1) { putFilteredDate(chatAdapter.filteredMessages.size(), lastFilteredMessage); i++; } } chatAdapter.filteredEndReached = MediaDataController.getInstance(currentAccount).searchEndReached(); if (notify) { chatAdapter.updateRowsSafe(); chatAdapter.notifyDataSetChanged(true); showProgressView(!chatAdapter.isFiltered ? loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty()); if (chatListView != null) { createEmptyView(false); if (!(!chatAdapter.isFiltered ? !loading && messages.isEmpty() && chatAdapter.botInfoRow < 0 : !getMediaDataController().isSearchLoading() && chatAdapter.filteredMessages.isEmpty())) { emptyViewContainer.setVisibility(View.GONE); chatListView.setEmptyView(null); } else { chatListView.setEmptyView(emptyViewContainer); chatListView.checkIfEmpty(); } } } } private void createBottomMessagesActionButtons() { } private void checkInstantSearch() { final long searchFromUserId = getArguments().getInt("search_from_user_id", 0); if (searchFromUserId != 0) { TLRPC.User user = getMessagesController().getUser(searchFromUserId); if (user != null) { openSearchWithText(""); if (searchUserButton != null) { searchUserButton.callOnClick(); } searchUserMessages(user, null); } } else { final long searchFromChatId = getArguments().getInt("search_from_chat_id", 0); if (searchFromChatId != 0) { TLRPC.Chat chat = getMessagesController().getChat(searchFromChatId); if (chat != null) { openSearchWithText(""); if (searchUserButton != null) { searchUserButton.callOnClick(); } searchUserMessages(null, chat); } } } } private void createTopPanel() { if (contentView == null || topChatPanelView != null || getContext() == null) { return; } topChatPanelView = new BlurredFrameLayout(getContext(), contentView) { private boolean ignoreLayout; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int leftMargin = 0; if (isSideMenued()) { width -= dp(SIDE_MENU_WIDTH); leftMargin += dp(32); } if (addToContactsButton != null && addToContactsButton.getVisibility() == VISIBLE && reportSpamButton != null && reportSpamButton.getVisibility() == VISIBLE) { width = (width - 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(dp(4), 0, dp(4), 0); layoutParams.leftMargin = leftMargin + width; layoutParams.width -= dp(15); } else { reportSpamButton.setPadding(dp(48), 0, dp(48), 0); layoutParams.leftMargin = leftMargin; } } if (addToContactsButton != null && addToContactsButton.getVisibility() == VISIBLE) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) addToContactsButton.getLayoutParams(); layoutParams.width = width; if (reportSpamButton != null && reportSpamButton.getVisibility() == VISIBLE) { addToContactsButton.setPadding(dp(11), 0, dp(4), 0); } else { addToContactsButton.setPadding(dp(48), 0, dp(48), 0); } layoutParams.leftMargin = leftMargin; } ignoreLayout = false; super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public void requestLayout() { if (ignoreLayout) { return; } super.requestLayout(); } }; topChatPanelView.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); topChatPanelView.backgroundPaddingBottom = dp(2); topChatPanelView.setTag(1); topChatPanelViewOffset = -AndroidUtilities.dp(50); invalidateChatListViewTopPadding(); topChatPanelView.setClickable(true); topChatPanelView.setVisibility(View.GONE); topChatPanelView.setBackgroundResource(R.drawable.blockpanel); topChatPanelView.getBackground().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); int index = Math.min(8, contentView.getChildCount()); if (pinnedMessageView != null && pinnedMessageView.getParent() == contentView) { index = contentView.indexOfChild(pinnedMessageView) + 1; } contentView.addView(topChatPanelView, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); reportSpamButton = new TextView(getContext()); reportSpamButton.setTextColor(getThemedColor(Theme.key_text_RedBold)); reportSpamButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_text_RedBold) & 0x19ffffff, 3)); reportSpamButton.setTag(Theme.key_text_RedBold); reportSpamButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); reportSpamButton.setTypeface(AndroidUtilities.bold()); reportSpamButton.setSingleLine(true); reportSpamButton.setMaxLines(1); reportSpamButton.setGravity(Gravity.CENTER); topChatPanelView.addView(reportSpamButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, 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)); emojiStatusSpamHint = new LinkSpanDrawable.LinksTextView(getContext(), themeDelegate); emojiStatusSpamHint.setTextColor(getThemedColor(Theme.key_chat_topPanelMessage)); emojiStatusSpamHint.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13.3f); emojiStatusSpamHint.setGravity(Gravity.CENTER); emojiStatusSpamHint.setVisibility(View.GONE); emojiStatusSpamHint.setLinkTextColor(getThemedColor(Theme.key_windowBackgroundWhiteLinkText)); topChatPanelView.addView(emojiStatusSpamHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 25, 0, 25, 1)); topViewSeparator1 = new View(getContext()); topViewSeparator1.setVisibility(View.GONE); topViewSeparator1.setBackgroundColor(getThemedColor(Theme.key_divider)); topViewSeparator1.setAlpha(.5f); topChatPanelView.addView(topViewSeparator1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1f / AndroidUtilities.density, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 2)); topViewSeparator2 = new View(getContext()); topViewSeparator2.setVisibility(View.GONE); topViewSeparator2.setAlpha(.5f); topViewSeparator2.setBackgroundColor(getThemedColor(Theme.key_divider)); topChatPanelView.addView(topViewSeparator2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1f / AndroidUtilities.density, Gravity.LEFT | Gravity.TOP, 10, 48, 10, 1)); topViewSeparator3 = new View(getContext()); topViewSeparator3.setVisibility(View.GONE); topViewSeparator3.setAlpha(.5f); topViewSeparator3.setBackgroundColor(getThemedColor(Theme.key_divider)); topChatPanelView.addView(topViewSeparator3, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1f / AndroidUtilities.density, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 38)); addToContactsButton = new TextView(getContext()); addToContactsButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); addToContactsButton.setVisibility(View.GONE); addToContactsButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); addToContactsButton.setTypeface(AndroidUtilities.bold()); addToContactsButton.setSingleLine(true); addToContactsButton.setMaxLines(1); addToContactsButton.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); addToContactsButton.setGravity(Gravity.CENTER); addToContactsButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_chat_addContact) & 0x19ffffff, 3)); topChatPanelView.addView(addToContactsButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 1)); addToContactsButton.setOnClickListener(v -> { if (addToContactsButtonArchive) { getMessagesController().addDialogToFolder(dialog_id, 0, 0, 0); createUndoView(); 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, getTopicId()); } 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(getContext(), currentAccount, users, chatInfo.id, ChatActivity.this, themeDelegate); bottomSheet.setDelegate((users1, fwdCount) -> { getMessagesController().addUsersToChat(currentChat, ChatActivity.this, users1, fwdCount, null, null, 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(() -> { if (undoView != null || getContext() == null) { return; } createUndoView(); undoView.showWithAction(dialog_id, UndoView.ACTION_CONTACT_ADDED, currentUser); }); presentFragment(activity); } }); restartTopicButton = new TextView(getContext()); restartTopicButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); restartTopicButton.setVisibility(View.GONE); restartTopicButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); restartTopicButton.setTypeface(AndroidUtilities.bold()); restartTopicButton.setSingleLine(true); restartTopicButton.setMaxLines(1); restartTopicButton.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); restartTopicButton.setGravity(Gravity.CENTER); restartTopicButton.setText(LocaleController.getString(R.string.RestartTopic).toUpperCase()); restartTopicButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_chat_addContact) & 0x19ffffff, 3)); topChatPanelView.addView(restartTopicButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 1)); restartTopicButton.setOnClickListener(v -> { if (forumTopic != null) { getMessagesController().getTopicsController().toggleCloseTopic(currentChat.id, forumTopic.id, forumTopic.closed = false); } updateTopicButtons(); updateBottomOverlay(); updateTopPanel(true); }); closeReportSpam = new ImageView(getContext()); closeReportSpam.setImageResource(R.drawable.miniplayer_close); closeReportSpam.setContentDescription(LocaleController.getString(R.string.Close)); closeReportSpam.setBackground(Theme.AdaptiveRipple.circle(getThemedColor(Theme.key_chat_topPanelClose))); closeReportSpam.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); closeReportSpam.setScaleType(ImageView.ScaleType.CENTER); topChatPanelView.addView(closeReportSpam, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 0, 6, 2, 0)); closeReportSpam.setOnClickListener(v -> { long did = dialog_id; if (currentEncryptedChat != null) { did = currentUser.id; } shownBotVerification = false; getMessagesController().hidePeerSettingsBar(did, currentUser, currentChat); updateTopPanel(true); updateInfoTopView(true); }); } private void createTopPanel2() { if (contentView == null || topChatPanelView2 != null || getContext() == null) { return; } topChatPanelView2 = new BlurredFrameLayout(getContext(), contentView); topChatPanelView2.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); topChatPanelView2.backgroundPaddingBottom = AndroidUtilities.dp(2); topChatPanelView2.setPadding(0, 0, 0, dp(2)); topChatPanelView2.setTag(1); topChatPanelView2Offset = -AndroidUtilities.dp(50); invalidateChatListViewTopPadding(); topChatPanelView2.setClickable(true); topChatPanelView2.setVisibility(View.GONE); topChatPanelView2.setBackgroundResource(R.drawable.blockpanel); topChatPanelView2.getBackground().setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); int index = 8; if (pinnedMessageView != null && pinnedMessageView.getParent() == contentView) { index = contentView.indexOfChild(pinnedMessageView) + 1; } contentView.addView(topChatPanelView2, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); } private void createTranslateButton() { if (translateButton != null || getContext() == null) { return; } createTopPanel(); if (topChatPanelView == null) { return; } translateButton = new TranslateButton(getContext(), this, themeDelegate) { @Override protected void onButtonClick() { if (getUserConfig().isPremium() || currentChat != null && currentChat.autotranslation) { getMessagesController().getTranslateController().toggleTranslatingDialog(getDialogId()); } else { MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dialog_show_translate_count" + getDialogId(), 14).commit(); showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_TRANSLATIONS, false)); } updateTopPanel(true); } @Override protected void onCloseClick() { MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dialog_show_translate_count" + getDialogId(), 140).commit(); updateTopPanel(true); } }; topChatPanelView.addView(translateButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 2)); } private boolean isAllChats() { return topicsTabs != null && threadMessageId == 0; } private boolean isSideMenued() { return topicsTabs != null || !isSubscriberSuggestions && ChatObject.isMonoForum(currentChat) || ChatObject.isForum(currentChat) && ChatObject.areTabsEnabled(currentChat); } private boolean isSideMenuEnabled() { return topicsTabs != null && topicsTabs.sidemenuEnabled; } private float getSideMenuAlpha() { return topicsTabs != null ? topicsTabs.sidemenuT : 0f; } private int getSideMenuWidth() { return (int) (dp(SIDE_MENU_WIDTH) * getSideMenuAlpha()); } public static final int SIDE_MENU_WIDTH = 64 + 7; private boolean isSideMenuAnimating() { return topicsTabs != null && topicsTabs.sidemenuAnimating; } private void createTopicsTabs() { if (topicsTabs != null || getContext() == null) { return; } if (pinnedMessageView == null) { createPinnedMessageView(); } topicsTabs = new TopicsTabsView(getContext(), this, contentView, currentAccount, getDialogId(), getResourceProvider()) { @Override public void updateSidemenuPosition() { super.updateSidemenuPosition(); invalidateChatListViewTopPadding(); AndroidUtilities.forEachViews(chatListView, view -> { if (view instanceof ChatMessageCell) { final ChatMessageCell cell = (ChatMessageCell) view; cell.isAllChats = isAllChats(); cell.isSideMenued = isSideMenued(); final boolean newSideMenuEnabled = isSideMenuEnabled(); if (cell.isSideMenuEnabled != newSideMenuEnabled) { cell.isSideMenuEnabled = newSideMenuEnabled; final int position = chatListView.getChildAdapterPosition(view); cell.relayout(); if (position >= 0) { chatAdapter.notifyItemChanged(position); } } cell.sideMenuAlpha = getSideMenuAlpha(); final int newSideMenuWidth = getSideMenuWidth(); if (cell.sideMenuWidth != newSideMenuWidth) { cell.sideMenuWidth = newSideMenuWidth; cell.updateTranslation(); cell.invalidate(); } } else if (view instanceof ChatActionCell) { final ChatActionCell cell = (ChatActionCell) view; cell.isAllChats = isAllChats(); cell.isSideMenued = isSideMenued(); cell.isSideMenuEnabled = isSideMenuEnabled(); cell.sideMenuAlpha = getSideMenuAlpha(); final int newSideMenuWidth = getSideMenuWidth(); if (cell.sideMenuWidth != newSideMenuWidth) { cell.sideMenuWidth = newSideMenuWidth; cell.invalidate(); } } else if (view instanceof ChatUnreadCell) { ((ChatUnreadCell) view).getTextView().setTranslationX(getSideMenuWidth() / 2f); } }); if (floatingDateView != null) { floatingDateView.setTranslationX(getSideMenuWidth() / 2f); } if (floatingTopicSeparator != null) { floatingTopicSeparator.setTranslationX(getSideMenuWidth() / 2f); } if (emptyViewContainer != null) { emptyViewContainer.setTranslationX(getSideMenuWidth() / 2.f); } if (pendingRequestsDelegate != null) { pendingRequestsDelegate.setLeftMargin(getSideMenuWidth()); } if (bizBotButton != null) { bizBotButton.setLeftMargin(getSideMenuWidth()); } if (restartTopicButton != null) { restartTopicButton.setTranslationX(getSideMenuWidth() / 2.0f); } if (emojiStatusSpamHint != null) { emojiStatusSpamHint.setTranslationX(getSideMenuWidth() / 2.0f); } } }; topicsTabs.setSideMenuBackgroundDrawable(glassBackgroundDrawableFactory.create(topicsTabs, blurredBackgroundColorProvider)); int index = 8; if (topChatPanelView != null && topChatPanelView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(topChatPanelView) + 1); } if (topChatPanelView2 != null && topChatPanelView2.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(topChatPanelView2) + 1); } View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null && pendingRequestsView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(pendingRequestsView) + 1); } if (pinnedMessageView != null && pinnedMessageView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(pinnedMessageView) + 1); } if (fragmentContextView != null && fragmentContextView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(fragmentContextView) + 1); } if (fragmentLocationContextView != null && fragmentLocationContextView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(fragmentLocationContextView) + 1); } topicsTabs.setCurrentTopic(getTopicId()); topicsTabs.setOnNewTopicSelected(() -> { presentFragment(TopicCreateFragment.create(-dialog_id, 0).setOpenInChatActivity(this)); }); topicsTabs.setOnTopicSelected((topicId, fromMessage) -> { if (topicId == getTopicId()) return; TLRPC.TL_forumTopic topic = topicsTabs.getTopic(topicId); TLRPC.Message message = topic == null ? null : topic.topicStartMessage; if (message == null && topic != null) { TLRPC.TL_forumTopic topicLocal = getMessagesController().getTopicsController().findTopic(-getDialogId(), topic.id); if (topicLocal != null) { topic = topicLocal; message = topic.topicStartMessage; } } if (message == null && topicId != 0) { return; } topicChangedFromMessage = fromMessage; if (fromMessage || true) { if (topicId == 0) { savePositionForTopicChange(getTopicId()); } else if (getTopicId() == 0) { savePositionForTopicChange(topicId); } else { clearOnLoadAndScrollMessageId = -1; } } else { clearOnLoadAndScrollMessageId = -1; } getConnectionsManager().cancelRequestsForGuid(classGuid); getMessagesStorage().cancelTasksForGuid(classGuid); classGuid = ConnectionsManager.generateClassGuid(); saveDraft(); messagePreviewParams = null; startLoadFromMessageId = 0;//clearOnLoadAndScrollMessageId >= 0 ? clearOnLoadAndScrollMessageId : 0; firstMessagesLoaded = false; clearOnLoad = true; waitingForLoad.clear(); justCreatedTopic = false; if (message != null && topicId != 0) { ArrayList messageObjects = new ArrayList<>(); messageObjects.add(new MessageObject(getCurrentAccount(), message, false, false)); setThreadMessages(messageObjects, currentChat, topic.id, topic.read_inbox_max_id, topic.read_outbox_max_id, topic); } else { this.forumTopic = null; threadMessageObjects = null; replyingMessageObject = threadMessageObject = null; threadMaxInboxReadId = 0; threadMaxOutboxReadId = 0; replyMaxReadId = 0; threadMessageId = 0; replyOriginalMessageId = 0; replyOriginalChat = null; isTopic = false; isComments = false; } firstLoadMessages(); updateTitle(true); avatarContainer.updateSubtitle(true); if (topic != null) { updateTopicTitleIcon(); } else { avatarContainer.checkAndUpdateAvatar(); } topicsTabs.setCurrentTopic(getTopicId()); updateTopPanel(true); updateBottomOverlay(true); getMessagesController().setForumLastTopicId(-getDialogId(), getTopicId()); reloadPinnedMessages(); hideFloatingDateView(true); hideFieldPanel(true); applyDraftMaybe(true, true); if (chatActivityEnterView != null) { chatActivityEnterView.hidePopup(false); chatActivityEnterView.updateFieldHint(true); if (getParentActivity() != null) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } } if (topic != null) { getMessagesController().getTopicsController().getTopicRepliesCount(dialog_id, topic.id); } reactionsMentionCount = topic != null ? topic.unread_reactions_count : 0; updateReactionsMentionButton(false); updateTopicButtons(); if (searchItemListener != null && actionBar.isSearchFieldVisible()) { searchItemListener.onSearchPressed(null); } }); topicsTabs.setOnDialogSelected((dialogId, fromMessage) -> { if (dialogId == getTopicId()) return; topicChangedFromMessage = fromMessage; if (fromMessage || true) { if (dialogId == 0) { savePositionForTopicChange(getTopicId()); } else if (getTopicId() == 0) { savePositionForTopicChange(dialogId); } else { clearOnLoadAndScrollMessageId = -1; } } else { clearOnLoadAndScrollMessageId = -1; } getConnectionsManager().cancelRequestsForGuid(classGuid); getMessagesStorage().cancelTasksForGuid(classGuid); classGuid = ConnectionsManager.generateClassGuid(); saveDraft(); messagePreviewParams = null; startLoadFromMessageId = 0;//clearOnLoadAndScrollMessageId >= 0 ? clearOnLoadAndScrollMessageId : 0; firstMessagesLoaded = false; clearOnLoad = true; waitingForLoad.clear(); setSavedDialog(dialogId); TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(-getDialogId(), dialogId); if (dialogId != 0 && topic != null) { threadMaxInboxReadId = topic.read_inbox_max_id; threadMaxOutboxReadId = topic.read_outbox_max_id; replyMaxReadId = Math.max(1, topic.read_inbox_max_id); getMessagesController().getTopicsController().getTopicRepliesCount(dialog_id, DialogObject.getPeerDialogId(topic.from_id)); /* this.forumTopic = forumTopic; 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; isTopic = forumTopic != null; isComments = replyingMessageObject.messageOwner.fwd_from != null && replyingMessageObject.messageOwner.fwd_from.channel_post != 0 && !isTopic; if (isTopic) { replyingMessageObject.isTopicMainMessage = true; } updatePinnedTopicStarterMessage(); updateTopPanel(false); updateBottomOverlay(); */ } else { this.forumTopic = null; threadMessageObjects = null; replyingMessageObject = threadMessageObject = null; threadMaxInboxReadId = 0; threadMaxOutboxReadId = 0; replyMaxReadId = 0; threadMessageId = 0; replyOriginalMessageId = 0; replyOriginalChat = null; isTopic = false; isComments = false; } firstLoadMessages(); updateTitle(true); avatarContainer.updateSubtitle(true); avatarContainer.checkAndUpdateAvatar(); topicsTabs.setCurrentTopic(dialogId); updateTopPanel(true); updateBottomOverlay(true); getMessagesController().setForumLastTopicId(-getDialogId(), getTopicId()); hideFloatingTopicView(true); hideFieldPanel(true); if (chatActivityEnterView != null) { chatActivityEnterView.hidePopup(false); chatActivityEnterView.updateFieldHint(true); if (getParentActivity() != null) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } } applyDraftMaybe(true, true); reactionsMentionCount = topic != null ? topic.unread_reactions_count : 0; updateReactionsMentionButton(false); updateTopicButtons(); if (searchItemListener != null && actionBar.isSearchFieldVisible()) { searchItemListener.onSearchPressed(null); } // }); contentView.addView(topicsTabs, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); topicsTabs.updateSidemenuPosition(); if (mentionContainer != null) { mentionContainer.bringToFront(); } } private void toggleIsAllChats() { final boolean isAllChats = isAllChats(); AndroidUtilities.forEachViews(chatListView, view -> { if (view instanceof ChatMessageCell) { final ChatMessageCell cell = (ChatMessageCell) view; if ((cell.isAllChats && cell.isSideMenuEnabled) != isAllChats && isSideMenuEnabled()) { cell.isAllChats = isAllChats; cell.isSideMenuEnabled = isSideMenuEnabled(); cell.relayout(); } } else if (view instanceof ChatActionCell) { final ChatActionCell cell = (ChatActionCell) view; cell.isAllChats = isAllChats; } }); } private void createBotAdView() { if (botAdView != null || getContext() == null) { return; } createTopPanel2(); if (topChatPanelView2 == null) { return; } botAdView = new BotAdView(getContext(), themeDelegate); topChatPanelView2.addView(botAdView); } private void createBizBotButton() { if (bizBotButton != null || getContext() == null) { return; } createTopPanel(); if (topChatPanelView == null) { return; } bizBotButton = new BusinessBotButton(getContext(), this, themeDelegate); topChatPanelView.addView(bizBotButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 2)); bizBotButton.setLeftMargin(getSideMenuWidth()); } private void createUndoView() { if (undoView != null || getContext() == null) { return; } undoView = new UndoView(getContext(), 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)); } @Override public INavigationLayout.BackButtonState getBackButtonState() { return INavigationLayout.BackButtonState.BACK; } private void createActionMode() { if (selectedMessagesCountTextView != null || getContext() == null) { return; } final ActionBarMenu actionMode = actionBar.createActionMode(); selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.bold()); selectedMessagesCountTextView.setTextColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon)); selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); if (currentEncryptedChat == null) { final boolean isSavedMessages = getDialogId() == getUserConfig().getClientUserId() && (chatMode == 0 || chatMode == MODE_SAVED); actionModeViews.add(actionMode.addItemWithWidth(save_to, R.drawable.msg_download, AndroidUtilities.dp(54), LocaleController.getString(R.string.SaveToMusic))); actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.Edit))); if (isSavedMessages) { actionModeViews.add(actionMode.addItemWithWidth(tag_message, R.drawable.menu_tag_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.AccDescrTagMessage))); } actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString(R.string.AddToFavorites))); actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString(R.string.Copy))); if (!isSavedMessages && getDialogId() != UserObject.VERIFY) { actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString(R.string.Forward))); } actionModeViews.add(actionMode.addItemWithWidth(share, R.drawable.msg_shareout, AndroidUtilities.dp(54), LocaleController.getString(R.string.ShareFile))); actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString(R.string.Delete))); } else { actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString(R.string.Edit))); actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString(R.string.AddToFavorites))); actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString(R.string.Copy))); actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString(R.string.Delete))); } actionMode.setItemVisibility(edit, canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); actionMode.setItemVisibility(copy, !getMessagesController().isChatNoForwards(currentChat) && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); actionMode.setItemVisibility(star, selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size() != 0 ? View.VISIBLE : View.GONE); actionMode.setItemVisibility(delete, cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); actionMode.setItemVisibility(tag_message, getUserConfig().isPremium() ? View.VISIBLE : View.GONE); actionMode.setItemVisibility(share, View.GONE); } private void hideTagSelector() { if (tagSelector == null) return; final ReactionsContainerLayout thisTagSelector = tagSelector; tagSelector = null; thisTagSelector.dismissWindow(); if (thisTagSelector.getReactionsWindow() != null && thisTagSelector.getReactionsWindow().containerView != null) { thisTagSelector.getReactionsWindow().containerView.animate().alpha(0).setDuration(180).start(); } thisTagSelector.animate().alpha(0.01f).translationY(-dp(12)).scaleX(.7f).scaleY(.7f).withEndAction(() -> { contentView.removeView(thisTagSelector); }).setDuration(180).start(); } private ReactionsContainerLayout tagSelector; private void showTagSelector() { if (getDialogId() != getUserConfig().getClientUserId() || !getUserConfig().isPremium()) return; if (tagSelector != null) return; tagSelector = new ReactionsContainerLayout(ReactionsContainerLayout.TYPE_TAGS, this, getContext(), currentAccount, themeDelegate) { private int[] loc = new int[2]; private ValueAnimator va; private boolean firstLayout = true; private void updateBubbleOffset(float x, boolean animated) { if (va != null) { va.cancel(); va = null; } if (!animated) { setBubbleOffset(x); } else { va = ValueAnimator.ofFloat(bubblesOffset, x); va.addUpdateListener(anm -> { setBubbleOffset((float) anm.getAnimatedValue()); invalidate(); }); va.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); va.setDuration(420); va.start(); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); final ActionBarMenu actionMode = actionBar.createActionMode(); View item = actionMode.getItem(tag_message); if (item != null) { getLocationInWindow(loc); float x = getX(); float x2 = x + getWidth(); item.getLocationInWindow(loc); float cx = loc[0] + item.getWidth() / 2f + dp(20) * (LocaleController.isRTL ? -1 : 1); if (LocaleController.isRTL) { updateBubbleOffset(cx - x, !firstLayout); } else { updateBubbleOffset(cx - x2, !firstLayout); } firstLayout = false; } } }; tagSelector.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(24), AndroidUtilities.dp(4), AndroidUtilities.dp(0)); tagSelector.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { if (tagSelector == null) return; if (getDialogId() == getUserConfig().getClientUserId() && !getUserConfig().isPremium()) { new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); clearSelectionMode(false); return; } boolean updateFilteredMessages = false; boolean notifyFilteredMessages = false; boolean remove = tagSelector.getSelectedReactions().contains(visibleReaction); HashSet groupsChecked = new HashSet<>(); int messagesCount = 0; for (int a = 0; a < selectedMessagesIds.length; ++a) { for (int k = 0; k < selectedMessagesIds[a].size(); ++k) { MessageObject messageObject = selectedMessagesIds[a].valueAt(k); if (messageObject.hasValidGroupId()) { MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); if (group == null || groupsChecked.contains(group.groupId)) continue; groupsChecked.add(group.groupId); messageObject = group.findPrimaryMessageObject(); if (messageObject == null) continue; } if (messageObject.hasReaction(visibleReaction) == remove) { selectReaction(findMessageCell(messageObject.getId(), false), messageObject, null, null, 0, 0, visibleReaction, false, false, false, true); if (!remove) { messagesCount++; } } if (messageObject != null && messageObject.messageOwner != null) { if (chatAdapter.isFiltered) { MessageObject realMessage = messagesDict[0].get(messageObject.getId()); if (realMessage != null && realMessage.messageOwner != null) { realMessage.messageOwner.reactions = messageObject.messageOwner.reactions; } } else if (!chatAdapter.isFiltered && searchingReaction != null) { updateFilteredMessages = true; } } if (chatAdapter.isFiltered && !messageObject.hasReaction(searchingReaction)) { final MessageObject msg = messageObject; final MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(msg); if (groupedMessages != null) { for (int i = 0; i < groupedMessages.messages.size(); ++i) { MessageObject gmsg = groupedMessages.messages.get(i); getMediaDataController().removeMessageFromResults(gmsg.getId()); } } else { getMediaDataController().removeMessageFromResults(msg.getId()); } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } updateFilteredMessages = true; notifyFilteredMessages = true; } } } if (updateFilteredMessages) { updateFilteredMessages(notifyFilteredMessages); } clearSelectionMode(true); if (messagesCount > 0) { TLRPC.Document document; if (visibleReaction.documentId == 0) { TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(visibleReaction.emojicon); if (availableReaction == null) { return; } document = availableReaction.activate_animation; } else { document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, visibleReaction.documentId); } if (document == null) { return; } BulletinFactory.of(ChatActivity.this).createMessagesTaggedBulletin(messagesCount, document, null).show(true); } } }); tagSelector.setTop(true); tagSelector.setClipChildren(false); tagSelector.setClipToPadding(false); tagSelector.setVisibility(View.VISIBLE); tagSelector.setHint(LocaleController.getString(tagSelector.getSelectedReactions().isEmpty() ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); contentView.addView(tagSelector, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0)); tagSelector.setMessage(null, null, true); tagSelector.setTranslationY(-dp(12)); tagSelector.setScaleY(.4f); tagSelector.setScaleX(.4f); tagSelector.animate().scaleY(1f).scaleX(1f).translationY(0).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); updateSelectedMessageReactions(); tagSelector.setTranslationY(contentPanTranslation + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); } private void createSearchContainer() { if (searchContainer != null || getContext() == null) { return; } searchContainer = new FrameLayout(getContext()) { @Override protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { if (child == searchCountText) { int leftMargin = 18; 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.setClickable(false); searchContainer.setWillNotDraw(false); bottomViewsVisibilityController.setViewVisible(MESSAGE_SEARCH_CONTAINER, false, false); searchContainer.setClipToPadding(false); searchCountText = new AnimatedTextView(getContext(), true, true, true); searchCountText.setAnimationProperties(.25f, 0, 280, CubicBezierInterpolator.EASE_OUT_QUINT); // searchCountText.setScaleProperty(.5f); searchCountText.setTextSize(dp(15)); searchCountText.setTypeface(AndroidUtilities.bold()); searchCountText.setTextColor(getThemedColor(Theme.key_chat_searchPanelText)); searchCountText.setGravity(Gravity.LEFT); searchContainer.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.CENTER_VERTICAL, 0, -1, 97.33f, 0)); chatInputBubbleContainer.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, searchContainerHeight, Gravity.BOTTOM, 7, 0, 7, 0)); if (hashtagHistoryView != null) { hashtagHistoryView.bringToFront(); } searchExpandList = new AnimatedTextView(getContext(), true, false, true); searchExpandList.setAnimationProperties(0, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); searchExpandList.setScaleProperty(.7f); searchExpandList.setTextSize(dp(15)); searchExpandList.setGravity(Gravity.RIGHT); searchExpandList.setTypeface(AndroidUtilities.bold()); searchExpandList.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlueText2)); searchExpandList.setText(LocaleController.getString(messagesSearchListContainer != null && messagesSearchListContainer.getTag() != null ? R.string.SearchAsChat : R.string.SearchAsList)); searchExpandList.adaptWidth = false; searchExpandList.setPadding(dp(15.33f), 0, dp(15.33f), 0); searchExpandList.setOnClickListener(v -> { toggleMesagesSearchListView(); }); searchExpandList.setAlpha(0.5f); searchExpandList.setClickable(false); searchContainer.addView(searchExpandList, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.FILL_VERTICAL)); searchOtherButton = new AnimatedTextView(getContext(), true, true, true); searchOtherButton.setGravity(Gravity.CENTER); searchOtherButton.setTypeface(AndroidUtilities.bold()); searchOtherButton.setTextColor(getThemedColor(Theme.key_chat_fieldOverlayText)); searchOtherButton.setTextSize(AndroidUtilities.dp(15)); searchOtherButton.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_windowBackgroundWhite), Theme.blendOver(getThemedColor(Theme.key_windowBackgroundWhite), getThemedColor(Theme.key_listSelector)))); searchOtherButton.setText(LocaleController.getString(chatAdapter.isFiltered ? R.string.SavedTagHideOtherMessages : R.string.SavedTagShowOtherMessages)); searchOtherButton.setOnClickListener(v -> { setFilterMessages(!chatAdapter.isFiltered); }); searchOtherButton.setVisibility(View.GONE); searchOtherButton.setAlpha(0f); searchContainer.addView(searchOtherButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); if (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && chatMode != MODE_SEARCH && !ChatObject.isMonoForum(currentChat)) { searchUserButton = new ImageView(getContext()); 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(44, 44, Gravity.LEFT | Gravity.TOP, 48, 0, 0, 0)); searchUserButton.setOnClickListener(view -> { if (mentionContainer != null) { mentionContainer.setReversed(true); mentionContainer.getAdapter().setSearchingMentions(true); checkUi_botMenuPosition(); } searchCalendarButton.setVisibility(View.GONE); searchUserButton.setVisibility(View.GONE); searchingForUser = true; searchingUserMessages = null; searchingChatMessages = null; searchItem.setSearchFieldHint(LocaleController.getString(R.string.SearchMembers)); searchItem.setSearchFieldCaption(LocaleController.getString(R.string.SearchFrom)); AndroidUtilities.showKeyboard(searchItem.getSearchField()); searchItem.clearSearchText(); }); searchUserButton.setContentDescription(LocaleController.getString(R.string.AccDescrSearchByUser)); } if (chatMode != MODE_SEARCH) { searchCalendarButton = new ImageView(getContext()); 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(44, 44, Gravity.LEFT | Gravity.TOP, 2.66f, 0, 0, 0)); searchCalendarButton.setOnClickListener(view -> { if (getParentActivity() == null) { return; } if (searchItem != null) { 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(R.string.JumpToDate)); } } private void showSearchShowOther(boolean show) { searchOtherButton.setVisibility(View.VISIBLE); searchOtherButton.animate().alpha(show ? 1f : 0f).withEndAction(() -> { searchOtherButton.setVisibility(show ? View.VISIBLE : View.GONE); }).setDuration(170).start(); } public void onPageDownClicked() { wasManualScroll = true; textSelectionHelper.cancelTextSelectionRunnable(); final Runnable inCaseLoading = () -> { sideControlsButtonsLayout.setButtonLoading(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, true, true); }; if (createUnreadMessageAfterId != 0) { scrollToMessageId(createUnreadMessageAfterId, 0, false, returnToLoadIndex, true, 0, null, inCaseLoading); } else if (returnToMessageId > 0) { scrollToMessageId(returnToMessageId, 0, true, returnToLoadIndex, true, 0, null, inCaseLoading); } else { scrollToLastMessage(true, true, inCaseLoading); if (!pinnedMessageIds.isEmpty()) { forceScrollToFirst = true; forceNextPinnedMessageId = pinnedMessageIds.get(0); } } } public ActionBarMenuItem getHeaderItem() { return headerItem; } private void playReactionAnimation(Integer messageId) { if (fragmentView == null) { return; } BaseCell cell = findMessageCell(messageId, false); if (cell instanceof ChatMessageCell) { final ChatMessageCell messageCell = (ChatMessageCell) cell; final TLRPC.MessagePeerReaction reaction = messageCell.getMessageObject().getRandomUnreadReaction(); if (reaction != null && (messageCell.reactionsLayoutInBubble.hasUnreadReactions || reaction.big)) { ReactionsEffectOverlay.show(ChatActivity.this, null, cell, null,0, 0, ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction), currentAccount, reaction.big ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } messageCell.markReactionsAsRead(); } else if (cell instanceof ChatActionCell) { final ChatActionCell actionCell = (ChatActionCell) cell; final TLRPC.MessagePeerReaction reaction = actionCell.getMessageObject().getRandomUnreadReaction(); if (reaction != null && (actionCell.reactionsLayoutInBubble.hasUnreadReactions || reaction.big)) { ReactionsEffectOverlay.show(ChatActivity.this, null, cell, null,0, 0, ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction), currentAccount, reaction.big ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } actionCell.markReactionsAsRead(); } } private void dimBehindView(View view, boolean enable) { dimBehindView(view, false, enable); } private void dimBehindView(View view, boolean blur, boolean enable) { setScrimView(view); dimBehindView(enable ? 0.2f : 0, blur, view != sideControlsButtonsLayout); } private void dimBehindView(View view, float value) { setScrimView(view); dimBehindView(value, false, view != sideControlsButtonsLayout); } private void setScrimView(View scrimView) { if (this.scrimView == scrimView) { return; } if (this.scrimView != null) { if (this.scrimView instanceof ChatActionCell) { ((ChatActionCell) this.scrimView).setInvalidateWithParent(null); } } this.scrimView = scrimView; if (this.scrimView instanceof ChatActionCell) { ((ChatActionCell) this.scrimView).setInvalidateWithParent(fragmentView); } } public void dimBehindView(boolean enable) { dimBehindView(enable ? 0.2f : 0, false, true); } private void checkInstantCameraView() { if (instantCameraView != null || !CameraView.isCameraAllowed() || getContext() == null) { return; } instantCameraView = new InstantCameraView(getContext(), this, themeDelegate, true) { @Override public void startAnimation(boolean open, boolean fromPaused) { super.startAnimation(open, fromPaused); animatorRoundMessageCameraVisibility.setValue(open, true); } }; instantCameraView.setClipToPadding(false); instantCameraView.setButtonsBackground(glassBackgroundDrawableFactory, blurredBackgroundColorProvider); int index = contentView.indexOfChild(chatInputViewsContainer); if (index < 0) { index = contentView.getChildCount(); } index = Math.min(index + 1, contentView.getChildCount()); contentView.addView(instantCameraView, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); } private void dimBehindView(float value, boolean blur, 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; final float max = Math.max(scrimPaintAlpha, value); if (enable) { scrimViewAlpha = 1f; scrimViewProgress = 0; if (scrimViewAlphaAnimator != null) { scrimViewAlphaAnimator.cancel(); } scrimProgressDirection = true; animators.add(scrimPaintAlphaAnimator = ValueAnimator.ofFloat(0, value)); if (blur) { AndroidUtilities.makeGlobalBlurBitmap(bitmap -> { scrimBlurBitmap = bitmap; scrimBlurBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG); scrimBlurBitmapPaint.setShader(scrimBlurBitmapShader = new BitmapShader(scrimBlurBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); ColorMatrix colorMatrix = new ColorMatrix(); AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, Theme.isCurrentThemeDark() ? .08f : +.25f); AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, Theme.isCurrentThemeDark() ? -.02f : -.07f); scrimBlurBitmapPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); scrimBlurMatrix = new Matrix(); }, 14); } } else { scrimViewProgress = scrimPaintAlpha / max; scrimProgressDirection = false; animators.add(scrimPaintAlphaAnimator = ValueAnimator.ofFloat(scrimPaintAlpha, 0)); } scrimPaintAlphaAnimator.addUpdateListener(a -> { scrimPaintAlpha = (float) a.getAnimatedValue(); scrimViewProgress = scrimPaintAlpha / max; if (fragmentView != null) { fragmentView.invalidate(); } }); if (!enable || hidePagedownButtons) { if (sideControlsButtonsLayout != null) { animators.add(ObjectAnimator.ofFloat(sideControlsButtonsLayout, View.ALPHA, enable ? 0 : 1)); } } scrimAnimatorSet.playTogether(animators); scrimAnimatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); scrimAnimatorSet.setDuration(320); final ChatMessageCell cell = scrimView instanceof ChatMessageCell ? (ChatMessageCell) scrimView : null; scrimAnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (!enable) { if (scrimBlurBitmap != null) { scrimBlurBitmapShader = null; scrimBlurBitmapPaint = null; scrimBlurBitmap.recycle(); scrimBlurBitmap = null; } if (cell != null) { cell.invalidate(); } setScrimView(null); scrimViewTask = null; scrimViewReaction = null; contentView.invalidate(); chatListView.invalidate(); } } }); if (scrimView != null && scrimViewAlpha <= 0f) { setScrimView(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.bold()); 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 boolean filledEditTextItemMenu = false; private void checkEditTextItemMenu() { if (filledEditTextItemMenu || editTextItem == null) { return; } ActionBarMenuItem item = editTextItem.createView(); item.addSubItem(text_spoiler, LocaleController.getString(R.string.Spoiler)); if (chatMode == 0) { item.addSubItem(text_quote, LocaleController.getString(R.string.Quote)); } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString(R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); item.addSubItem(text_bold, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString(R.string.Italic)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); item.addSubItem(text_italic, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString(R.string.Mono)); stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); item.addSubItem(text_mono, stringBuilder); if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString(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); item.addSubItem(text_strike, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString(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); item.addSubItem(text_underline, stringBuilder); } item.addSubItem(text_link, LocaleController.getString(R.string.CreateLink)); item.addSubItem(text_regular, LocaleController.getString(R.string.Regular)); filledEditTextItemMenu = true; } private void updatePagedownButtonsPosition() { if (sideControlsButtonsLayout != null) { float baseTranslationY2 = -windowInsetsStateHolder.getAnimatedMaxBottomInset() - chatInputViewsContainer.getInputBubbleHeight() - dp(ChatInputViewsContainer.INPUT_BUBBLE_BOTTOM + 4); sideControlsButtonsLayout.setTranslationY(baseTranslationY2); } if (suggestEmojiPanel != null) { float baseTranslationY2 = -windowInsetsStateHolder.getAnimatedMaxBottomInset() - dp(ChatInputViewsContainer.INPUT_BUBBLE_BOTTOM + 7); suggestEmojiPanel.setTranslationY(baseTranslationY2); } } private void updateReactionsMentionButton(boolean animated) { if (getParentActivity() == null) { return; } boolean visible = reactionsMentionCount > 0 && (chatMode == 0 || chatMode == MODE_SUGGESTIONS); sideControlsButtonsLayout.showButton(ChatActivitySideControlsButtonsLayout.BUTTON_REACTIONS, visible, animated); sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_REACTIONS, reactionsMentionCount, animated); } public void fallbackFieldPanel() { if (messageSuggestionParams != null) { showFieldPanelForSuggestionParams(messageSuggestionParams); } else if (foundWebPage != null) { showFieldPanelForWebPage(true, foundWebPage, false); } else if (replyingQuote != null) { showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); } else if (replyingMessageObject != null && replyingMessageObject != threadMessageObject) { showFieldPanelForReply(replyingMessageObject); } else if (messagePreviewParams != null && messagePreviewParams.forwardMessages != null) { showFieldPanelForForward(true, messagePreviewParams.forwardMessages.messages); } else if (editingMessageObject != null) { showFieldPanelForEdit(true, editingMessageObject); } else { showFieldPanelForWebPage(false, null, true); } } private boolean keyboardWasVisible; private void openForwardingPreview(int startTab) { if (messagePreviewParams == null || forwardingPreviewView != null) { return; } if (messagePreviewParams.linkMessage != null) { messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } if (messagePreviewParams.isEmpty()) { return; } // if (chatActivityEnterView != null) { // chatActivityEnterView.freezeEmojiView(false); // } keyboardWasVisible = chatActivityEnterView.isKeyboardVisible(); forwardingPreviewView = new MessagePreviewView(contentView.getContext(), this, messagePreviewParams, currentUser, currentChat, currentAccount, themeDelegate, startTab, replyingQuote != null && replyingQuote.outdated) { @Override protected void removeLink() { dismiss(true); foundWebPage = null; if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(null, false); } if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, null, null, replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } fallbackFieldPanel(); } @Override protected void removeQuote() { dismiss(true); replyingQuote = null; showFieldPanelForReply(replyingMessageObject); } @Override protected void removeReply() { dismiss(true); replyingMessageObject = null; replyingQuote = null; messagePreviewParams.updateReply(null, null, dialog_id, null); fallbackFieldPanel(); } @Override protected void removeForward() { super.removeForward(); dismiss(true); messagePreviewParams.updateForward(null, dialog_id); fallbackFieldPanel(); } @Override protected void onFullDismiss(boolean canShowKeyboard) { if (messagePreviewParams != null) { messagePreviewParams.attach(null); } if (canShowKeyboard) { AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null) { chatActivityEnterView.freezeEmojiView(false); } }, 15); } } @Override protected void onQuoteSelectedPart() { if (replyingQuote == null || replyingQuote.message == null || messagePreviewParams.quote != null && messagePreviewParams.quote.message != null && replyingQuote.message.getId() != messagePreviewParams.quote.message.getId()) { replyingQuote = messagePreviewParams.quote; } } @Override protected void onDismiss(boolean canShowKeyboard) { forwardingPreviewView = null; checkShowBlur(true); if (messagePreviewParams != null) { if (replyingQuote == null) { replyingQuote = messagePreviewParams.quote; } if (messagePreviewParams.quote == null) { replyingQuote = null; } if (replyingQuote != null) { replyingQuote.outdated = false; replyingQuote.start = messagePreviewParams.quoteStart; replyingQuote.end = messagePreviewParams.quoteEnd; replyingQuote.update(); if (fieldPanelShown == 2) { showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); } } else { ArrayList selectedMessage = new ArrayList<>(); if (messagePreviewParams.forwardMessages != null) { messagePreviewParams.forwardMessages.getSelectedMessages(selectedMessage); } fallbackFieldPanel(); } } forbidForwardingWithDismiss = false; if (keyboardWasVisible && canShowKeyboard) { AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null) { chatActivityEnterView.openKeyboard(); } }, 50); keyboardWasVisible = false; } AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } @Override protected void selectAnotherChat(boolean forward) { dismiss(false); if (messagePreviewParams != null) { if (!forward) { ignoreDraft = true; } int hasPoll = 0; boolean hasInvoice = false; if (messagePreviewParams.forwardMessages != null) { for (int a = 0, N = messagePreviewParams.forwardMessages.messages.size(); a < N; a++) { MessageObject messageObject = messagePreviewParams.forwardMessages.messages.get(a); if (messageObject.isTodo()) { hasPoll = 3; } else if (messageObject.isPoll()) { if (hasPoll != 2) { hasPoll = messageObject.isPublicPoll() ? 2 : 1; } } else if (messageObject.isInvoice()) { hasInvoice = true; } selectedMessagesIds[0].put(messageObject.getId(), messageObject); } } final Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); args.putBoolean("quote", !forward); final boolean reply = !forward && messagePreviewParams.replyMessage != null && !messagePreviewParams.replyMessage.messages.isEmpty() && messagePreviewParams.quote == null; args.putBoolean("reply_to", reply); if (reply) { final long author = DialogObject.getPeerDialogId(messagePreviewParams.replyMessage.messages.get(0).getFromPeer()); if (author != 0 && author != getDialogId() && author != getUserConfig().getClientUserId() && author > 0) { args.putLong("reply_to_author", author); } } args.putInt("hasPoll", hasPoll); args.putBoolean("hasInvoice", hasInvoice); args.putInt("messagesCount", messagePreviewParams.forwardMessages == null ? 0 : messagePreviewParams.forwardMessages.messages.size()); args.putBoolean("canSelectTopics", true); final DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } } @Override protected void didSendPressed() { super.didSendPressed(); dismiss(true); chatActivityEnterView.getSendButton().callOnClick(); } }; messagePreviewParams.attach(forwardingPreviewView); TLRPC.Peer defPeer = chatInfo != null ? chatInfo.default_send_as : null; if (defPeer == null && sendAsPeersObj != null && !sendAsPeersObj.peers.isEmpty()) { defPeer = sendAsPeersObj.peers.get(0).peer; } forwardingPreviewView.setSendAsPeer(defPeer); checkShowBlur(true); contentView.addView(forwardingPreviewView); if (keyboardWasVisible) { chatActivityEnterView.freezeEmojiView(true); chatActivityEnterView.showEmojiView(); openKeyboardOnAttachMenuClose = true; } AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); fragmentView.requestLayout(); } private void animateToNextChat() { if (pullingDownDrawable == null) { return; } if (isTopic) { if (pullingDownDrawable.getTopic() != null) { addToPulledTopicsMyself(); addToPulledDialogs(currentChat, pullingDownDrawable.nextTopic, dialog_id, dialogFolderId, dialogFilterId); Bundle bundle = new Bundle(); bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); bundle.putBoolean("pulled", true); ChatActivity chatActivity = ForumUtilities.getChatActivityForTopic(ChatActivity.this, -dialog_id, pullingDownDrawable.getTopic(), 0, bundle); chatActivity.setPullingDownTransition(true); replacingChatActivity = true; presentFragment(chatActivity, true); } } else if (pullingDownDrawable.getChatId() != 0) { addToPulledDialogsMyself(); addToPulledDialogs(pullingDownDrawable.nextChat, null, 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); if (nextChannels != null && nextChannels.size() > 1) { chatActivity.setNextChannels(new ArrayList<>(nextChannels.subList(1, nextChannels.size()))); } chatActivity.setPullingDownTransition(true); replacingChatActivity = true; presentFragment(chatActivity, true); } } private ArrayList nextChannels; public void setNextChannels(ArrayList channels) { nextChannels = channels; } private void addToPulledDialogsMyself() { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, null, dialog_id, dialogFilterId, dialogFolderId); } private void addToPulledDialogs(TLRPC.Chat chat, TLRPC.TL_forumTopic topic, long dialogId, int folderId, int filterId) { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); BackButtonMenu.addToPulledDialogs(this, stackIndex, chat, null, topic, dialogId, folderId, filterId); } private void addToPulledTopicsMyself() { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, forumTopic, dialog_id, dialogFilterId, dialogFolderId); } private void setPullingDownTransition(boolean fromPullingDownTransition) { this.fromPullingDownTransition = fromPullingDownTransition; } public void setSwitchFromTopics(boolean switchFromTopics) { this.switchFromTopics = switchFromTopics; } 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(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(searchingQuery = "", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); } private void updateTranslateItemVisibility() { if (translateItem == null) { return; } translateItem.setVisibility(getMessagesController().getTranslateController().isTranslateDialogHidden(getDialogId()) && getMessagesController().getTranslateController().isDialogTranslatable(getDialogId()) ? View.VISIBLE : View.GONE); } private Animator infoTopViewAnimator; private void updateInfoTopView(boolean animated) { if (contentView == null) { return; } SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); CharSequence text = null; View.OnClickListener onClickListener = null; 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(R.string.ActionUserInvitedToChannel) : LocaleController.getString(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 checkTopUndoView() { if (topUndoView != null) { return; } topUndoView = new UndoView(getContext(), 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, 17, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 8, 8, 8, 0)); } private void createPinnedMessageView() { if (currentEncryptedChat != null || pinnedMessageView != null || getContext() == null) { return; } final int possibleLeftMarginDp = 0; // isSideMenued() ? SIDE_MENU_WIDTH : 0; pinnedMessageView = new BlurredFrameLayout(getContext(), 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)); int index = 8; if (topChatPanelView != null && topChatPanelView.getParent() == contentView) { index = contentView.indexOfChild(topChatPanelView); } contentView.addView(pinnedMessageView, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); pinnedMessageView.setOnClickListener(v -> { wasManualScroll = true; if (isThreadChat() && !isTopic) { scrollToMessageId((int) 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(getContext()); 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(getContext(), themeDelegate); pinnedMessageView.addView(pinnedLineView, LayoutHelper.createFrame(2, 48, Gravity.LEFT | Gravity.TOP, 8, 0, 0, 0)); pinnedMessageView.setClipChildren(false); pinnedCounterTextView = new NumberTextView(getContext()); pinnedCounterTextView.setAddNumber(); pinnedCounterTextView.setTextSize(14); pinnedCounterTextView.setTextColor(getThemedColor(Theme.key_chat_topPanelTitle)); pinnedCounterTextView.setTypeface(AndroidUtilities.bold()); pinnedMessageView.addView(pinnedCounterTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 7, 44 + possibleLeftMarginDp, 0)); for (int a = 0; a < 2; a++) { pinnedNameTextView[a] = new TrackingWidthSimpleTextView(getContext()); pinnedNameTextView[a].setTextSize(14); pinnedNameTextView[a].setTextColor(getThemedColor(Theme.key_chat_topPanelTitle)); pinnedNameTextView[a].setTypeface(AndroidUtilities.bold()); pinnedMessageView.addView(pinnedNameTextView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.TOP | Gravity.LEFT, 18, 7.3f, 44 + possibleLeftMarginDp, 0)); pinnedMessageTextView[a] = new SimpleTextView(getContext()) { @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 + possibleLeftMarginDp, 0)); pinnedMessageButton[a] = new PinnedMessageButton(getContext()); pinnedMessageView.addView(pinnedMessageButton[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.RIGHT, 0, 10, 14, 0)); pinnedMessageImageView[a] = new BackupImageView(getContext()) { private SpoilerEffect spoilerEffect = new SpoilerEffect(); private Path path = new Path(); private float[] radii = new float[8]; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (hasBlur) { canvas.save(); AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); int[] rad = imageReceiver.getRoundRadius(); radii[0] = radii[1] = rad[0]; radii[2] = radii[3] = rad[1]; radii[4] = radii[5] = rad[2]; radii[6] = radii[7] = rad[3]; path.rewind(); path.addRoundRect(AndroidUtilities.rectTmp, radii, Path.Direction.CW); canvas.clipPath(path); int sColor = Color.WHITE; spoilerEffect.setColor(ColorUtils.setAlphaComponent(sColor, (int) (Color.alpha(sColor) * 0.325f))); spoilerEffect.setBounds(0, 0, getWidth(), getHeight()); spoilerEffect.draw(canvas); canvas.restore(); invalidate(); } } }; pinnedMessageImageView[a].setBlurAllowed(true); 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(getContext()); 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(R.string.AccPinnedMessagesList)); pinnedListButton.setVisibility(View.INVISIBLE); pinnedListButton.setAlpha(0.0f); pinnedListButton.setScaleX(0.4f); pinnedListButton.setScaleY(0.4f); 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(getContext()); closePinned.setImageResource(R.drawable.miniplayer_close); closePinned.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); closePinned.setScaleType(ImageView.ScaleType.CENTER); closePinned.setVisibility(View.GONE); closePinned.setContentDescription(LocaleController.getString(R.string.Close)); pinnedProgress = new RadialProgressView(getContext(), 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)); 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) && (!currentChat.monoforum /*|| ChatObject.canManageMonoForum(currentAccount, 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(R.string.UnpinMessageAlertTitle)); builder.setMessage(LocaleController.getString(R.string.UnpinMessageAlert)); builder.setPositiveButton(LocaleController.getString(R.string.UnpinMessage), (dialogInterface, i) -> { MessageObject messageObject = pinnedMessageObjects.get(currentPinnedMessageId); if (messageObject == null) { messageObject = messagesDict[0].get(currentPinnedMessageId); } unpinMessage(messageObject); }); builder.setNegativeButton(LocaleController.getString(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); } }); updatePinnedListButton(false); } private void openAnotherForward() { if (messagePreviewParams == null || messagePreviewParams.isEmpty() || messagePreviewParams.forwardMessages == null || messagePreviewParams.forwardMessages.messages == null) { return; } boolean fewSenders = false; long lastPeerId = 0; long dialogId = 0; for (int a = 0, N = messagePreviewParams.forwardMessages.messages.size(); a < N; a++) { MessageObject message = messagePreviewParams.forwardMessages.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", messagePreviewParams.forwardMessages.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", messagePreviewParams.forwardMessages.messages.size()), chat == null ? "" : chat.title); } builder.setMessage(AndroidUtilities.replaceTags(message)); builder.setTitle(LocaleController.formatPluralString("messages", messagePreviewParams.forwardMessages.messages.size())); builder.setPositiveButton(LocaleController.getString(R.string.CancelForwarding), (dialogInterface, i) -> { forbidForwardingWithDismiss = false; if (messagePreviewParams != null) { messagePreviewParams.updateForward(null, dialog_id); } fallbackFieldPanel(); }); builder.setNegativeButton(LocaleController.getString(R.string.ShowForwardingOptions), (dialogInterface, i) -> { openForwardingPreview(MessagePreviewView.TAB_FORWARD); }); AlertDialog dialog = builder.create(); showDialog(dialog); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(getThemedColor(Theme.key_text_RedBold)); } } 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.updatePinnedTopicStarterMessage(); } } fragment.loadedPinnedMessagesCount = loadedPinnedMessagesCount; fragment.totalPinnedMessagesCount = isTopic ? pinnedMessageIds.size() : 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 openHashtagSearch(String text) { ChatActivity.this.openHashtagSearch(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); if (pinnedMessageIds.isEmpty()) { preferences.edit().remove("pin_" + dialog_id).commit(); } else { 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) { if (isTopic) { for (int i = 0; i < pinnedMessageIds.size(); i++) { getMessagesController().pinMessage(currentChat, currentUser, pinnedMessageIds.get(i), true, false, false); } } else { 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() && !parentLayout.hasIntegratedBlurInPreview() && !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); if (fragmentView != null) { fragmentView.invalidate(); } } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); if (fragmentView != null) { 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.setOnClickListener(e -> { finishPreviewFragment(); }); blurredView.setAlpha(0.0f); blurredView.animate().setListener(null).cancel(); blurredView.animate().alpha(1f).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (fragmentView == null || chatListView == null) { return; } 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(); if (fragmentView != null) { fragmentView.invalidate(); } } } @Override public int getPreviewHeight() { if (chatMode == MODE_PINNED && messages.size() == 2) { return getHeightForMessage(messages.get(0), false) + AndroidUtilities.dp(80) + ActionBar.getCurrentActionBarHeight(); } return super.getPreviewHeight(); } boolean animateProgressViewTo; private Boolean liteModeChat; private boolean getLiteModeChat() { if (liteModeChat == null) { liteModeChat = LiteMode.isEnabled(LiteMode.FLAGS_CHAT); } return liteModeChat; } private void showProgressView(boolean show) { if (progressView == null) { return; } if (DISABLE_PROGRESS_VIEW && !AndroidUtilities.isTablet() && !isComments && currentUser == null && getLiteModeChat()) { animateProgressViewTo = show; return; } if (fragmentOpened && SharedConfig.animationsEnabled()) { if (show == animateProgressViewTo) { return; } animateProgressViewTo = 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 { animateProgressViewTo = show; progressView.setVisibility(show ? View.VISIBLE : View.INVISIBLE); } } private void hideInfoView() { 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, topChatPanelView != null && topChatPanelView.getVisibility() == View.VISIBLE ? (topChatPanelView.getLayoutParams().height - AndroidUtilities.dp(2)) : 0); topPanelViewH += Math.max(-topPanelViewH, topChatPanelViewOffset); float topPanelView2H = Math.max(0, topChatPanelView2 != null && topChatPanelView2.getVisibility() == View.VISIBLE ? (topChatPanelView2.getLayoutParams().height - AndroidUtilities.dp(2)) : 0); topPanelView2H += Math.max(-topPanelView2H, topChatPanelView2Offset); float pinnedViewH = 0; if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } if (actionBarSearchTags != null) { pinnedViewH = Math.max(pinnedViewH, actionBarSearchTags.getCurrentHeight()); } if (hashtagSearchTabs != null) { pinnedViewH = Math.max(pinnedViewH, hashtagSearchTabs.getCurrentHeight()); } 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() - AndroidUtilities.dp(4)); } float oldPadding = chatListViewPaddingTop; chatListViewPaddingTop = dp(4) + contentPaddingTop + (paddingTopHeight = topPanelViewH + pinnedViewH + pendingViewH + topPanelView2H) + (topicsTabs != null ? dp(48) * (1.0f - topicsTabs.sidemenuT) : 0); chatListViewPaddingTop += blurredViewTopOffset; chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation; float searchExpandOffset = 0; if (searchExpandProgress != 0 && chatActivityEnterView != null && chatActivityEnterView.getVisibility() == View.VISIBLE) { chatListViewPaddingTop -= (searchExpandOffset = searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(searchContainerHeight))); } if (infoTopView != null) { infoTopView.setTranslationY(chatListView.getTranslationY() + chatListViewPaddingTop + topViewOffset - dp(30)); chatListViewPaddingTop += topViewOffset; chatListViewPaddingVisibleOffset += topViewOffset; } if (floatingDateView != null) { floatingDateView.setTranslationY(chatListView.getTranslationY() - searchExpandOffset + chatListViewPaddingTop + floatingDateViewOffset - dp(4)); } updateFloatingTopicView(); // int p = isInsideContainer && chatMode != MODE_SEARCH ? dp(4) : 0; // chatListView.getMeasuredHeight() * 2 / 3; if (chatListView != null && chatLayoutManager != null && chatAdapter != null) { int p = chatListView.getPaddingTop(); int b = chatListView.getPaddingBottom(); checkUi_chatListViewPaddings(); // final int b = blurredViewBottomOffset + AndroidUtilities.navigationBarHeight + dp(9 + 44 + 7); // + (isInsideContainer && searchContainer != null && searchContainer.getVisibility() == View.VISIBLE ? dp(50) : 0); if (chatListView.getPaddingTop() != p || chatListView.getPaddingBottom() != b) { //int top = 0; //MessageObject scrollToMessageObject = null; //for (int i = 0; i < chatListView.getChildCount(); i++) { // View v = chatListView.getChildAt(i); // if (v instanceof ChatMessageCell) { // scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); // top = getScrollingOffsetForView(v); // break; // } else if (v instanceof ChatActionCell) { // scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); // top = getScrollingOffsetForView(v); // break; // } //} //if (scrollToMessageObject != null) { // chatAdapter.updateRowsSafe(); // int index = messages.indexOf(scrollToMessageObject); // if (index >= 0) { // chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + index, top); // } //} invalidateMessagesVisiblePart(); invalidateMergedVisibleBlurredPositionsAndSourcesPositions(); } chatListView.setTopGlowOffset((int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - 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 (child.getTop() > padding) { chatListView.scrollBy(0, (int) (child.getTop() - padding)); } break; } } } if (!isThreadChat() && !wasManualScroll && unreadMessageObject != null && chatListView != null && !(translateButton != null && translateButton.getVisibility() == View.VISIBLE)) { chatListView.scrollBy(0, (int) (oldPadding - chatListViewPaddingTop)); } } invalidateChatListViewTopPadding = false; Bulletin.updateCurrentPosition(); checkUi_chatListViewPaddings(); } private void checkUi_chatListViewPaddings() { if (chatListView == null) { return; } final int paddingBottomTarget = (int) ( blurredViewBottomOffset + dp(9 + 7) + inputIslandHeightTarget + windowInsetsStateHolder.getInsets(WindowInsetsCompat.Type.ime() | WindowInsetsCompat.Type.systemBars()).bottom ); final float paddingBottomAnimated = blurredViewBottomOffset + dp(9 + 7) + inputIslandHeightCurrent + windowInsetsStateHolder.getAnimatedMaxBottomInset(); final int paddingTop = (int) chatListViewPaddingTop; if (topicsTabs != null) { topicsTabs.setSideMenuBackgroundMarginTop(Math.max(0, paddingTop - blurredViewTopOffset - dp(5))); } chatListViewPaddingsAnimator.setPaddings(paddingTop, paddingBottomAnimated, paddingBottomTarget, wasManualScroll); } private void invalidateChatListViewTopPadding() { if (!invalidateChatListViewTopPadding) { invalidateChatListViewTopPadding = true; if (contentView != null) { contentView.invalidate(); } if (chatListView != null) { chatListView.invalidate(); } } int topPanelHeight = topChatPanelView != null && topChatPanelView.getVisibility() == View.VISIBLE ? ((topChatPanelView.getLayoutParams() == null ? AndroidUtilities.dp(50) : topChatPanelView.getLayoutParams().height) - AndroidUtilities.dp(2)) : 0; topPanelHeight = topPanelHeight + (int) Math.max(-topPanelHeight, topChatPanelViewOffset); float translation = contentPanTranslation + contentPaddingTop + Math.max(0, topPanelHeight); if (topicsTabs != null) { translation += dp(48) * (1.f - topicsTabs.sidemenuT); } if (pinnedMessageView != null) { translation += pinnedMessageEnterOffset; pinnedMessageView.setTranslationY(translation); translation += dp(48); } int topPanel2Height = topChatPanelView2 != null && topChatPanelView2.getVisibility() == View.VISIBLE ? ((topChatPanelView2.getLayoutParams() == null ? AndroidUtilities.dp(50) : topChatPanelView2.getLayoutParams().height) - AndroidUtilities.dp(2)) : 0; topPanel2Height = topPanel2Height + (int) Math.max(-topPanel2Height, topChatPanelView2Offset); translation += Math.max(0, topPanel2Height); View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null) { pendingRequestsView.setTranslationY(translation + pendingRequestsDelegate.getViewEnterOffset()); } if (topButtonsLayout != null) { topButtonsLayout.setTranslationY(translation); } float p = 0; if (topicsTabs != null) { p += dp(48) * (1.f - topicsTabs.sidemenuT); } p += actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0; p += hashtagSearchTabs != null ? hashtagSearchTabs.getCurrentHeight() : 0; if (fragmentContextView != null) { float from = 0; if (fragmentLocationContextView != null && fragmentLocationContextView.getVisibility() == View.VISIBLE) { from += dp(36); } fragmentContextView.setTranslationY(contentPanTranslation + p + from + fragmentContextView.getTopPadding()); } if (fragmentLocationContextView != null) { float from = 0; if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { from += AndroidUtilities.dp(fragmentContextView.getStyleHeight()) + fragmentContextView.getTopPadding(); } fragmentLocationContextView.setTranslationY(contentPanTranslation + p + from + fragmentLocationContextView.getTopPadding()); } if (topChatPanelView != null) { topChatPanelView.setTranslationY(contentPanTranslation + p + contentPaddingTop + topChatPanelViewOffset); } if (topChatPanelView2 != null) { topChatPanelView2.setTranslationY(contentPanTranslation + p + contentPaddingTop + topChatPanelView2Offset + topPanelHeight + Math.max(0, topChatPanelViewOffset) + Math.max(0, pinnedMessageView != null ? dp(48) + pinnedMessageEnterOffset : 0)); } if (alertView != null && alertView.getVisibility() == View.VISIBLE) { alertView.setTranslationY(contentPanTranslation + p + contentPaddingTop - dp(50) * (1f - alertViewEnterProgress)); } if (undoView != null) { undoView.setAdditionalTranslationY( windowInsetsStateHolder.getAnimatedMaxBottomInset() + dp(9 + 7) + chatInputViewsContainer.getInputBubbleHeight()); } if (messagesSearchListContainer != null) { messagesSearchListContainer.setTranslationY(getHashtagTabsHeight() + contentPanTranslation); messagesSearchListContainer.setPadding(0, (actionBarSearchTags != null && actionBarSearchTags.shown() ? actionBarSearchTags.getHeight() : 0), 0, getHashtagTabsHeight()); } if (hashtagHistoryView != null) { hashtagHistoryView.setTranslationY(getHashtagTabsHeight() + contentPanTranslation); } } private TextureView createTextureView(boolean add) { if (parentLayout == null) { return null; } AndroidUtilities.cancelRunOnUIThread(destroyTextureViewRunnable); if (videoPlayerContainer == null) { 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(isSideMenued()), AndroidUtilities.roundPlayingMessageSize(isSideMenued())); } } }); videoPlayerContainer.setClipToOutline(true); 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(isSideMenued()), AndroidUtilities.roundPlayingMessageSize(isSideMenued()))); } 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); 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 share() { MessageObject msg = null; for (int a = 1; a >= 0; a--) { if (msg == null && selectedMessagesIds[a].size() != 0) { msg = messagesDict[a].get(selectedMessagesIds[a].keyAt(0)); } selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } if (getParentActivity() != null && msg != null && (msg.isVoice() || msg.isRoundVideo()) && msg.getDocument() != null) { TLRPC.Document document = msg.getDocument(); File file = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, false, true); if ((msg.messageOwner != null && msg.messageOwner.attachPath != null) && (file == null || !file.exists())) { file = new File(msg.messageOwner.attachPath); } if (file != null && file.exists()) { Intent intent = new Intent(Intent.ACTION_SEND); if (msg.isVideo() || msg.isRoundVideo()) { intent.setType("video/mp4"); } else { if (msg != null) { intent.setType(msg.getMimeType()); } else { intent.setType("image/jpeg"); } } if (Build.VERSION.SDK_INT >= 24) { try { intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(getParentActivity(), ApplicationLoader.getApplicationId() + ".provider", file)); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } catch (Exception ignore) { intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); } } else { intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); } getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString(R.string.ShareFile)), 500); } } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); updateSelectedMessageReactions(); } 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(R.string.ForwardsRestrictedInfoChannel); } else { str = LocaleController.getString(R.string.ForwardsRestrictedInfoGroup); } } else { str = LocaleController.getString(R.string.ForwardsRestrictedInfoBot); } if (fromActionBar) { if (fwdRestrictedTopHint == null) { SizeNotifierFrameLayout frameLayout = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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 = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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(actionsButtonsLayout.getForwardButton(), 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.isTodo()) { hasPoll = 3; } else if (messageObject.isPoll()) { hasPoll = messageObject.isPublicPoll() ? 2 : 1; if (hasPoll == 2) { break; } } else if (messageObject.isInvoice()) { hasInvoice = true; } } if (hasPoll == 2) { break; } } if (selectionReactionsOverlay != null && selectionReactionsOverlay.isVisible()) { selectionReactionsOverlay.setHiddenByScroll(true); } Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); args.putInt("messagesCount", canForwardMessagesCount); args.putInt("hasPoll", hasPoll); args.putBoolean("hasInvoice", hasInvoice); args.putBoolean("canSelectTopics", true); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } public 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 { View text = bottomOverlayLinks ? bottomOverlayLinksText : bottomOverlayChatText; 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(text, View.SCALE_X, 1.0f), ObjectAnimator.ofFloat(text, View.SCALE_Y, 1.0f), ObjectAnimator.ofFloat(text, 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 { (bottomOverlayLinks ? bottomOverlayLinksText : 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 || bottomOverlayLinks ? View.INVISIBLE : View.VISIBLE); bottomOverlayLinksText.setVisibility(show || !bottomOverlayLinks ? View.INVISIBLE : View.VISIBLE); bottomOverlayChatText.setScaleX(show || bottomOverlayLinks ? 0.1f : 1.0f); bottomOverlayLinksText.setScaleX(show || !bottomOverlayLinks ? 0.1f : 1.0f); bottomOverlayChatText.setScaleY(show || bottomOverlayLinks ? 0.1f : 1.0f); bottomOverlayLinksText.setScaleY(show || !bottomOverlayLinks ? 0.1f : 1.0f); bottomOverlayChatText.setAlpha(show || bottomOverlayLinks ? 0.0f : 1.0f); bottomOverlayLinksText.setAlpha(show || !bottomOverlayLinks ? 0.0f : 1.0f); } } private void sendBotInlineResult(TLRPC.BotInlineResult result, boolean notify, int scheduleDate, long stars) { 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(), null, replyingQuote, notify, scheduleDate, 0, quickReplyShortcut, getQuickReplyId(), stars); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); getMediaDataController().increaseInlineRating(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; } } public 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.getPosition(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(), AlertDialog.ALERT_TYPE_SPINNER, themeDelegate); progressDialog.setOnCancelListener(postponedScrollCancelListener); progressDialog.showDelayed(1000); postponedScrollToLastMessageQueryIndex = lastLoadIndex; fakePostponedScroll = false; 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++, isTopic); floatingDateView.setAlpha(0.0f); floatingDateView.setTag(null); floatingTopicViewAlpha = 0.0f; updateFloatingTopicView(); floatingTopicSeparator.setTag(null); } } private boolean approved; public void processInlineBotWebView(TLRPC.TL_inlineBotWebView object) { final Runnable open = () -> { final TLRPC.User bot = mentionContainer.getAdapter().getFoundContextBot(); final WebViewRequestProps props = WebViewRequestProps.of(currentAccount, currentUser != null ? currentUser.id : currentChat.id, bot.id, object.text, object.url, BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON, 0, getSendMonoForumPeerId(), false, null, false, null, null, BotWebViewSheet.FLAG_FROM_INLINE_SWITCH, false, false); if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(props) != null) { return; } final String restriction_reason = bot == null ? null : MessagesController.getInstance(currentAccount).getRestrictionReason(bot.restriction_reason); if (!TextUtils.isEmpty(restriction_reason)) { MessagesController.getInstance(currentAccount).showCantOpenAlert(this, restriction_reason); return; } // if (AndroidUtilities.isTablet() || true) { BotWebViewSheet webViewSheet = new BotWebViewSheet(getContext(), getResourceProvider()); webViewSheet.setDefaultFullsize(false); webViewSheet.setNeedsContext(true); webViewSheet.setParentActivity(getParentActivity()); webViewSheet.requestWebView(ChatActivity.this, props); webViewSheet.show(); // } else { // BotWebViewAttachedSheet webViewSheet = createBotViewer(); // webViewSheet.setDefaultFullsize(false); // webViewSheet.setNeedsContext(true); // webViewSheet.setParentActivity(getParentActivity()); // webViewSheet.requestWebView(ChatActivity.this, props); // webViewSheet.show(); // } }; if (approved) { open.run(); } else { WebAppDisclaimerAlert.show(getContext(), ignored -> { approved = true; open.run(); }, null, 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 || getContext() == null) { return; } if (chatAttachAlert == null) { chatAttachAlert = new ChatAttachAlert(getParentActivity(), this, false, false, true, themeDelegate) { @Override public void dismissInternal() { if (chatAttachAlert != null && chatAttachAlert.isShowing()) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } super.dismissInternal(); onEditTextDialogClose(false, true); } @Override public void onDismissAnimationStart() { if (chatAttachAlert != null) { chatAttachAlert.setFocusable(false); } if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { 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, int scheduleRepeatPeriod, long effectId, boolean invertMedia, boolean forceDocument, long payStars) { if (getParentActivity() == null || chatAttachAlert == null) { return; } editingMessageObject = chatAttachAlert.getEditingMessageObject(); if (editingMessageObject != null && editingMessageObject.messageOwner != null) { editingMessageObject.messageOwner.invert_media = invertMedia; } if (button == 8 || button == 7 || button == 4 && !chatAttachAlert.getPhotoLayout().getSelectedPhotos().isEmpty()) { if (chatAttachAlert != null && button != 8) { chatAttachAlert.dismiss(true); } final HashMap selectedPhotos = chatAttachAlert.getPhotoLayout().getSelectedPhotos(); final ArrayList selectedPhotosOrder = chatAttachAlert.getPhotoLayout().getSelectedPhotosOrder(); if (!selectedPhotos.isEmpty()) { final int albumsCount = (int) Math.ceil(selectedPhotos.size() / 10f); for (int i = 0; i < albumsCount; ++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; if (photoEntry.highQuality) { info.originalPhotoEntry = photoEntry.clone(); } } else if (photoEntry.path != null) { info.path = photoEntry.path; } info.thumbPath = photoEntry.thumbPath; info.coverPath = photoEntry.coverPath; info.coverPhoto = photoEntry.coverPhoto; 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; info.updateStickersOrder = SendMessagesHelper.checkUpdateStickersOrder(photoEntry.caption); info.hasMediaSpoilers = photoEntry.hasSpoiler; info.stars = photoEntry.starsAmount; info.highQuality = photoEntry.highQuality; photos.add(info); photoEntry.reset(); } boolean updateStickersOrder = false; if (i == 0) { fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); updateStickersOrder = photos.get(0).updateStickersOrder; } if (editingMessageObject != null && editingMessageObject.needResendWhenEdit()) { MessageSuggestionParams params = messageSuggestionParams != null ? messageSuggestionParams : MessageSuggestionParams.of(editingMessageObject.messageOwner.suggested_post); SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, editingMessageObject, getThreadMessage(), null, replyingQuote, button == 4 || forceDocument, arg, null, notify, scheduleDate, scheduleRepeatPeriod, chatMode, updateStickersOrder, null, quickReplyShortcut, getQuickReplyId(), effectId, invertMedia, payStars, getSendMonoForumPeerId(), params); } else { SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate, scheduleRepeatPeriod, chatMode, updateStickersOrder, null, quickReplyShortcut, getQuickReplyId(), effectId, invertMedia, payStars, getSendMonoForumPeerId(), messageSuggestionParams); } } 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) { String username = UserObject.getPublicUsername(user); if (chatActivityEnterView == null || user == null || TextUtils.isEmpty(username)) { return; } chatActivityEnterView.setFieldText("@" + 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(), 200); if (reset) { openKeyboardOnAttachMenuClose = false; } } if (resetAdjust && !isInsideContainer) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } public void doOnIdle(Runnable runnable) { NotificationCenter.getInstance(currentAccount).doOnIdle(runnable); } public void performHistoryClear(boolean revoke, boolean canDeleteHistory) { final long threadId = getThreadId(); performHistoryClear(threadId, revoke, canDeleteHistory); } public void performHistoryClear(long threadId, boolean revoke, boolean canDeleteHistory) { setClearingHistory(threadId, true); createUndoView(); if (undoView == null) { return; } 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); } if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { if (threadId != 0) { getMessagesStorage().removeTopic(-currentChat.id, threadId); getMessagesController().deleteSavedDialog(threadId, getMessagesController().getInputPeer(-currentChat.id)); getMessagesController().getTopicsController().onTopicsDeletedServerSide(currentChat.id, threadId); } } else { getMessagesController().deleteDialog(dialog_id, 1, revoke); } setClearingHistory(threadId, false); if (threadId == getThreadId()) { clearHistory(false, null); chatAdapter.notifyDataSetChanged(); } }, () -> { setClearingHistory(threadId, false); if (threadId == getThreadId()) { 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; } @Nullable public UndoView getUndoView() { createUndoView(); return undoView; } public long getMergeDialogId() { return mergeDialogId; } public boolean hasReportSpam() { return topChatPanelView != null && topChatPanelView.getTag() == null && reportSpamButton.getVisibility() != View.GONE; } public void setChatInvite(TLRPC.ChatInvite invite) { chatInvite = invite; } public void setBotUser(String value) { if (inlineReturn != 0) { getMessagesController().sendBotStart(currentUser, value); } else { sentBotStart = true; getMessagesController().sendBotStart(currentUser, botUser = value); updateBottomOverlay(); } } private void afterMessageSend() { messageSuggestionParams = null; if (threadMessageId == 0 || isTopic) { if (isTopic) { replyingMessageObject = threadMessageObject; } else { replyingMessageObject = null; } replyingQuote = null; if (chatActivityEnterView != null) { chatActivityEnterView.setReplyingMessageObject(null, null); } } hideFieldPanel(false); if (chatMode == 0) { getMediaDataController().cleanDraft(dialog_id, threadMessageId, true); } } private void toggleMesagesSearchListView() { if (messagesSearchListContainer != null) { showMessagesSearchListView(messagesSearchListContainer.getTag() == null); } } private void showMessagesSearchListView(boolean show) { if (messagesSearchListContainer == null || show && messagesSearchListContainer.getTag() != null || !show && messagesSearchListContainer.getTag() == null) { return; } if (messagesSearchListViewAnimation != null) { messagesSearchListViewAnimation.cancel(); messagesSearchListViewAnimation = null; } if (show) { messagesSearchListContainer.setVisibility(View.VISIBLE); } if (!show && chatMode == MODE_SEARCH) { LinearLayoutManager messagesSearchLayoutManager = (LinearLayoutManager) messagesSearchListView.getLayoutManager(); Object item = messagesSearchAdapter.getItem((messagesSearchLayoutManager.findFirstVisibleItemPosition() + messagesSearchLayoutManager.findLastVisibleItemPosition()) / 2); Object firstItem = messagesSearchAdapter.getItem(messagesSearchLayoutManager.findFirstVisibleItemPosition()); Object lastItem = messagesSearchAdapter.getItem(messagesSearchLayoutManager.findLastVisibleItemPosition()); if (item != null && firstItem != null && lastItem != null) { ArrayList messages = chatAdapter.getMessages(); int chatFirstItemPosition = chatLayoutManager.findFirstVisibleItemPosition(); int chatLastItemPosition = chatLayoutManager.findLastVisibleItemPosition(); int messageId = ((MessageObject) item).messageOwner.id; boolean firstItemVisible = false; int firstItemMid = ((MessageObject) firstItem).messageOwner.id; boolean lastItemVisible = false; int lastItemMid = ((MessageObject) lastItem).messageOwner.id; int messageIndex = -1; for (int i = 0; i < messages.size(); i++) { if (messages.get(i).messageOwner.id == firstItemMid) { int firstMessagePosition = chatAdapter.messagesStartRow + i; firstItemVisible = chatFirstItemPosition <= firstMessagePosition && chatLastItemPosition >= firstMessagePosition; if (firstItemVisible) { break; } } if (messages.get(i).messageOwner.id == lastItemMid) { int lastMessagePosition = chatAdapter.messagesStartRow + i; lastItemVisible = chatFirstItemPosition <= lastMessagePosition && chatLastItemPosition >= lastMessagePosition; if (lastItemVisible) { break; } } if (messages.get(i).messageOwner.id == messageId) { messageIndex = i; } } if (!firstItemVisible && !lastItemVisible && messageIndex != -1) { int messageHeight = getHeightForMessage(messages.get(messageIndex), true); int offset = (chatListView.getHeight() - messageHeight) / 2; chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messageIndex, offset); } } } messagesSearchListContainer.setTag(show ? 1 : null); messagesSearchListContainer.setPadding(0, (actionBarSearchTags != null && actionBarSearchTags.shown() ? actionBarSearchTags.getHeight() : 0), 0, getHashtagTabsHeight()); messagesSearchListViewAnimation = new AnimatorSet(); messagesSearchListViewAnimation.playTogether(ObjectAnimator.ofFloat(messagesSearchListContainer, 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) { messagesSearchListContainer.setVisibility(View.GONE); } } } @Override public void onAnimationCancel(Animator animation) { if (animation.equals(messagesSearchListViewAnimation)) { messagesSearchListViewAnimation = null; } } }); messagesSearchListViewAnimation.start(); if (searchExpandList != null) { searchExpandList.setText(LocaleController.getString(messagesSearchListContainer != null && messagesSearchListContainer.getTag() != null ? R.string.SearchAsChat : R.string.SearchAsList), !LocaleController.isRTL); } hideHints(); updateSearchCountText(); } 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() { openScheduledMessages(0, false); } private void openScheduledMessages(int fromMessageId, boolean showConvertToast) { 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); if (showConvertToast) { bundle.putInt("converting_toast_from", fromMessageId); bundle.putBoolean("converting_toast", true); } ChatActivity fragment = new ChatActivity(bundle); if (isTopic) { ForumUtilities.applyTopic(fragment, MessagesStorage.TopicKey.of(getDialogId(), getTopicId())); } fragment.chatActivityDelegate = new ChatActivityDelegate() { @Override public void openReplyMessage(int mid) { scrollToMessageId(mid, 0, true, 0, true, 0); } @Override public void openHashtagSearch(String text) { ChatActivity.this.openHashtagSearch(text); } }; presentFragment(fragment, false); } public void shareMyContact(int type, MessageObject messageObject) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString(R.string.ShareYouPhoneNumberTitle)); if (currentUser != null) { if (currentUser.bot) { builder.setMessage(LocaleController.getString(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(R.string.AreYouSureShareMyContactInfo)); } builder.setPositiveButton(LocaleController.getString(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.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(getUserConfig().getCurrentUser(), dialog_id, messageObject, getThreadMessage(), null, null, true, 0, 0); params.quick_reply_shortcut_id = getQuickReplyId(); params.quick_reply_shortcut = quickReplyShortcut; SendMessagesHelper.getInstance(currentAccount).sendMessage(params); if (chatMode == 0) { moveScrollToLastMessage(false); } hideFieldPanel(false); } }); builder.setNegativeButton(LocaleController.getString(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 || isInPreviewMode()) { return; } if (voiceHintTextView == null) { SizeNotifierFrameLayout frameLayout = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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(R.string.HoldToVideo) : LocaleController.getString(R.string.HoldToAudio)); } else { voiceHintTextView.setText(LocaleController.getString(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; } public boolean checkSlowModeAlert() { CharSequence time = chatActivityEnterView.getSlowModeTimer(); if (time != null) { new AlertDialog.Builder(getContext()) .setTitle(LocaleController.getString(R.string.Slowmode)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("SlowModeHint", R.string.SlowModeHint, time))) .setPositiveButton(LocaleController.getString(R.string.OK), null) .show(); return false; } return true; } private void hideHints(boolean scroll) { if (!scroll) { if (slowModeHint != null) { slowModeHint.hide(); } if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } if (scheduledHint != null) { scheduledHint.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(); } if (bottomGiftHintView != null) { bottomGiftHintView.hide(); } if (bottomSuggestHintView != null) { bottomSuggestHintView.hide(); } } private void hideSendButtonHints() { if (scheduledOrNoSoundHint != null) { scheduledOrNoSoundHint.hide(); } if (scheduledHint != null) { scheduledHint.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 showScheduledHint() { boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); if (scheduledHintShown || scheduledOrNoSoundHintShown || disableNoSound || SharedConfig.scheduledHintShows >= 3 || chatActivityEnterView.isEditingMessage()) { return; } AndroidUtilities.cancelRunOnUIThread(showScheduledHintRunnable); AndroidUtilities.runOnUIThread(showScheduledHintRunnable, 4000); } private void showScheduledOrNoSoundHint() { boolean disableNoSound = UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0 || chatMode == MODE_EDIT_BUSINESS_LINK; long scheduledOrNoSoundHintTimeFromLastSeen = System.currentTimeMillis() - SharedConfig.scheduledOrNoSoundHintSeenAt; long scheduledHintTimeFromLastSeen = System.currentTimeMillis() - SharedConfig.scheduledHintSeenAt; if (disableNoSound || SharedConfig.scheduledOrNoSoundHintShows >= 3 || scheduledOrNoSoundHintTimeFromLastSeen < 86400000L || scheduledHintTimeFromLastSeen < 86400000L || chatActivityEnterView.isEditingMessage()) { 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 = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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.canSendVoice(currentChat) && !ChatObject.canSendRoundVideo(currentChat)) { if (checkCanRemoveRestrictionsByBoosts()) { return; } if (chatActivityEnterView.isInVideoMode()) { mediaBanTooltip.setText(ChatObject.getRestrictedErrorText(currentChat, ChatObject.ACTION_SEND_ROUND)); } else { mediaBanTooltip.setText(ChatObject.getRestrictedErrorText(currentChat, ChatObject.ACTION_SEND_VOICE)); } } else if (ChatObject.isActionBannedByDefault(currentChat, ChatObject.ACTION_SEND_VOICE)) { mediaBanTooltip.setText(LocaleController.getString(R.string.GlobalAttachVoiceRestricted)); } else if (ChatObject.isActionBannedByDefault(currentChat, ChatObject.ACTION_SEND_ROUND)) { mediaBanTooltip.setText(LocaleController.getString(R.string.GlobalAttachRoundRestricted)); } else if (ChatObject.isActionBannedByDefault(currentChat, ChatObject.ACTION_SEND_MEDIA)) { mediaBanTooltip.setText(LocaleController.getString(R.string.GlobalAttachMediaRestricted)); } else { if (currentChat.banned_rights == null) { return; } if (AndroidUtilities.isBannedForever(currentChat.banned_rights)) { mediaBanTooltip.setText(LocaleController.getString(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 = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); if (index == -1) { return; } noSoundHintView = new HintView(getParentActivity(), HintView.TYPE_NOSOUND, 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 = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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 = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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 = true; // 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(); } public boolean showEmojiHint() { if (chatActivityEnterView == null || chatActivityEnterView.getVisibility() != View.VISIBLE) { return false; } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); int moreemojihint; if ((moreemojihint = preferences.getInt("moreemojihint", 0)) > 3 && UserConfig.getInstance(currentAccount).isPremium()) { return false; } if (UserConfig.getInstance(currentAccount).isPremium()) { preferences.edit().putInt("moreemojihint", moreemojihint + 1).commit(); } if (getParentActivity() == null || fragmentView == null || emojiHintTextView != null) { return false; } if (!allowContextBotPanelSecond) { if (chatActivityEnterView != null) { chatActivityEnterView.setOpenGifsTabFirst(); } return false; } SizeNotifierFrameLayout frameLayout = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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)); emojiHintTextView = new HintView(getParentActivity(), 9, themeDelegate); final String emojiPlaceholder = "<>"; String textString = LocaleController.formatString("TapHereEmoji", R.string.TapHereEmoji, emojiPlaceholder); SpannableStringBuilder text = new SpannableStringBuilder(textString); int i = textString.indexOf(emojiPlaceholder); if (i >= 0) { SpannableString emoji = new SpannableString("x"); Drawable emojiDrawable = getContext().getResources().getDrawable(R.drawable.smiles_tab_smiles).mutate(); emojiDrawable.setBounds(0, 0, AndroidUtilities.dp(20), AndroidUtilities.dp(20)); emojiDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_gifSaveHintText), PorterDuff.Mode.MULTIPLY)); emoji.setSpan(new ImageSpan(emojiDrawable, ImageSpan.ALIGN_BOTTOM), 0, emoji.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); text.replace(i, i + emojiPlaceholder.length(), emoji); emojiHintTextView.textView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(0), AndroidUtilities.dp(8), AndroidUtilities.dp(6)); } emojiHintTextView.setText(text); frameLayout.addView(emojiHintTextView, 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(emojiHintTextView, View.ALPHA, 0.0f, 1.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { AndroidUtilities.runOnUIThread(() -> { if (emojiHintTextView == null) { return; } AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( ObjectAnimator.ofFloat(emojiHintTextView, View.ALPHA, 0.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (emojiHintTextView != null) { emojiHintTextView.setVisibility(View.GONE); frameLayout.removeView(emojiHintTextView); emojiHintTextView = null; } } }); AnimatorSet.setDuration(300); AnimatorSet.start(); }, 2000); } }); AnimatorSet.setDuration(300); AnimatorSet.start(); View emojiButton = chatActivityEnterView.getEmojiButton(); if (emojiButton != null) { emojiHintTextView.showForView(emojiButton, true); } return true; } 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 = contentView; int index = frameLayout.indexOfChild(chatInputViewsContainer); 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, 37, 0, 0, 27)); gifHintTextView = new HintView(getParentActivity(), 9, themeDelegate); gifHintTextView.setText(LocaleController.getString(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 && messageSuggestionParams != null) { chatAttachAlert.setMaxSelectedPhotos(1, true); } else if (currentChat != null && !ChatObject.hasAdminRights(currentChat) && currentChat.slowmode_enabled) { chatAttachAlert.setMaxSelectedPhotos(10, true); } else { chatAttachAlert.setMaxSelectedPhotos(-1, true); } chatAttachAlert.enableDefaultMode(); chatAttachAlert.init(); chatAttachAlert.getCommentView().setText(chatActivityEnterView.getFieldText()); chatAttachAlert.parentThemeDelegate = themeDelegate; showDialog(chatAttachAlert); } public void openAttachMenuForCreatingSticker() { ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(null); if (getParentActivity() == null) { return; } createChatAttachView(); chatAttachAlert.getPhotoLayout().loadGalleryPhotos(); if (Build.VERSION.SDK_INT == 21 || Build.VERSION.SDK_INT == 22) { chatActivityEnterView.closeKeyboard(); } chatAttachAlert.setMaxSelectedPhotos(1, false); chatAttachAlert.setOpenWithFrontFaceCamera(true); chatAttachAlert.enableStickerMode(null); chatAttachAlert.init(); chatAttachAlert.parentThemeDelegate = themeDelegate; if (visibleDialog != null) { chatAttachAlert.show(); } else { showDialog(chatAttachAlert); } } private void showFloatingDateView(boolean scroll) { if (floatingDateView == null || chatMode == MODE_QUICK_REPLIES) { 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; } } private void showFloatingTopicView(boolean scroll) { if (floatingTopicSeparator == null || chatMode == MODE_QUICK_REPLIES) { return; } if (floatingTopicSeparator.getTag() == null) { if (floatingTopicAnimation != null) { floatingTopicAnimation.cancel(); } floatingTopicSeparator.setTag(1); floatingTopicAnimation = ValueAnimator.ofFloat(floatingTopicViewAlpha, 1.0f); floatingTopicAnimation.setDuration(150); floatingTopicAnimation.addUpdateListener(anm -> { floatingTopicViewAlpha = (float) anm.getAnimatedValue(); updateFloatingTopicView(); }); floatingTopicAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(floatingTopicAnimation)) { floatingTopicViewAlpha = 1.0f; updateFloatingTopicView(); floatingTopicAnimation = null; } } }); floatingTopicAnimation.start(); } if (!scroll) { invalidateMessagesVisiblePart(); hideDateDelay = 1000; } } private void updateFloatingTopicView() { if (floatingTopicSeparator == null) return; floatingTopicSeparator.setTranslationX(getSideMenuWidth() / 2f); floatingTopicSeparator.setTranslationY(chatListView.getTranslationY() + chatListViewPaddingTop + floatingTopicViewOffset - dp(4) + dp(28)); final float alpha = Utilities.clamp(AndroidUtilities.ilerp(floatingTopicViewOffset, -floatingTopicSeparator.getHeight(), 0f), 1f, 0f); floatingTopicSeparator.setAlpha(floatingTopicViewAlpha * alpha); final float scale = lerp(0.5f, 1f, alpha); floatingTopicSeparator.setScaleX(scale); floatingTopicSeparator.setScaleY(scale); } private void hideFloatingTopicView(boolean animated) { if (floatingTopicSeparator.getTag() != null && !currentFloatingTopicOnScreen && (!scrollingFloatingTopic || currentFloatingTopIsNotMessage)) { floatingTopicSeparator.setTag(null); if (animated) { floatingTopicAnimation = ValueAnimator.ofFloat(floatingTopicViewAlpha, 0.0f); floatingTopicAnimation.setDuration(150); floatingTopicAnimation.addUpdateListener(anm -> { floatingTopicViewAlpha = (float) anm.getAnimatedValue(); updateFloatingTopicView(); }); floatingTopicAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(floatingTopicAnimation)) { floatingTopicViewAlpha = 0.0f; updateFloatingTopicView(); floatingTopicAnimation = null; } } }); floatingTopicAnimation.setStartDelay(hideDateDelay); floatingTopicAnimation.start(); } else { if (floatingTopicAnimation != null) { floatingTopicAnimation.cancel(); floatingTopicAnimation = null; } floatingTopicViewAlpha = 0.0f; updateFloatingTopicView(); } hideDateDelay = 500; } } private boolean removingFromParent; @Override public void onRemoveFromParent() { removingFromParent = true; MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null && messageObject.isVideo()) { MediaController.getInstance().cleanupPlayer(true, true); } else { MediaController.getInstance().setTextureView(videoTextureView, null, null, false); } if (starReactionsOverlay != null) { starReactionsOverlay.setMessageCell(null); AndroidUtilities.removeFromParent(starReactionsOverlay); starReactionsOverlay = null; } super.onRemoveFromParent(); } protected void setIgnoreAttachOnPause(boolean value) { ignoreAttachOnPause = value; } public ChatActivityEnterView getChatActivityEnterViewForStickers() { return bottomChannelButtonsLayout.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 || waitingForGetDifference) { return; } int firstVisibleItem = RecyclerListView.NO_POSITION; int lastVisibleItem = RecyclerListView.NO_POSITION; int visibleItemCount = 0; for (int i = 0; i < chatListView.getChildCount(); i++) { int position = chatListView.getChildAdapterPosition(chatListView.getChildAt(i)); if (position != RecyclerListView.NO_POSITION) { if (firstVisibleItem == RecyclerListView.NO_POSITION || position < firstVisibleItem) { firstVisibleItem = position; } if (lastVisibleItem == RecyclerListView.NO_POSITION || position > lastVisibleItem) { lastVisibleItem = position; } visibleItemCount++; } } if (chatAdapter.isFiltered) { if (chatAdapter.loadingUpRow >= 0 && firstVisibleItem >= 0 && chatAdapter.loadingUpRow >= firstVisibleItem && chatAdapter.loadingUpRow <= lastVisibleItem) { getMediaDataController().loadMoreSearchMessages(false); } return; } final int firstVisibleItemFinal = firstVisibleItem; final int visibleItemCountFinal = visibleItemCount; int totalItemCount = chatAdapter.getItemCount(); int checkLoadCount; if (scroll) { checkLoadCount = 25; } else { checkLoadCount = 5; } if (chatMode == MODE_SEARCH) { if (totalItemCount - firstVisibleItemFinal - visibleItemCountFinal <= checkLoadCount && !loading) { if (!endReached[0]) { loading = true; waitingForLoad.add(lastLoadIndex); HashtagSearchController.getInstance(currentAccount).searchHashtag(searchingHashtag, classGuid, searchType, lastLoadIndex++); } } return; } AndroidUtilities.runOnUIThread(() -> { if (totalItemCount - firstVisibleItemFinal - visibleItemCountFinal <= 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++, isTopic); } else { getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 50, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } 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++, isTopic); } } if (visibleItemCountFinal > 0 && !loadingForward && firstVisibleItemFinal <= 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++, isTopic); 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++, isTopic); 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) { final Activity activity = getParentActivity(); if (Build.VERSION.SDK_INT >= 33) { if (activity.checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) { try { getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO}, BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE); } catch (Throwable ignore) {} return; } } else if (Build.VERSION.SDK_INT >= 23) { if (activity.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 { 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, false, quiz); pollCreateActivity.setDelegate((poll, params, notify, scheduleDate) -> { if (checkSlowModeAlert()) { SendMessagesHelper.SendMessageParams params2 = SendMessagesHelper.SendMessageParams.of(poll, dialog_id, replyingMessageObject, getThreadMessage(), null, params, notify, scheduleDate, 0); params2.quick_reply_shortcut = quickReplyShortcut; params2.quick_reply_shortcut_id = getQuickReplyId(); getSendMessagesHelper().sendMessage(params2); afterMessageSend(); } }); presentFragment(pollCreateActivity); } @Override public void didSelectFiles(ArrayList files, String caption, ArrayList captionEntities, ArrayList fmessages, boolean notify, int scheduleDate, int scheduleRepeatPeriod, long effectId, boolean invertMedia, long payStars) { fillEditingMediaWithCaption(caption, null); if (checkSlowModeAlert()) { if (!fmessages.isEmpty() && !TextUtils.isEmpty(caption)) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(caption, dialog_id, null, null, null, true, captionEntities, null, null, true, 0, 0, null, false); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.invert_media = invertMedia; params.payStars = payStars; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; SendMessagesHelper.getInstance(currentAccount).sendMessage(params); caption = null; } getSendMessagesHelper().sendMessage(fmessages, dialog_id, false, false, true, 0, 0, null, -1, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, caption, captionEntities, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, editingMessageObject, notify, scheduleDate, scheduleRepeatPeriod, null, quickReplyShortcut, getQuickReplyId(), effectId, invertMedia, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); afterMessageSend(); } } @Override public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate, int scheduleRepeatPeriod, long payStars) { fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, true, false, editingMessageObject, notify, scheduleDate, scheduleRepeatPeriod, chatMode, photos.get(0).updateStickersOrder, null, quickReplyShortcut, getQuickReplyId(), 0, false, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); 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; } if (!checkSlowModeAlert()) { 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.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(photos.get(0).caption, dialog_id, replyingMessageObject, getThreadMessage(), null, false, photos.get(0).entities, null, null, notify, scheduleDate, 0, null, false); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); SendMessagesHelper.getInstance(currentAccount).sendMessage(params); } 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(), null, replyingQuote, notify, scheduleDate, 0, quickReplyShortcut, getQuickReplyId(), 0); 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, replyingQuote, false, true, editingMessageObject, notify, scheduleDate, 0, chatMode, photos.get(0).updateStickersOrder, null, quickReplyShortcut, getQuickReplyId(), 0, false, 0, getSendMonoForumPeerId(), messageSuggestionParams); 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); 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 && dialog != chatThemeBottomSheet && !(dialog instanceof BotWebViewSheet) && super.dismissDialogOnPause(dialog); } int waitingForWebpageId; private void cancelSearchLinks() { if (linkSearchRequestId != 0) { getConnectionsManager().cancelRequest(linkSearchRequestId, true); } } private void editResetMediaManual() { if (editingMessageObject != null && editingMessageObject.messageOwner != null && editingMessageObject.messageOwner.media != null) { editingMessageObject.messageOwner.media.manual = false; } } public void checkEditLinkRemoved(final CharSequence charSequence) { final boolean manual = editingMessageObject != null && editingMessageObject.messageOwner != null && editingMessageObject.messageOwner.media != null && editingMessageObject.messageOwner.media.webpage != null && !(editingMessageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPageEmpty) && editingMessageObject.messageOwner.media.manual; if (messagePreviewParams != null && editingMessageObject != null && (editingMessageObject.type == MessageObject.TYPE_TEXT || editingMessageObject.type == MessageObject.TYPE_EMOJIS) && foundWebPage != null) { if (messagePreviewParams.hasLink(charSequence, foundWebPage.url)) { return; } if (manual) { foundWebPage = null; if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(null, true); } if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } editResetMediaManual(); fallbackFieldPanel(); } } } public void searchLinks(final CharSequence charSequence, final boolean force) { if (currentEncryptedChat != null && getMessagesController().secretWebpagePreview == 0 || editingMessageObject != null && (!editingMessageObject.isWebpage() || editingMessageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPagePending)) { return; } if (currentChat != null && !ChatObject.canSendEmbed(currentChat)) { if (foundWebPage != null) { foundWebPage = null; if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(null, true); } fallbackFieldPanel(); editResetMediaManual(); } return; } checkEditLinkRemoved(charSequence); 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 == '/')) { if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } return; } } pendingLinkSearchString = null; foundUrls = null; foundWebPage = null; if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(null, true); } fallbackFieldPanel(); editResetMediaManual(); } final MessagesController messagesController = getMessagesController(); Utilities.searchQueue.postRunnable(() -> { boolean requestAnyway = false; if (linkSearchRequestId != 0) { getConnectionsManager().cancelRequest(linkSearchRequestId, true); linkSearchRequestId = 0; requestAnyway = true; } 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 && !requestAnyway) { return; } } foundUrls = urls; if (urls == null) { AndroidUtilities.runOnUIThread(() -> { foundWebPage = null; fallbackFieldPanel(); }); 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(() -> { foundWebPage = null; fallbackFieldPanel(); }); return; } textToCheck = charSequence; } final String firstUrl = urls == null || urls.isEmpty() ? null : urls.get(0).toString(); if (currentEncryptedChat != null && messagesController.secretWebpagePreview == 2) { AndroidUtilities.runOnUIThread(() -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString(R.string.AppName)); builder.setPositiveButton(LocaleController.getString(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(R.string.Cancel), null); builder.setMessage(LocaleController.getString(R.string.SecretLinkPreviewAlert)); showDialog(builder.create()); messagesController.secretWebpagePreview = 0; MessagesController.getGlobalMainSettings().edit().putInt("secretWebpage2", messagesController.secretWebpagePreview).commit(); }); return; } final TL_account.getWebPagePreview req = new TL_account.getWebPagePreview(); if (textToCheck instanceof String) { req.message = (String) textToCheck; } else { req.message = textToCheck.toString(); } if (foundWebPage != null && req.message.equals(foundWebPage.displayedText)) { return; } final int myId = ++waitingForWebpageId; requestLinkPreviewCached(req, (success, webpage) -> AndroidUtilities.runOnUIThread(() -> { if (waitingForWebpageId != myId) { return; } if (success) { foundWebPage = webpage; foundWebPage.display_url = req.message; 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; } if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } showFieldPanelForWebPage(true, foundWebPage, false); } else { if (foundWebPage != null) { foundWebPage = null; if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } fallbackFieldPanel(); } } } else { foundWebPage = null; fallbackFieldPanel(); } })); }); } private HashMap lastLinkPreviewResults; private void requestLinkPreviewCached(TL_account.getWebPagePreview req, Utilities.Callback2 done) { if (lastLinkPreviewResults == null) { lastLinkPreviewResults = new HashMap<>(); } TLRPC.WebPage result = lastLinkPreviewResults.get(req.message); if (result != null) { done.run(true, result); } else { requestLinkPreview(req, (success, webpage) -> { if (success && !(webpage instanceof TLRPC.TL_webPagePending)) { Iterator keys = lastLinkPreviewResults.keySet().iterator(); while (keys.hasNext() && lastLinkPreviewResults.size() > 5) { keys.next(); keys.remove(); } lastLinkPreviewResults.put(req.message, webpage); } done.run(success, webpage); }); } } private void requestLinkPreview(TL_account.getWebPagePreview req, Utilities.Callback2 done) { cancelSearchLinks(); linkSearchRequestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { linkSearchRequestId = 0; TLRPC.TL_messageMediaWebPage media = null; if (response instanceof TL_account.webPagePreview) { final TL_account.webPagePreview preview = (TL_account.webPagePreview) response; getMessagesController().putUsers(preview.users, false); getMessagesController().putChats(preview.chats, false); if (preview.media instanceof TLRPC.TL_messageMediaWebPage) { media = (TLRPC.TL_messageMediaWebPage) preview.media; } } if (media != null) { if (media.webpage != null && "telegram_story".equals(media.webpage.type)) { TLRPC.TL_webPageAttributeStory _attrStory = null; if (media.webpage.attributes != null) { for (int i = 0; i < media.webpage.attributes.size(); ++i) { if (media.webpage.attributes.get(i) instanceof TLRPC.TL_webPageAttributeStory) { _attrStory = (TLRPC.TL_webPageAttributeStory) media.webpage.attributes.get(i); break; } } } if (_attrStory == null) { done.run(false, null); return; } if (_attrStory != null && _attrStory.storyItem != null) { done.run(true, media.webpage); return; } final TLRPC.TL_webPageAttributeStory attrStory = _attrStory; final TLRPC.TL_messageMediaWebPage finalMedia = media; getMessagesStorage().getStorageQueue().postRunnable(() -> { try { LongSparseArray> array = new LongSparseArray<>(); TLRPC.TL_message message = new TLRPC.TL_message(); message.message = ""; message.id = 0; message.media = finalMedia; ArrayList list = new ArrayList<>(); list.add(new MessageObject(currentAccount, message, false, false)); array.put(DialogObject.getPeerDialogId(attrStory.peer), list); getMessagesController().getStoriesController().getStoriesStorage().fillMessagesWithStories(array, () -> { MessageObject result = null; if (array.size() == 1 && array.valueAt(0) != null && array.valueAt(0).size() == 1) { result = array.valueAt(0).get(0); } if (result != null && result.messageOwner != null && result.messageOwner.media != null && result.messageOwner.media.webpage != null && result.messageOwner.media.webpage.attributes != null) { for (int i = 0; i < result.messageOwner.media.webpage.attributes.size(); ++i) { TLRPC.WebPageAttribute attr = result.messageOwner.media.webpage.attributes.get(i); if (attr instanceof TLRPC.TL_webPageAttributeStory) { if (((TLRPC.TL_webPageAttributeStory) attr).storyItem != null) { final TLRPC.WebPage webpage = result.messageOwner.media.webpage; AndroidUtilities.runOnUIThread(() -> { done.run(true, webpage); }); return; } } } } AndroidUtilities.runOnUIThread(() -> { done.run(false, null); }); }, classGuid, false, null); } catch (Exception ignore) {} }); } else { done.run(media.webpage != null, media.webpage); } } else { done.run(false, null); } })); getConnectionsManager().bindRequestToGuid(linkSearchRequestId, classGuid); } private void forwardMessages(ArrayList arrayList, boolean fromMyName, boolean hideCaption, boolean notify, int scheduleDate, long payStars) { if (arrayList == null || arrayList.isEmpty()) { return; } if (!checkSlowModeAlert()) { return; } if ((scheduleDate != 0) == (chatMode == MODE_SCHEDULED)) { waitingForSendingMessageLoad = true; } int result = getSendMessagesHelper().sendMessage(arrayList, dialog_id, fromMyName, hideCaption, notify, scheduleDate, 0, getThreadMessage(), -1, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); 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); String tk = isTopic ? dialog_id + "_" + getTopicId() : "" + dialog_id; if (preferences.getInt("answered_" + tk, 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 static class ReplyQuote { public final long peerId; public MessageObject message; public int start, end; public int task_id; public boolean outdated; public boolean todo; public String text; public ArrayList entities; public int offset, length; public TLRPC.TodoItem task; private ReplyQuote(long peerId, @NonNull MessageObject message, int start, int end) { this.peerId = peerId; this.message = message; this.start = start; this.end = end; this.todo = false; this.task_id = -1; update(); } private ReplyQuote(long peerId, @NonNull MessageObject message, int task_id) { this.peerId = peerId; this.message = message; this.start = -1; this.end = -1; this.todo = true; this.task_id = task_id; update(); } public static ReplyQuote from(MessageObject messageObject, String text, int offset) { if (messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.message == null || text == null) { return null; } int start = MessageObject.findQuoteStart(messageObject.messageOwner.message, text, offset); if (start < 0) { return null; } return new ReplyQuote( messageObject.getDialogId(), messageObject, start, start + text.length() ); } public static ReplyQuote from(MessageObject messageObject, int task_id) { if (messageObject == null || messageObject.messageOwner == null || !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaToDo)) { return null; } return new ReplyQuote( messageObject.getDialogId(), messageObject, task_id ); } public static ReplyQuote from(MessageObject messageObject) { if (messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.message == null) { return null; } return from(messageObject, 0, Math.min(MessagesController.getInstance(messageObject.currentAccount).quoteLengthMax, messageObject.messageOwner.message.length())); } public static ReplyQuote from(MessageObject messageObject, int start, int end) { if (messageObject == null) { return null; } return new ReplyQuote( messageObject.getDialogId(), messageObject, start, end ); } private boolean update() { if (message == null || message.messageOwner == null || message.messageOwner.message == null) { FileLog.e("ReplyQuote: message is null"); return false; } if (todo) { final TLRPC.TodoItem foundItem = MessageObject.findTodoItem(message, task_id); if (foundItem == null) { FileLog.e("ReplyQuote: todo task is not found"); return false; } task = foundItem; return true; } else { if (end < start || end > message.messageOwner.message.length() || start > message.messageOwner.message.length() || start < 0 || end < 0) { FileLog.e("ReplyQuote: start/end are invalid (" + start + ", " + end + ", len=" + message.messageOwner.message.length() + ")"); return false; } final String fulltext = message.messageOwner.message; int realStart = Math.max(0, start); while (realStart < end && Character.isWhitespace(fulltext.charAt(realStart))) realStart++; int realEnd = Math.min(end, fulltext.length()); while (realEnd > realStart && Character.isWhitespace(fulltext.charAt(realEnd - 1))) realEnd--; if (realStart == realEnd) { FileLog.e("ReplyQuote: message is full of whitespace"); return false; } text = message.messageOwner.message.substring(realStart, realEnd); if (entities != null) { entities.clear(); } if (message.messageOwner.entities != null && !message.messageOwner.entities.isEmpty()) { for (int i = 0; i < message.messageOwner.entities.size(); ++i) { TLRPC.MessageEntity entity = message.messageOwner.entities.get(i); if (!AndroidUtilities.intersect1dInclusive(realStart, realEnd, entity.offset, entity.offset + entity.length)) { continue; } TLRPC.MessageEntity newEntity; if (entity instanceof TLRPC.TL_messageEntityBold) { newEntity = new TLRPC.TL_messageEntityBold(); } else if (entity instanceof TLRPC.TL_messageEntityItalic) { newEntity = new TLRPC.TL_messageEntityItalic(); } else if (entity instanceof TLRPC.TL_messageEntityUnderline) { newEntity = new TLRPC.TL_messageEntityUnderline(); } else if (entity instanceof TLRPC.TL_messageEntityStrike) { newEntity = new TLRPC.TL_messageEntityStrike(); } else if (entity instanceof TLRPC.TL_messageEntitySpoiler) { newEntity = new TLRPC.TL_messageEntitySpoiler(); } else if (entity instanceof TLRPC.TL_messageEntityCustomEmoji) { newEntity = new TLRPC.TL_messageEntityCustomEmoji(); ((TLRPC.TL_messageEntityCustomEmoji) newEntity).document_id = ((TLRPC.TL_messageEntityCustomEmoji) entity).document_id; ((TLRPC.TL_messageEntityCustomEmoji) newEntity).document = ((TLRPC.TL_messageEntityCustomEmoji) entity).document; } else { continue; } int entityStart = entity.offset - realStart; int entityEnd = entity.offset + entity.length - realStart; if (entityStart < 0 && entityEnd < 0 || entityStart > realEnd && entityEnd > realEnd) { continue; } newEntity.offset = Math.max(0, entityStart); newEntity.length = Math.min(entityEnd, realEnd - realStart) - newEntity.offset; if (entities == null) { entities = new ArrayList<>(); } entities.add(newEntity); } } offset = realStart; length = realEnd - realStart; return true; } } // returns whether quote alert should be shown public boolean checkEdit(MessageObject message) { if (message == null || message.messageOwner == null || message.messageOwner.message == null) { FileLog.e("ReplyQuote.checkEdit: message is null"); return outdated = false; } if (end < start || end > message.messageOwner.message.length() || start > message.messageOwner.message.length() || start < 0 || end < 0) { FileLog.e("ReplyQuote.checkEdit: start/end are invalid (" + start + ", " + end + ", len=" + message.messageOwner.message.length() + ")"); return outdated = false; } String newText = message.messageOwner.message.substring(start, end); if (TextUtils.equals(text, newText)) { this.message = message; update(); // maybe some entities changed return outdated = false; } int newStart = message.messageOwner.message.indexOf(text); if (newStart >= 0) { this.message = message; end = end - start + newStart; start = newStart; update(); return outdated = false; } this.message = message; start = 0; end = message.messageOwner.message.length(); update(); return outdated = true; } public String getText() { return text; } public boolean isValid() { if (todo) { return task != null; } else { return !TextUtils.isEmpty(text); } } public ArrayList getEntities() { return entities; } public boolean limited() { return text != null && message != null && text.length() > MessagesController.getInstance(message.currentAccount).quoteLengthMax; } } public void hideFieldPanel(boolean animated) { showFieldPanel(false, null, null, null, null, true, 0, null, false, 0, animated); } public void hideFieldPanel(boolean notify, int scheduleDate, long payStars, boolean animated) { showFieldPanel(false, null, null, null, null, notify, scheduleDate, null, false, payStars, animated); } public void showFieldPanelForWebPage(boolean show, TLRPC.WebPage webPage, boolean cancel) { showFieldPanel(show, null, null, null, webPage, true, 0, null, cancel, 0, true); } public void showFieldPanelForForward(boolean show, ArrayList messageObjectsToForward) { showFieldPanel(show, null, null, messageObjectsToForward, null, true, 0, null, false, 0, true); } public void showFieldPanelForReply(MessageObject messageObjectToReply) { showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, null, false, 0, true); } private Runnable onHideFieldPanelRunnable; public void showFieldPanelForReplyQuote(MessageObject messageObjectToReply, ReplyQuote quote) { showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, quote, false, 0, true); } public void showFieldPanelForEdit(boolean show, MessageObject messageObjectToEdit) { showFieldPanel(show, null, messageObjectToEdit, null, null, true, 0, null, false, 0, true); } public void showFieldPanelForSuggestionParams(MessageSuggestionParams suggestionParams) { showFieldPanel(true, null, null, null, null, true, 0, null, false, 0, suggestionParams, true); } public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean notify, int scheduleDate, ReplyQuote quote, boolean cancel, long payStars, boolean animated) { showFieldPanel(show, messageObjectToReply, messageObjectToEdit, messageObjectsToForward, webPage, notify, scheduleDate, quote, cancel, payStars, null, animated); } private int fieldPanelShown; public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean notify, int scheduleDate, ReplyQuote quote, boolean cancel, long payStars, MessageSuggestionParams suggestionParams, boolean animated) { if (chatActivityEnterView == null) { return; } chatActivityEnterView.setSuggestionButtonVisible(!show && ChatObject.isMonoForum(currentChat), animated); if (mentionContainer != null) { mentionContainer.getAdapter().setAllowStickers(!show || messageObjectToEdit == null); } boolean showHint = false; if (show) { if (messageObjectToReply == null && messageObjectsToForward == null && messageObjectToEdit == null && webPage == null && suggestionParams == null) { messagePreviewParams = null; return; } hideHints(false); if (searchItem != null && actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(false); chatActivityEnterView.setFieldFocused(); AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null && fieldPanelShown != 5) { chatActivityEnterView.openKeyboard(); } }, 100); } boolean openKeyboard = false; // if (messageObjectToReply != null && messageObjectToReply.getDialogId() != dialog_id && quote == null) { // messageObjectsToForward = new ArrayList<>(); // messageObjectsToForward.add(messageObjectToReply); // messageObjectToReply = null; // openKeyboard = true; // } chatActivityEnterTopView.getReplyView().setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 52, 0)); chatActivityEnterTopView.getEditView().setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 48, 0)); chatActivityEnterTopView.setEditSuggestionMode(false); chatActivityEnterTopView.setEditMode(false); messageSuggestionParams = null; if (messageObjectToEdit != null) { fieldPanelShown = 1; forbidForwardingWithDismiss = false; if (messagePreviewParams != null) { messagePreviewParams.updateForward(null, dialog_id); messagePreviewParams.updateReply(null, null, dialog_id, null); } if (threadMessageId == 0 || isTopic) { if (isTopic) { replyingMessageObject = threadMessageObject; } else { replyingMessageObject = null; } replyingQuote = null; chatActivityEnterView.setReplyingMessageObject(null, null); updateBottomOverlay(); } boolean wereNoEdit = editingMessageObject == null; editingMessageObject = messageObjectToEdit; final boolean mediaEmpty = messageObjectToEdit.isMediaEmpty(); chatActivityEnterView.setEditingMessageObject(messageObjectToEdit, getValidGroupedMessage(messageObjectToEdit), !mediaEmpty); chatActivityEnterView.setForceShowSendButton(false, false); final boolean canEditMedia = messageObjectToEdit.canEditMedia(); replyCloseImageView.setContentDescription(LocaleController.getString(R.string.AccDescrCancelEdit)); if (messageObjectToEdit.needResendWhenEdit()) { messageSuggestionParams = MessageSuggestionParams.of(messageObjectToEdit.messageOwner != null ? messageObjectToEdit.messageOwner.suggested_post : null); } if (!mediaEmpty && canEditMedia) { String editButtonText = null; String replaceButtonText; if (messageObjectToEdit.isPhoto()) { editButtonText = LocaleController.getString(R.string.EditMessageEditPhoto); replaceButtonText = LocaleController.getString(R.string.EditMessageReplacePhoto); } else if (messageObjectToEdit.isVideo()) { editButtonText = LocaleController.getString(R.string.EditMessageEditVideo); replaceButtonText = LocaleController.getString(R.string.EditMessageReplaceVideo); } else if (messageObjectToEdit.isGif()) { replaceButtonText = LocaleController.getString(R.string.EditMessageReplaceGif); } else if (messageObjectToEdit.isMusic()) { replaceButtonText = LocaleController.getString(R.string.EditMessageReplaceAudio); } else { replaceButtonText = LocaleController.getString(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(canEditMedia ? R.drawable.nav_edit_attach : R.drawable.group_edit); replyIconImageView.setContentDescription(LocaleController.getString(R.string.AccDescrEditing)); if (mediaEmpty || canEditMedia) { replyNameTextView.setText(LocaleController.getString(R.string.EditMessage)); } else { replyNameTextView.setText(LocaleController.getString(R.string.EditCaption)); } if (canEditMedia) { replyObjectTextView.setText(LocaleController.getString(mediaEmpty ? R.string.AddMessageMedia : R.string.EditMessageMedia)); } else if (messageObjectToEdit.messageText != null || messageObjectToEdit.caption != null) { CharSequence mess = messageObjectToEdit.caption != null ? messageObjectToEdit.caption : messageObjectToEdit.messageText; if (mess.length() > 150) { mess = mess.subSequence(0, 150); } mess = AndroidUtilities.replaceNewLines(mess); Spannable cs = new SpannableStringBuilder(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), false)); MediaDataController.addTextStyleRuns(messageObjectToEdit, cs); if (messageObjectToEdit.messageOwner != null) { cs = MessageObject.replaceAnimatedEmoji(cs, messageObjectToEdit.messageOwner.entities, replyObjectTextView.getPaint().getFontMetricsInt()); } replyObjectTextView.setText(AnimatedEmojiSpan.cloneSpans(cs)); } } if (editingMessageObject.needResendWhenEdit()) { replyIconImageView.setImageResource(R.drawable.filled_paid_suggest_24); replyNameTextView.setText(LocaleController.getString(R.string.PostSuggestionsOfferChangeTitle)); final boolean isTon = messageSuggestionParams.amount != null && messageSuggestionParams.amount.currency == AmountUtils.Currency.TON; final ColoredImageSpan[] spanArr = new ColoredImageSpan[1]; final String amountString = messageSuggestionParams.amount != null ? messageSuggestionParams.amount.asDecimalString(): "0"; if (messageSuggestionParams.isEmpty()) { replyObjectTextView.setText(LocaleController.getString(R.string.SuggestAPostBelowSubtitle)); } else if (messageSuggestionParams.time <= 0) { replyObjectTextView.setText(StarsIntroActivity.replaceStarsWithPlain(isTon, LocaleController.formatString(R.string.SuggestAPostBelowSubtitleStars, amountString ), 0.66f, spanArr)); } else { replyObjectTextView.setText(StarsIntroActivity.replaceStarsWithPlain(isTon, LocaleController.formatSpannable(R.string.SuggestAPostBelowSubtitleStarsAndTime, amountString, Emoji.replaceEmoji("\uD83D\uDCC6 " + MessageSuggestionOfferSheet.formatDateTime(messageSuggestionParams.time), replyObjectTextView.getPaint().getFontMetricsInt(), true) ), 0.66f, spanArr)); } if (isTon && spanArr[0] != null) { spanArr[0].setColorKey(Theme.key_chat_replyPanelIcons); } if (chatActivityEnterTopView.isEditMode()) { chatActivityEnterTopView.setEditSuggestionMode(true); chatActivityEnterTopView.getReplyView().setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 52 + 48 * 2, 0)); chatActivityEnterTopView.getEditView().setLayoutParams(LayoutHelper.createFrame(48 * 2, LayoutHelper.MATCH_PARENT, Gravity.RIGHT, 0, 0, 48, 0)); } else { chatActivityEnterTopView.getReplyView().setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 52 + 48, 0)); chatActivityEnterTopView.getEditView().setLayoutParams(LayoutHelper.createFrame(48, LayoutHelper.MATCH_PARENT, Gravity.RIGHT, 0, 0, 48, 0)); chatActivityEnterTopView.setEditSuggestionMode(true); final ChatActivityEnterTopView.EditViewButton[] buttons = chatActivityEnterTopView.getEditView().getButtons(); buttons[0].getImageView().setImageResource(R.drawable.nav_edit_attach); buttons[0].setEditButton(false); buttons[1].setVisibility(View.GONE); } } if (wereNoEdit) { if (messageObjectToEdit.messageOwner != null && messageObjectToEdit.messageOwner.media != null && messageObjectToEdit.messageOwner.media.webpage != null) { foundWebPage = messageObjectToEdit.messageOwner.media.webpage; chatActivityEnterView.setWebPage(foundWebPage, false); showFieldPanelForWebPage(true, foundWebPage, false); return; } else { foundWebPage = null; if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(null, false); } } } updateBottomOverlay(); } else if (messageObjectToReply != null) { editingMessageObject = null; // set it for a case when replying in in View as messages mode MessageObject topicTopMessageObject = null; if (isForumInViewAsMessagesMode() && ChatObject.isForum(currentChat)) { long topicId = MessageObject.getTopicId(currentAccount, messageObjectToReply.messageOwner, true); if (topicId != 0) { TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, topicId); if (topic != null && topic.topicStartMessage != null) { topicTopMessageObject = new MessageObject(currentAccount, topic.topicStartMessage, false, false); topicTopMessageObject.isTopicMainMessage = true; topicTopMessageObject.replyToForumTopic = topic; } } } replyingMessageObject = messageObjectToReply; replyingQuote = quote; if (replyingQuote != null && !replyingQuote.isValid()) { replyingQuote = null; } chatActivityEnterView.setReplyingMessageObject(messageObjectToReply, quote, topicTopMessageObject); chatActivityEnterView.setEditingMessageObject(null, null, false); forbidForwardingWithDismiss = false; if (messagePreviewParams == null) { messagePreviewParams = new MessagePreviewParams(currentEncryptedChat != null, getMessagesController().isChatNoForwards(currentChat), ChatObject.isMonoForum(currentChat)); messagePreviewParams.attach(forwardingPreviewView); } messagePreviewParams.updateReply(replyingMessageObject, replyingQuoteGroup != null ? replyingQuoteGroup : getGroup(replyingMessageObject.getGroupId()), dialog_id, replyingQuote); if (messagePreviewParams.isEmpty() && editingMessageObject == null) { messagePreviewParams = null; } fieldPanelShown = 2; String restrictionReason = MessagesController.getInstance(currentAccount).getRestrictionReason(messageObjectToReply.messageOwner.restriction_reason); chatActivityEnterView.setForceShowSendButton(false, false); CharSequence name = null; if (messageObjectToReply.isForwarded() && messageObjectToReply.getDialogId() != dialog_id) { if (messageObjectToReply.messageOwner.fwd_from.from_id != null) { name = MessageObject.peerNameWithIcon(currentAccount, messageObjectToReply.messageOwner.fwd_from.from_id); } else { name = null; } } if (currentEncryptedChat != null) { if (messageObjectToReply.isOutOwner()) { name = UserObject.getUserName(getUserConfig().getCurrentUser()); } else { name = UserObject.getUserName(currentUser); } } else if (name == null && 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 = new SpannableStringBuilder(ChatObject.isChannelAndNotMegaGroup(chat) ? MessageObject.channelSpan() : MessageObject.groupSpan()).append(" ").append(chat.title); } else { TLRPC.User user = getMessagesController().getUser(messageObjectToReply.messageOwner.from_id.user_id); if (user == null) { return; } name = UserObject.getUserName(user); } } else if (name == null) { TLRPC.Chat chat = null; TLRPC.User user = null; if (ChatObject.isChannel(currentChat) && currentChat.megagroup && messageObjectToReply.isForwardedChannelPost()) { chat = getMessagesController().getChat(messageObjectToReply.messageOwner.fwd_from.from_id.channel_id); } else { final long did = messageObjectToReply.getSenderId(); if (did < 0) { chat = getMessagesController().getChat(-did); } else { user = getMessagesController().getUser(did); } } if (chat == null && user == null) { return; } if (chat != null) { name = new SpannableStringBuilder(ChatObject.isChannelAndNotMegaGroup(chat) ? MessageObject.channelSpan() : MessageObject.groupSpan()).append(" ").append(chat.title); } else { name = UserObject.getUserName(user); } } CharSequence nameText; if (quote != null && quote.todo) { replyIconImageView.setImageResource(R.drawable.filled_reply_quote); final TLRPC.MessageMedia media = MessageObject.getMedia(quote.message); if (media instanceof TLRPC.TL_messageMediaToDo) { final TLRPC.TL_messageMediaToDo mediaTodo = (TLRPC.TL_messageMediaToDo) media; nameText = LocaleController.formatSpannable(R.string.ReplyToTaskIn, MessageObject.formatTextWithEntities(mediaTodo.todo.title, false, replyNameTextView.getPaint())); } else { nameText = LocaleController.getString(R.string.ReplyToTask); } } else if (quote != null && !quote.todo) { replyIconImageView.setImageResource(R.drawable.filled_reply_quote); nameText = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.ReplyToQuote), name == null ? "" : name); } else { if (messagePreviewParams == null || messagePreviewParams.hasSecretMessages || chatMode == MODE_QUICK_REPLIES) { replyIconImageView.setImageResource(R.drawable.ic_ab_reply); } else { replyIconImageView.setImageResource(R.drawable.filled_reply_settings); } nameText = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.ReplyTo), name == null ? "" : name); } nameText = Emoji.replaceEmoji(nameText, replyNameTextView.getPaint().getFontMetricsInt(), false); replyNameTextView.setText(nameText); replyIconImageView.setContentDescription(LocaleController.getString(R.string.AccDescrReplying)); replyCloseImageView.setContentDescription(LocaleController.getString(R.string.AccDescrCancelReply)); replyObjectHintTextView.setText(LocaleController.getString(R.string.TapForReplyOptions)); if (!SharedConfig.replyingOptionsHintShown) { showHint = true; } CharSequence replyObjectText = null; CharSequence sourceText = null; ArrayList entities = messageObjectToReply != null && messageObjectToReply.messageOwner != null ? messageObjectToReply.messageOwner.entities : null; if (replyingQuote != null && replyingQuote.todo) { replyObjectText = MessageObject.formatTextWithEntities(replyingQuote.task.title, false, replyObjectTextView.getPaint()); } else if (replyingQuote != null) { if (replyingQuote.outdated) { replyObjectText = new SpannableStringBuilder(LocaleController.getString(R.string.QuoteOutdated)); ((SpannableStringBuilder) replyObjectText).setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM_ITALIC)), 0, replyObjectText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { replyObjectText = new SpannableStringBuilder(replyingQuote.getText()); entities = replyingQuote.getEntities(); replyObjectText = AndroidUtilities.replaceNewLines(replyObjectText); if (entities != null) { replyObjectText = MessageObject.replaceAnimatedEmoji(replyObjectText, entities, replyObjectTextView.getPaint().getFontMetricsInt()); } replyObjectText = Emoji.replaceEmoji(replyObjectText, replyObjectTextView.getPaint().getFontMetricsInt(), false); } } else if (!TextUtils.isEmpty(restrictionReason)) { replyObjectText = restrictionReason; sourceText = restrictionReason; } else if (MessageObject.isTopicActionMessage(messageObjectToReply)) { ForumUtilities.applyTopicToMessage(messageObjectToReply); if (messageObjectToReply.messageTextForReply != null) { replyObjectText = messageObjectToReply.messageTextForReply; } else { replyObjectText = messageObjectToReply.messageTextShort; } AnimatedEmojiSpan.applyFontMetricsForString(replyObjectText, replyObjectTextView.getPaint()); } else if (messageObjectToReply.replyToForumTopic != null) { replyObjectText = ForumUtilities.getTopicSpannedName(messageObjectToReply.replyToForumTopic, replyObjectTextView.getPaint(), false); } else if (messageObjectToReply.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { replyObjectText = Emoji.replaceEmoji(messageObjectToReply.messageOwner.media.game.title, replyObjectTextView.getPaint().getFontMetricsInt(), 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(), false); } if (replyObjectText != null) { if (replyObjectText instanceof Spannable && sourceText != null) { MediaDataController.addTextStyleRuns(entities, sourceText, (Spannable) replyObjectText); } replyObjectTextView.setText(AnimatedEmojiSpan.cloneSpans(replyObjectText)); } updateBottomOverlay(); } else if (messageObjectsToForward != null) { if (messageObjectsToForward.isEmpty()) { return; } fieldPanelShown = 3; if (messagePreviewParams == null) { messagePreviewParams = new MessagePreviewParams(currentEncryptedChat != null, getMessagesController().isChatNoForwards(currentChat), ChatObject.isMonoForum(currentChat)); messagePreviewParams.attach(forwardingPreviewView); } messagePreviewParams.updateForward(messageObjectsToForward, dialog_id); if (messagePreviewParams.isEmpty() && editingMessageObject == null) { messagePreviewParams = null; } editingMessageObject = null; chatActivityEnterView.setEditingMessageObject(null, null, false); forbidForwardingWithDismiss = false; chatActivityEnterView.setForceShowSendButton(true, false); ArrayList uids = new ArrayList<>(); replyIconImageView.setImageResource(R.drawable.filled_forward); replyIconImageView.setContentDescription(LocaleController.getString(R.string.AccDescrForwarding)); replyCloseImageView.setContentDescription(LocaleController.getString(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; } } int userNamesCount = 0; 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); } userNamesCount++; } 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); } userNamesCount++; } else { userNames.append(" "); userNames.append(LocaleController.formatPluralString("AndOther", uids.size() - 1)); userNamesCount++; break; } } formwardingNameText = userNames; CharSequence text = ""; if (type == -1 || type == MessageObject.TYPE_TEXT || type == MessageObject.TYPE_DATE || type == MessageObject.TYPE_ACTION_PHOTO || type == MessageObject.TYPE_EMOJIS) { text = LocaleController.formatPluralString("PreviewForwardMessagesCount", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_PHOTO) { text = LocaleController.formatPluralString("PreviewForwardPhoto", messageObjectsToForward.size()); if (messageObjectsToForward.size() == 1) { messageObjectToReply = messageObjectsToForward.get(0); } } else if (type == MessageObject.TYPE_GIVEAWAY) { text = LocaleController.getString(R.string.BoostingGiveaway); } else if (type == MessageObject.TYPE_GIVEAWAY_RESULTS) { text = LocaleController.getString(R.string.BoostingGiveawayResults); } else if (type == MessageObject.TYPE_GEO) { text = LocaleController.formatPluralString("PreviewForwardLocation", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_VIDEO) { text = LocaleController.formatPluralString("PreviewForwardVideo", messageObjectsToForward.size()); if (messageObjectsToForward.size() == 1) { messageObjectToReply = messageObjectsToForward.get(0); } } else if (type == MessageObject.TYPE_CONTACT) { text = LocaleController.formatPluralString("PreviewForwardContact", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_VOICE) { text = LocaleController.formatPluralString("PreviewForwardAudio", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_ROUND_VIDEO) { text = LocaleController.formatPluralString("PreviewForwardRound", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_MUSIC) { text = LocaleController.formatPluralString("PreviewForwardMusic", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_STICKER || type == MessageObject.TYPE_ANIMATED_STICKER) { text = LocaleController.formatPluralString("PreviewForwardSticker", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_POLL) { text = LocaleController.formatPluralString(object != null && object.isTodo() ? "PreviewForwardTodo" : "PreviewForwardPoll", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_GIF || type == MessageObject.TYPE_FILE) { if (messageObjectsToForward.size() == 1 & type == MessageObject.TYPE_FILE) { messageObjectToReply = messageObjectsToForward.get(0); } if (messageObjectsToForward.size() == 1 && type == MessageObject.TYPE_GIF) { text = LocaleController.getString(R.string.AttachGif); } else { text = LocaleController.formatPluralString("PreviewForwardFile", messageObjectsToForward.size()); } } else if (type == MessageObject.TYPE_STORY) { if (messageObjectsToForward.size() == 1) { text = LocaleController.getString(R.string.Story); } else { text = LocaleController.formatPluralString("Stories", messageObjectsToForward.size()); } } replyNameTextView.setText(text); if (messagePreviewParams != null && messagePreviewParams.hideForwardSendersName) { replyObjectTextView.setText(LocaleController.getString(R.string.HiddenSendersNameDescription)); } else { if ((type == -1 || type == MessageObject.TYPE_TEXT || type == MessageObject.TYPE_DATE || type == MessageObject.TYPE_ACTION_PHOTO || 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(), 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()); } } if (userNamesCount == 1) { mess = TextUtils.concat(userNames, ": ", mess); } replyObjectTextView.setText(mess); } else { replyObjectTextView.setText(LocaleController.formatString("ForwardingFromNames", R.string.ForwardingFromNames, userNames)); } } replyObjectHintTextView.setText(LocaleController.getString(R.string.TapForForwardingOptions)); if (!SharedConfig.forwardingOptionsHintShown) { showHint = true; } } else if (webPage != null) { fieldPanelShown = 4; replyIconImageView.setImageResource(R.drawable.filled_link); if (messagePreviewParams == null) { messagePreviewParams = new MessagePreviewParams(currentEncryptedChat != null, getMessagesController().isChatNoForwards(currentChat), ChatObject.isMonoForum(currentChat)); messagePreviewParams.attach(forwardingPreviewView); } messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); if (messagePreviewParams.isEmpty() && editingMessageObject == null) { messagePreviewParams = null; } if (webPage instanceof TLRPC.TL_webPagePending) { replyNameTextView.setText(LocaleController.getString(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(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); } } else if (suggestionParams != null) { messageSuggestionParams = suggestionParams; messagePreviewParams = null; fieldPanelShown = 5; if (foundWebPage != null) { foundWebPage = null; chatActivityEnterView.setWebPage(null, !cancel); } chatActivityEnterView.setReplyingMessageObject(threadMessageObject, null); chatActivityEnterView.setEditingMessageObject(null, null, false); topViewWasVisible = 0; replyingMessageObject = threadMessageObject; replyingQuote = null; editingMessageObject = null; replyImageLocation = null; replyImageLocationObject = null; replyIconImageView.setImageResource(R.drawable.filled_paid_suggest_24); replyNameTextView.setText(LocaleController.getString(R.string.SuggestAPostBelow)); final boolean isTon = suggestionParams.amount != null && suggestionParams.amount.currency == AmountUtils.Currency.TON; final ColoredImageSpan[] spanArr = new ColoredImageSpan[1]; final String amountString = suggestionParams.amount != null ? suggestionParams.amount.asDecimalString(): "0"; if (suggestionParams.isEmpty()) { replyObjectTextView.setText(LocaleController.getString(R.string.SuggestAPostBelowSubtitle)); } else if (suggestionParams.time <= 0) { replyObjectTextView.setText(StarsIntroActivity.replaceStarsWithPlain(isTon, LocaleController.formatString(R.string.SuggestAPostBelowSubtitleStars, amountString ), 0.66f, spanArr)); } else { replyObjectTextView.setText(StarsIntroActivity.replaceStarsWithPlain(isTon, LocaleController.formatSpannable(R.string.SuggestAPostBelowSubtitleStarsAndTime, amountString, Emoji.replaceEmoji("\uD83D\uDCC6 " + MessageSuggestionOfferSheet.formatDateTime(suggestionParams.time), replyObjectTextView.getPaint().getFontMetricsInt(), true) ), 0.66f, spanArr)); } if (isTon && spanArr[0] != null) { spanArr[0].setColorKey(Theme.key_chat_replyPanelIcons); } } 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.getInstance(currentAccount).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; } } 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() || forwardingPreviewView != null) { 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; replyImageHasMediaSpoiler = thumbMediaMessageObject.hasMediaSpoilers(); replyImageView.setImage(ImageLocation.getForObject(replyImageLocation, photoSizeObject), replyImageHasMediaSpoiler ? "5_5_b" : "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), replyImageHasMediaSpoiler ? "5_5_b" : "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 { fieldPanelShown = 0; if (replyingMessageObject == null && messagePreviewParams == null && foundWebPage == null && editingMessageObject == null && !chatActivityEnterView.isTopViewVisible() && topicsTabs == null) { messagePreviewParams = null; return; } if (replyingMessageObject != null && replyingMessageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyKeyboardForceReply) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); String tk = isTopic ? dialog_id + "_" + getTopicId() : "" + dialog_id; preferences.edit().putInt("answered_" + tk, replyingMessageObject.getId()).commit(); } if (foundWebPage != null) { foundWebPage = null; chatActivityEnterView.setWebPage(null, !cancel); } if (messagePreviewParams != null && messagePreviewParams.forwardMessages != null) { forbidForwardingWithDismiss = false; // if (messagePreviewParams.quote == null) { ArrayList messagesToForward = new ArrayList<>(); if (messagePreviewParams.forwardMessages != null) { messagePreviewParams.forwardMessages.getSelectedMessages(messagesToForward); } forwardMessages(messagesToForward, messagePreviewParams.hideForwardSendersName, messagePreviewParams.hideCaption, notify, scheduleDate != 0 && scheduleDate != 0x7ffffffe ? scheduleDate + 1 : scheduleDate, payStars); // } } if (forwardingPreviewView == null) { messagePreviewParams = null; } chatActivityEnterView.setForceShowSendButton(false, animated); if (!waitingForSendingMessageLoad) { chatActivityEnterView.hideTopView(animated); } chatActivityEnterView.setReplyingMessageObject(threadMessageObject, null); chatActivityEnterView.setEditingMessageObject(null, null, false); topViewWasVisible = 0; replyingMessageObject = threadMessageObject; replyingQuote = null; editingMessageObject = null; replyImageLocation = null; replyImageLocationObject = null; messageSuggestionParams = null; updateBottomOverlay(); } 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); } if (chatActivityEnterView != null) { chatActivityEnterView.updateSendButtonPaid(); } } 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; } if (readNow) { final boolean delete = messageObject.messageOwner.ttl != 0x7FFFFFFF; final int ttl = messageObject.messageOwner.ttl == 0x7FFFFFFF ? 0 : messageObject.messageOwner.ttl; messageObject.messageOwner.destroyTime = ttl + getConnectionsManager().getCurrentTime(); if (currentEncryptedChat != null) { getMessagesController().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id, ttl); } else { getMessagesController().markMessageAsRead2(dialog_id, messageObject.getId(), null, ttl, 0, delete); } return null; } else { return () -> { final boolean delete = messageObject.messageOwner.ttl != 0x7FFFFFFF; final int ttl = messageObject.messageOwner.ttl == 0x7FFFFFFF ? 0 : messageObject.messageOwner.ttl; messageObject.messageOwner.destroyTime = ttl + getConnectionsManager().getCurrentTime(); messageObject.messageOwner.destroyTimeMillis = ttl * 1000L + getConnectionsManager().getCurrentTimeMillis(); if (currentEncryptedChat != null) { getMessagesController().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id, ttl); } else { getMessagesController().markMessageAsRead2(dialog_id, messageObject.getId(), null, ttl, 0, delete); } }; } } private Runnable sendSecretMediaDelete(MessageObject messageObject) { if (messageObject == null || messageObject.isOut() || !messageObject.isSecretMedia() || messageObject.messageOwner.ttl != 0x7FFFFFFF) { return null; } final long taskId = getMessagesController().createDeleteShowOnceTask(dialog_id, messageObject.getId()); messageObject.forceExpired = true; if (messageObject.isOutOwner() || !messageObject.isRoundOnce() && !messageObject.isVoiceOnce()) { ArrayList msgs = new ArrayList<>(); msgs.add(messageObject); updateMessages(msgs, true); } return () -> getMessagesController().doDeleteShowOnceTask(taskId, dialog_id, messageObject.getId()); } private void clearChatData(boolean full) { messages.clear(); messagesByDays.clear(); messagesByDaysSorted.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; } if (full) { 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.isFiltered) { chatAdapter.notifyDataSetChanged(false); } } public void scrollToLastMessage(boolean skipSponsored, boolean top) { scrollToLastMessage(skipSponsored, top, null); } public void scrollToLastMessage(boolean skipSponsored, boolean top, Runnable inCaseLoading) { 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) { sideControlsButtonsLayout.setButtonLoading(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, false, true); 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++; top = false; } } if (top && messages != null && !messages.isEmpty() && messages.get(position) != null) { long groupId = messages.get(position).getGroupId(); while (groupId != 0 && position + 1 < messages.size()) { if (groupId != messages.get(position + 1).getGroupId()) { break; } position++; } } if (messages != null && !messages.isEmpty()) { position = Math.min(position, messages.size() - 1); } final int finalPosition = position; final boolean finalTop = top; Runnable scroll = () -> { chatScrollHelper.scrollToPosition(chatScrollHelperCallback.position = finalPosition, chatScrollHelperCallback.offset = 0, chatScrollHelperCallback.bottom = !finalTop, true, true); canShowPagedownButton = false; updatePagedownButtonVisibility(true); }; if (SCROLL_DEBUG_DELAY && inCaseLoading != null) { inCaseLoading.run(); AndroidUtilities.runOnUIThread(() -> { resetProgressDialogLoading(); scroll.run(); }, 7500); } else { scroll.run(); } } } else { if (progressDialog != null) { progressDialog.dismiss(); } updatePinnedListButton(false); if (inCaseLoading != null) { inCaseLoading.run(); } else { resetProgressDialogLoading(); progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, themeDelegate); progressDialog.setOnCancelListener(postponedScrollCancelListener); progressDialog.showDelayed(1000); } postponedScrollToLastMessageQueryIndex = lastLoadIndex; fakePostponedScroll = false; postponedScrollMessageId = 0; postponedScrollIsCanceled = false; waitingForLoad.clear(); waitingForLoad.add(lastLoadIndex); AndroidUtilities.runOnUIThread(() -> { getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 30, 0, 0, true, 0, classGuid, 0, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); }, SCROLL_DEBUG_DELAY ? 7500 : 0); } } public void updateTextureViewPosition(boolean needVisibleUpdate, 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()) && !messageObject.isVoiceTranscriptionOpen() && MediaController.getInstance().isPlayingMessage(messageObject)) { ImageReceiver imageReceiver = messageCell.getPhotoImage(); videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); float translationY = messageCell.getY() + messageCell.getPaddingTop() + 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(isSideMenued()) || layoutParams.height != AndroidUtilities.roundPlayingMessageSize(isSideMenued())) { layoutParams.width = layoutParams.height = AndroidUtilities.roundPlayingMessageSize(isSideMenued()); aspectRatioFrameLayout.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT); videoPlayerContainer.setLayoutParams(layoutParams); } float scale = (AndroidUtilities.roundPlayingMessageSize(isSideMenued()) + AndroidUtilities.roundMessageInset * 2) / (float) AndroidUtilities.roundPlayingMessageSize(isSideMenued()); float transitionScale = messageCell.getPhotoImage().getImageWidth() / AndroidUtilities.roundPlayingMessageSize(isSideMenued()); 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 (needVisibleUpdate && 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(isSideMenued()) - 100); fragmentView.invalidate(); if (messageObject.isRoundVideo() || messageObject.isVideo()) { if (checkTextureViewPosition || PipRoundVideoView.getInstance() != null) { MediaController.getInstance().setCurrentVideoVisible(false); } else if (needScroll) { 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 || fragmentView == null) { return; } int count = chatListView.getChildCount(); int height = chatListView.getMeasuredHeight(); int minPositionHolder = Integer.MAX_VALUE; int minPositionDateHolder = Integer.MAX_VALUE; int minPositionTopicHolder = Integer.MAX_VALUE; int minTopicPositionHolder = Integer.MAX_VALUE; View minDateChild = null; View minTopicChild = null; View minChild = null; View minMessageChild = null; View minTopicMessageChild = null; boolean foundTextureViewMessage = false; boolean previousThreadMessageVisible = threadMessageVisible; int previousPinnedMessageId = currentPinnedMessageId; int maxVisibleId = Integer.MIN_VALUE; MessageObject maxVisibleMessageObject = null; threadMessageVisible = firstLoading; Integer currentReadMaxId = null; long 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.getMeasuredHeight() - (inPreviewMode || isInsideContainer ? 0 : AndroidUtilities.dp(48)) - chatListView.getTop()); pollsToCheck.clear(); float clipTop = chatListViewPaddingTop; float clipTopicTop = chatListViewPaddingTop + dp(28); long currentTime = System.currentTimeMillis(); int maxAdapterPosition = -1; int minAdapterPosition = -1; boolean blurEnabled = SharedConfig.chatBlurEnabled() && Color.alpha(Theme.getColor(Theme.key_chat_BlurAlpha)) != 255; MessageObject messageStarter = isTopic ? topicStarterMessageObject : threadMessageObject; float clipTopFinal = clipTop - chatListViewPaddingVisibleOffset; float clipBottomFinal = chatListView.getMeasuredHeight() - blurredViewBottomOffset; boolean checkPremiumFloodWait = !UserConfig.getInstance(currentAccount).isPremium(); 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; } } final int top = (int) view.getY(); final 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 <= clipTopFinal || top > clipBottomFinal) { if (messageCell != null) { if (blurEnabled) { messageCell.setVisibleOnScreen(false, 0, 0); } else { messageCell.setVisibleOnScreen(true, 0, 0); } } continue; } if (messageCell != null) { messageCell.setVisibleOnScreen(true, clipTopFinal - top, bottom - clipBottomFinal); if (checkPremiumFloodWait) { if (messageCell.checkLoadCaughtPremiumFloodWait()) { showPremiumFloodWaitBulletin(false); checkPremiumFloodWait = false; } else if (messageCell.checkUploadCaughtPremiumFloodWait()) { showPremiumFloodWaitBulletin(true); checkPremiumFloodWait = false; } } } 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(); } final boolean visibleToBeRead = !BaseFragment.hasSheets(this) && (currentChat == null || !ChatObject.isChannelAndNotMegaGroup(currentChat) || view.getMeasuredHeight() > 0 && top + view.getMeasuredHeight() * (messageCell == null || messageCell.getCurrentPosition() == null ? .80f : 1f) < clipBottomFinal); final float visibleTop = getServiceTop(view); final int visibleBackgroundHeight = getServiceHeight(view); boolean hasTopicSeparator = false; if (messageCell != null) { messageObject = messageCell.getMessageObject(); if (messageObject.getDialogId() == dialog_id && messageObject.getId() > maxVisibleId) { maxVisibleId = messageObject.getId(); maxVisibleMessageObject = messageObject; } hasTopicSeparator = messageCell.topicSeparator != null; messageCell.setParentBounds((SharedConfig.chatBlurEnabled() && contentView.DRAW_USING_RENDERNODE() ? 0 : chatListViewPaddingTop) - chatListViewPaddingVisibleOffset - dp(4), chatListView.getMeasuredHeight() - blurredViewBottomOffset); messageCell.setVisiblePart( viewTop, viewBottom - viewTop, recyclerChatViewHeight, 0, view.getY() + (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY() - (1f - contentPanTranslationT) * chatListViewPaddingTop, contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), blurredViewTopOffset, blurredViewBottomOffset, top - (int) chatListViewPaddingTop ); if (messageObject.isSponsored()) { final float rTop = ViewPositionWatcher.computeYCoordinateInParent(messageCell, contentView); final boolean isVisible = messageObject.viewsReloaded || rTop < contentView.getMeasuredHeight() - dp(9 + 32) - windowInsetsStateHolder.getAnimatedMaxBottomInset() - inputIslandHeightCurrent; messageCell.setSponsoredMessageVisible(isVisible, isVisible); if (isVisible) { markSponsoredAsRead(messageObject); } } if (!threadMessageVisible && messageStarter != null && (messageObject == messageStarter || isTopic && messageObject != null && messageObject.getId() == messageStarter.getId()) && messageCell.getBottom() > chatListViewPaddingTop) { threadMessageVisible = true; } if (videoPlayerContainer != null && (messageObject.isVideo() || messageObject.isRoundVideo()) && !messageObject.isVoiceTranscriptionOpen() && 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() + messageCell.getPaddingTop() + 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 (messageObject != null && fragmentOpened && openAnimationEnded && (chatListItemAnimator == null || !chatListItemAnimator.isRunning()) && messageCell.checkUnreadReactions(clipTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { reactionsMentionCount--; getMessagesStorage().markMessageReactionsAsRead(getDialogId(), getTopicId(), messageObject.getId(), true); if (reactionsMentionCount <= 0) { getMessagesController().markReactionsAsRead(dialog_id, getTopicId()); } if (reactionsMentionCount >= 0) { TLRPC.MessagePeerReaction reaction = messageCell.getMessageObject().getRandomUnreadReaction(); if (reaction != null) { ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction); ReactionsEffectOverlay.show(ChatActivity.this, null, messageCell, null, 0, 0, visibleReaction, currentAccount, reaction.big ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } messageCell.markReactionsAsRead(); } else { messageCell.markReactionsAsRead(); reactionsMentionCount = 0; } updateReactionsMentionButton(true); } getDownloadController().checkUnviewedDownloads(messageCell.getId(), dialog_id); boolean allowPlayEffect = messageObject.getEffect() != null || ((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() || messageCell.getEffect() != null || 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()); } hasTopicSeparator = cell.topicSeparator != null; if (messageObject != null && fragmentOpened && openAnimationEnded && (chatListItemAnimator == null || !chatListItemAnimator.isRunning()) && cell.checkUnreadReactions(clipTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { reactionsMentionCount--; getMessagesStorage().markMessageReactionsAsRead(getDialogId(), getTopicId(), messageObject.getId(), true); if (reactionsMentionCount <= 0) { getMessagesController().markReactionsAsRead(dialog_id, getTopicId()); } if (reactionsMentionCount >= 0) { TLRPC.MessagePeerReaction reaction = cell.getMessageObject().getRandomUnreadReaction(); if (reaction != null) { ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction); ReactionsEffectOverlay.show(ChatActivity.this, null, cell, null, 0, 0, visibleReaction, currentAccount, reaction.big ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } cell.markReactionsAsRead(); } else { reactionsMentionCount = 0; } updateReactionsMentionButton(true); } cell.setVisiblePart(visibleTop, visibleBackgroundHeight); } else if (view instanceof BotHelpCell) { view.invalidate(); } else if (view instanceof ChatLoadingCell) { ((ChatLoadingCell) view).setVisiblePart(visibleTop, visibleBackgroundHeight); } else if (view instanceof UserInfoCell) { ((UserInfoCell) view).setVisiblePart(visibleTop, visibleBackgroundHeight); } if (isAllChats()) { final int topicBottom = hasTopicSeparator ? top + view.getPaddingTop() : bottom; if (bottom <= clipTopicTop) { if (view instanceof ChatActionCell) { ((ChatActionCell) view).setShowTopic(false); } else if (view instanceof ChatMessageCell) { ((ChatMessageCell) view).setShowTopic(false); } } else { if (topicBottom < minTopicPositionHolder) { minTopicPositionHolder = topicBottom; if (view instanceof ChatActionCell) { minTopicMessageChild = view; } else if (view instanceof ChatMessageCell) { minTopicMessageChild = view; } } } if (topicBottom >= clipTopicTop) { if (hasTopicSeparator && (chatListItemAnimator == null || (!chatListItemAnimator.willRemoved(view) && !chatListItemAnimator.willAddedFromAlpha(view)))) { if (view instanceof ChatActionCell) { ((ChatActionCell) view).setShowTopic(true); if (topicBottom < minPositionTopicHolder) { minPositionTopicHolder = topicBottom; minTopicChild = view; } } else if (view instanceof ChatMessageCell) { ((ChatMessageCell) view).setShowTopic(true); if (topicBottom < minPositionTopicHolder) { minPositionTopicHolder = topicBottom; minTopicChild = view; } } } } } if (chatMode != MODE_SCHEDULED && messageObject != null) { int id = messageObject.getId(); if ( !isThreadChat() && visibleToBeRead && (!messageObject.isOut() && messageObject.isUnread() || messageObject.messageOwner.from_scheduled && id > currentReadMaxId) || (isThreadChat() || ChatObject.isMonoForum(currentChat)) && id > 0 && id > currentReadMaxId && id > replyMaxReadId ) { MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); if (group != null) { for (MessageObject msg : group.messages) { final int msg_id = msg.getId(); if (msg_id > 0) { maxPositiveUnreadId = Math.max(maxPositiveUnreadId, msg_id); } if (msg_id < 0 && !isThreadChat()) { maxNegativeUnreadId = Math.min(maxNegativeUnreadId, msg_id); } maxUnreadDate = Math.max(maxUnreadDate, msg.messageOwner.date); } } else { 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 != null && messageObject.isDateObject) { view.setAlpha(0); } } else { 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 != null && messageObject.isDateObject) { if (view.getAlpha() != 1.0f) { view.setAlpha(1.0f); } if (position < minPositionDateHolder) { minPositionDateHolder = position; minDateChild = view; } } } } } currentPinnedMessageId = 0; if (!pinnedMessageIds.isEmpty() || (isTopic && maxPinnedMessageId != 0)) { 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 && (isTopic || (!pinnedMessageIds.isEmpty() && currentPinnedMessageIndex[0] > pinnedMessageIds.size() - 2))) { getMediaDataController().loadPinnedMessages(dialog_id, maxPinnedMessageId, 0); loadingPinnedMessagesList = true; } } getMessagesController().addToPollsQueue(dialog_id, pollsToCheck); chatMessagesMetadataController.checkMessages(chatAdapter, maxAdapterPosition, minAdapterPosition, currentTime); 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(isSideMenued()) - 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(); } if (messageObject != null && messageObject.messageOwner != null) { floatingDateView.setCustomDate(messageObject.messageOwner.date, chatMode == MODE_SCHEDULED, true); } } if (minTopicMessageChild != null) { MessageObject messageObject; if (minTopicMessageChild instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) minTopicMessageChild).getMessageObject(); } else { messageObject = ((ChatActionCell) minTopicMessageChild).getMessageObject(); } if (messageObject != null && messageObject.messageOwner != null) { floatingTopicSeparator.set(messageObject); } } currentFloatingDateOnScreen = false; currentFloatingTopicOnScreen = 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 + (reversed ? 0 : 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 + (reversed ? 0 : 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 (chatMode == MODE_QUICK_REPLIES) { showFloatingView = false; } 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 (minTopicChild != null) { boolean showFloatingView = false; if (minTopicChild.getY() > clipTopicTop || currentFloatingTopIsNotMessage) { if (minTopicChild instanceof ChatActionCell) { ((ChatActionCell) minTopicChild).setShowTopic(true); } else if (minTopicChild instanceof ChatMessageCell) { ((ChatMessageCell) minTopicChild).setShowTopic(true); } if (chatListView.getChildAdapterPosition(minTopicChild) == chatAdapter.messagesStartRow + (reversed ? 0 : messages.size() - 1)) { if (minTopicChild instanceof ChatActionCell) { ((ChatActionCell) minTopicChild).setShowTopic(true); } else if (minTopicChild instanceof ChatMessageCell) { ((ChatMessageCell) minTopicChild).setShowTopic(true); } if (floatingTopicAnimation != null) { floatingTopicAnimation.cancel(); floatingTopicAnimation = null; } floatingTopicSeparator.setTag(null); currentFloatingTopicOnScreen = false; } else { hideFloatingTopicView(!currentFloatingTopIsNotMessage); } } else { if (minTopicChild instanceof ChatActionCell) { ((ChatActionCell) minTopicChild).setShowTopic(false); } else if (minTopicChild instanceof ChatMessageCell) { ((ChatMessageCell) minTopicChild).setShowTopic(false); } showFloatingView = true; } float offset = minTopicChild.getY() + minTopicChild.getPaddingTop() - clipTopicTop; if (offset > floatingTopicSeparator.getMeasuredHeight() && offset < floatingTopicSeparator.getMeasuredHeight() * 2) { if (chatListView.getChildAdapterPosition(minTopicChild) == chatAdapter.messagesStartRow + (reversed ? 0 : messages.size() - 1)) { showFloatingView = false; if (minTopicChild instanceof ChatActionCell) { ((ChatActionCell) minTopicChild).setShowTopic(true); } else if (minTopicChild instanceof ChatMessageCell) { ((ChatMessageCell) minTopicChild).setShowTopic(true); } if (floatingTopicAnimation != null) { floatingTopicAnimation.cancel(); floatingTopicAnimation = null; } floatingTopicSeparator.setTag(null); } else { floatingTopicViewOffset = -floatingTopicSeparator.getMeasuredHeight() * 2 + offset; } } else { floatingTopicViewOffset = 0; } if (chatMode == MODE_QUICK_REPLIES) { showFloatingView = false; } if (showFloatingView) { if (floatingTopicAnimation != null) { floatingTopicAnimation.cancel(); floatingTopicAnimation = null; } if (floatingTopicSeparator.getTag() == null) { floatingTopicSeparator.setTag(1); } currentFloatingTopicOnScreen = true; } } else { hideFloatingTopicView(true); floatingTopicViewOffset = 0; } if (isThreadChat() && (!isTopic || pinnedOnlyStarterMessage())) { if (previousThreadMessageVisible != threadMessageVisible) { AndroidUtilities.runOnUIThread(() -> { 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; } AndroidUtilities.runOnUIThread(() -> { updatePinnedMessageView(animated, animateToNext); }); } else if (isTopic && currentPinnedMessageId != 0 && (pinnedMessageView == null || pinnedMessageView.getTag() != null)) { AndroidUtilities.runOnUIThread(() -> { updatePinnedMessageView(animated, 0); }); } else { updatePinnedListButton(animated); } } if (floatingDateView != null) { floatingDateView.setTranslationX(getSideMenuWidth() / 2f); floatingDateView.setTranslationY(chatListView.getTranslationY() + chatListViewPaddingTop + floatingDateViewOffset - dp(4)); } updateFloatingTopicView(); invalidateChatListViewTopPadding(); if (!firstLoading && !paused && !inPreviewMode && (chatMode == 0 || chatMode == MODE_SUGGESTIONS) && !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); if (isTopic && replyOriginalChat != null) { getMessagesStorage().updateRepliesMaxReadId(replyOriginalChat.id, replyOriginalMessageId, Math.max(maxPositiveUnreadId, replyMaxReadId), 0, true); } firstUnreadSent = true; } } if (threadId != 0 && maxPositiveUnreadId > 0 && replyMaxReadId != maxPositiveUnreadId && (replyOriginalChat != null || UserObject.isBotForum(currentUser) || ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat))) { replyMaxReadId = maxPositiveUnreadId; long chatId = currentChat != null ? currentChat.id : -currentUser.id; getMessagesStorage().updateRepliesMaxReadId(chatId, threadId, replyMaxReadId, newUnreadMessageCount, true); } else if (threadId != 0 && maxPositiveUnreadId > 0 && replyMaxReadId != maxPositiveUnreadId && replyOriginalChat != null) { replyMaxReadId = maxPositiveUnreadId; getMessagesStorage().updateRepliesMaxReadId(replyOriginalChat.id, replyOriginalMessageId, replyMaxReadId, newUnreadMessageCount, true); if (!isTopic) { getNotificationCenter().postNotificationName(NotificationCenter.commentsRead, replyOriginalChat.id, replyOriginalMessageId, replyMaxReadId); } } } if (progressView2 != null) { progressView2.invalidate(); } } private float getServiceTop(View view) { return view.getY() + (isKeyboardVisible() ? chatListView.getTop() : actionBar.getMeasuredHeight()) - contentView.getBackgroundTranslationY() - (1f - contentPanTranslationT) * chatListViewPaddingTop; } public int getServiceHeight(View view) { return contentView.getBackgroundSizeY(); } private boolean pinnedOnlyStarterMessage() { return pinnedMessageIds.size() == 1 && topicStarterMessageObject != null && pinnedMessageIds.get(0) == topicStarterMessageObject.getId(); } private void inlineUpdate1() { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, newUnreadMessageCount, openAnimationEnded); } } private void inlineUpdate2() { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, newUnreadMessageCount, true); } } private void toggleMute(boolean instant) { boolean muted = getMessagesController().isDialogMuted(dialog_id, getTopicId()); if (!muted) { if (instant) { getNotificationsController().muteDialog(dialog_id, getTopicId(), true); } else { BottomSheet alert = AlertsCreator.createMuteAlert(this, dialog_id, getTopicId(), themeDelegate); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } } else { getNotificationsController().muteDialog(dialog_id, getTopicId(), false); if (!instant) { BulletinFactory.createMuteBulletin(this, false, themeDelegate).show(); } } } private int getScrollOffsetForMessage(MessageObject object) { return getScrollOffsetForMessage(getHeightForMessage(object, !TextUtils.isEmpty(highlightMessageQuote))) - scrollOffsetForQuote(object); } private int getScrollOffsetForMessage(int messageHeight) { return (int) Math.max(-AndroidUtilities.dp(2), (chatListView.getMeasuredHeight() - blurredViewBottomOffset - chatListViewPaddingTop - windowInsetsStateHolder.getCurrentMaxBottomInset() - dp(44 + 9) - messageHeight) / 2); } private int scrollOffsetForQuote(MessageObject object) { if (TextUtils.isEmpty(highlightMessageQuote) || object == null) { if (dummyMessageCell != null) { dummyMessageCell.computedGroupCaptionY = 0; dummyMessageCell.computedCaptionLayout = null; } return 0; } int offsetY; CharSequence text; ArrayList textLayoutBlocks; if (object.getGroupId() != 0) { MessageObject.GroupedMessages group = getGroup(object.getGroupId()); if (dummyMessageCell == null || dummyMessageCell.computedCaptionLayout == null || group == null || group.captionMessage == null) { if (dummyMessageCell != null) { dummyMessageCell.computedGroupCaptionY = 0; dummyMessageCell.computedCaptionLayout = null; } return 0; } offsetY = dummyMessageCell.computedGroupCaptionY; text = group.captionMessage.caption; textLayoutBlocks = dummyMessageCell.computedCaptionLayout.textLayoutBlocks; } else if (!TextUtils.isEmpty(object.caption) && dummyMessageCell != null && dummyMessageCell.captionLayout != null) { offsetY = (int) dummyMessageCell.captionY; text = object.caption; textLayoutBlocks = dummyMessageCell.captionLayout.textLayoutBlocks; } else { offsetY = 0; text = object.messageText; textLayoutBlocks = object.textLayoutBlocks; if (dummyMessageCell != null && dummyMessageCell.linkPreviewAbove) { offsetY += dummyMessageCell.linkPreviewHeight + AndroidUtilities.dp(10); } } if (dummyMessageCell != null) { dummyMessageCell.computedGroupCaptionY = 0; dummyMessageCell.computedCaptionLayout = null; } if (textLayoutBlocks == null || text == null) { return 0; } int index = MessageObject.findQuoteStart(text.toString(), highlightMessageQuote, highlightMessageQuoteOffset); if (index < 0) { return 0; } for (int i = 0; i < textLayoutBlocks.size(); ++i) { MessageObject.TextLayoutBlock block = textLayoutBlocks.get(i); StaticLayout layout = block.textLayout; String layoutText = layout.getText().toString(); if (index > block.charactersOffset) { final float y; if (index - block.charactersOffset > layoutText.length() - 1) { y = offsetY + (int) (block.textYOffset(textLayoutBlocks) + block.padTop + block.height); } else { y = offsetY + block.textYOffset(textLayoutBlocks) + block.padTop + layout.getLineTop(layout.getLineForOffset(index - block.charactersOffset)); } if (y > AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)) { return (int) (y - AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)); } return 0; } } return 0; } private int getHeightForMessage(MessageObject object, boolean withGroupCaption) { if (getParentActivity() == null) { return 0; } if (dummyMessageCell == null) { dummyMessageCell = new ChatMessageCell(getParentActivity(), currentAccount, true, sharedResources, themeDelegate); } dummyMessageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser); dummyMessageCell.isSavedChat = chatMode == MODE_SAVED; dummyMessageCell.isSavedPreviewChat = chatMode == MODE_SAVED && isInsideContainer; dummyMessageCell.isBot = currentUser != null && currentUser.bot; dummyMessageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; dummyMessageCell.isAllChats = isAllChats(); dummyMessageCell.isSideMenued = isSideMenued(); dummyMessageCell.isSideMenuEnabled = isSideMenuEnabled(); return dummyMessageCell.computeHeight(object, groupedMessagesMap.get(object.getGroupId()), withGroupCaption); } private void startMessageUnselect() { if (unselectRunnable != null) { AndroidUtilities.cancelRunOnUIThread(unselectRunnable); } unselectRunnable = () -> { highlightMessageId = Integer.MAX_VALUE; highlightMessageQuoteFirst = false; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = null; highlightTaskId = null; highlightMessageQuoteOffset = -1; showNoQuoteAlert = false; updateVisibleRows(); unselectRunnable = null; }; AndroidUtilities.runOnUIThread(unselectRunnable, highlightMessageQuote != null ? 2500 : 1000); } private void removeSelectedMessageHighlight() { if (highlightMessageQuote != null || highlightTaskId != null) { return; } if (unselectRunnable != null) { AndroidUtilities.cancelRunOnUIThread(unselectRunnable); unselectRunnable = null; } highlightMessageId = Integer.MAX_VALUE; highlightMessageQuoteFirst = false; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = null; highlightTaskId = null; } private AlertDialog progressDialog; private int nextScrollToMessageId; private int nextScrollFromMessageId; private boolean nextScrollSelect; private int nextScrollLoadIndex; private boolean nextScrollForce; private int nextScrollForcePinnedMessageId; public static final int PROGRESS_REPLY = 0; public static final int PROGRESS_LINK = 1; public static final int PROGRESS_INSTANT = 2; public static final int PROGRESS_BOT_BUTTON = 3; public static final int PROGRESS_GIFT = 4; public static final int PROGRESS_PAID_MEDIA = 5; public static final int PROGRESS_FORWARD = 6; private int progressDialogAtMessageId; private int progressDialogAtMessageType; private CharacterStyle progressDialogLinkSpan; private String progressDialogBotButtonUrl; private Browser.Progress progressDialogCurrent; private void resetProgressDialogLoading() { progressDialogLinkSpan = null; progressDialogAtMessageId = 0; progressDialogAtMessageType = -1; progressDialogBotButtonUrl = null; progressDialogCurrent = null; sideControlsButtonsLayout.setButtonLoading(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, false, true); } public static final boolean SCROLL_DEBUG_DELAY = false; private boolean pinnedProgressIsShowing; Runnable updatePinnedProgressRunnable; public void scrollToMessageId(int id, int fromMessageId, boolean select, int loadIndex, boolean forceScroll, int forcePinnedMessageId) { scrollToMessageId(id, fromMessageId, select, loadIndex, forceScroll, forcePinnedMessageId, null, null); } public void scrollToMessageId(int id, int fromMessageId, boolean select, int loadIndex, boolean forceScroll, int forcePinnedMessageId, Integer taskId, Runnable inCaseLoading) { if (waitingForGetDifference) { return; } 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 = chatAdapter.isFiltered ? (filteredMessagesDict != null ? filteredMessagesDict.get(id) : null) : 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 (chatAdapter.getMessages().size() > 0) { if (isThreadChat() && id == threadMessageId) { scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; } else { int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { MessageObject messageObject = chatAdapter.getMessages().get(i - chatAdapter.messagesStartRow); if (messageObject.getId() == 0 || messageObject.isSponsored()) { 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 (!SCROLL_DEBUG_DELAY && 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 = chatAdapter.getMessages().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; highlightTaskId = taskId; } chatAdapter.updateRowsSafe(); int position = chatAdapter.messagesStartRow + chatAdapter.getMessages().indexOf(object); updateVisibleRows(); boolean found = false; int offsetY = 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 messageObject = cell.getMessageObject(); if (messageObject != null && messageObject.getId() == object.getId()) { found = true; view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); offsetY = scrollOffsetForQuote(messageObject); } } 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()) - offsetY; 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(chatScrollHelperCallback.position = position, chatScrollHelperCallback.offset = yOffset, chatScrollHelperCallback.bottom = 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); if (inCaseLoading != null) { inCaseLoading.run(); } else if (forceNextPinnedMessageId == 0) { progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, 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; fakePostponedScroll = false; postponedScrollMinMessageId = minMessageId[0]; postponedScrollMessageId = id; getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, 0, false, ((isThreadChat() && !isTopic) || AndroidUtilities.isTablet()) ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } else { View child = chatListView.getChildAt(0); if (child != null && child.getTop() <= 0) { showFloatingDateView(false); showFloatingTopicView(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 (sideControlsButtonsLayout == null) { return; } boolean show = canShowPagedownButton && !textSelectionHelper.isInSelectionMode() && !chatActivityEnterView.isRecordingAudioVideo() && !isInsideContainer && (!searching || getMediaDataController().searchResultMessages.isEmpty()); if (show) { if (animated && (openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150)) { animated = false; } pagedownButtonShowedByScroll = false; } else { returnToMessageId = 0; newUnreadMessageCount = 0; } sideControlsButtonsLayout.showButton(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, show, animated); } private void updateSearchUpDownButtonVisibility(boolean animated) { if (sideControlsButtonsLayout == null) { return; } boolean show = !getMediaDataController().searchResultMessages.isEmpty() && searching && !searchingFiltered || chatMode == MODE_SEARCH && searchType == SEARCH_PUBLIC_POSTS && !messages.isEmpty(); sideControlsButtonsLayout.showButton(ChatActivitySideControlsButtonsLayout.BUTTON_SEARCH_UP, show, animated); sideControlsButtonsLayout.showButton(ChatActivitySideControlsButtonsLayout.BUTTON_SEARCH_DOWN, show, animated); if (show) { sideControlsButtonsLayout.showButton(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, false, animated); } if (!show) { returnToMessageId = 0; } contentView.invalidate(); } private void showMentionDownButton(boolean show, boolean animated) { if (sideControlsButtonsLayout == null) { return; } sideControlsButtonsLayout.showButton(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, show && !ChatObject.isMonoForum(currentChat), animated); if (!show) { returnToMessageId = 0; } } private boolean shouldHaveLightNavigationBarIcons; public boolean isShouldHaveLightNavigationBarIcons() { return shouldHaveLightNavigationBarIcons && (!windowInsetsStateHolder.inAppViewIsVisible() || themeDelegate != null && themeDelegate.isDark); } public class ChatActivityFragmentView extends SizeNotifierFrameLayout { public ChatActivity getChatActivity() { return ChatActivity.this; } public ChatActivityFragmentView(Context context, INavigationLayout parentLayout) { super(context, parentLayout); 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); } if (factCheckHint != null) { factCheckHint.hide(); } } @Override protected void onTransitionEnd() { if (chatActivityEnterView != null) { chatActivityEnterView.onAdjustPanTransitionEnd(); } if (mentionContainer != null) { // mentionContainer.onPanTransitionEnd(); } if (voiceHintTextView != null && voiceHintTextView.getVisibility() == View.VISIBLE) { voiceHintTextView.showForView(chatActivityEnterView.getAudioVideoButtonContainer(), false); } } @Override protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { return; } contentPanTranslation = y; contentPanTranslationT = progress; if (contentView != null) { contentView.updateBlurContent(); } if (chatAttachAlert != null && chatAttachAlert.isShowing()) { setNonNoveTranslation(y); } else { actionBar.setTranslationY(y); if (tagSelector != null) { tagSelector.setTranslationY(contentPanTranslation + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); } if (savedMessagesSearchHint != null) { savedMessagesSearchHint.setTranslationY(y); } if (savedMessagesHint != null) { savedMessagesHint.setTranslationY(y); } if (actionBarSearchTags != null) { actionBarSearchTags.setTranslationY(y); } if (topicsTabs != null) { topicsTabs.setTranslationY(y); } if (hashtagSearchTabs != null) { hashtagSearchTabs.setTranslationY(y); } if (emptyViewContainer != null) { emptyViewContainer.setTranslationY(y / 2); } if (hashtagHistoryView != null) { hashtagHistoryView.setTranslationY(getHashtagTabsHeight() + y); hashtagHistoryView.emptyView.setTranslationY(-y / 2); } if (messagesSearchListContainer != null) { messagesSearchListContainer.setTranslationY(getHashtagTabsHeight() + y); } if (hashtagSearchEmptyView != null) { hashtagSearchEmptyView.setTranslationY(-y / 2); } if (searchViewPager != null) { View page = searchViewPager.getCurrentView(); if (page instanceof ChatActivityContainer) { ChatActivity child = ((ChatActivityContainer) page).chatActivity; if (child.messagesSearchListContainer != null) { child.messagesSearchListContainer.setTranslationY(getHashtagTabsHeight() + y); } if (child.hashtagSearchEmptyView != null) { child.hashtagSearchEmptyView.setTranslationY(-y / 2); } } } progressView.setTranslationY(y / 2); contentView.setBackgroundTranslation((int) y); if (instantCameraView != null) { 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); } if (AndroidUtilities.isTablet() && getParentActivity() instanceof LaunchActivity) { BaseFragment mainFragment = ((LaunchActivity)getParentActivity()).getActionBarLayout().getLastFragment(); if (mainFragment instanceof DialogsActivity) { ((DialogsActivity)mainFragment).setPanTranslationOffset(y); } } if (voiceHintTextView != null && voiceHintTextView.getVisibility() == View.VISIBLE) { voiceHintTextView.showForView(chatActivityEnterView.getAudioVideoButtonContainer(), false); } if (fragmentContextView != null) { fragmentContextView.onPanTranslationUpdate(y); } } @Override protected boolean heightAnimationEnabled() { INavigationLayout actionBarLayout = getParentLayout(); if (isInsideContainer || 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 public void drawBlurRect(Canvas canvas, float y, Rect rectTmp, Paint blurScrimPaint, boolean top) { int blurAlpha = Color.alpha(Theme.getColor(SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH ? Theme.key_chat_BlurAlpha : Theme.key_chat_BlurAlphaSlow, getResourceProvider())); final BlurredBackgroundSource blurSource = glassBackgroundSourceFrostedRenderNode; if (blurSource != null && blurAlpha < 255) { canvas.save(); canvas.translate(0, -y); blurSource.draw(canvas, rectTmp.left, rectTmp.top + y, rectTmp.right, rectTmp.bottom + y ); canvas.restore(); } else { blurAlpha = 255; } final int oldScrimAlpha = blurScrimPaint.getAlpha(); blurScrimPaint.setAlpha(blurAlpha); canvas.drawRect(rectTmp, blurScrimPaint); blurScrimPaint.setAlpha(oldScrimAlpha); } @Override public void onUpdateBackgroundDrawable(Drawable drawable) { super.onUpdateBackgroundDrawable(drawable); if (drawable instanceof MotionBackgroundDrawable) { ((MotionBackgroundDrawable) drawable).setFastRenderAllowed(); } final BlurredBackgroundSource source = wallpaperBitmapProvider.updateSourceFromBackgroundViewDrawable(drawable); final int navigationBarColor = wallpaperBitmapProvider.getNavigationBarColor(source); final float brightness = AndroidUtilities.computePerceivedBrightness(navigationBarColor); final boolean isDark = brightness <= 0.9f; shouldHaveLightNavigationBarIcons = isDark; navbarContentSourceWallpaper.setSource(source); if (chatInputViewsContainer != null) { chatInputViewsContainer.invalidate(); chatInputViewsContainer.getFadeView().invalidate(); } invalidateAllGlassAttachedViews(); checkSystemBarColors(); } int inputFieldHeight = 0; int lastHeight; int lastWidth; ArrayList drawTimeAfter = new ArrayList<>(); ArrayList drawNamesAfter = new ArrayList<>(); ArrayList drawCaptionAfter = new ArrayList<>(); ArrayList drawReactionsAfter = new ArrayList<>(); Paint backgroundPaint; int backgroundColor; @Override protected boolean invalidateOptimized() { return true; } private final RectF tmpViewRectF = new RectF(); public void drawList(Canvas blurCanvas, RectF position) { final long drawingTime = SystemClock.uptimeMillis(); blurCanvas.save(); blurCanvas.clipRect(position); blurCanvas.translate(0, chatListView.getY()); chatListView.drawChatBackgroundElements(blurCanvas); for (int i = 0; i < chatListView.getChildCount(); i++) { View child = chatListView.getChildAt(i); tmpViewRectF.set(child.getX(), child.getY() + chatListView.getY(), child.getX() + child.getWidth(), child.getY() + chatListView.getY() + child.getHeight()); if (!tmpViewRectF.intersect(position)) { continue; } if (child instanceof ChatMessageCell) { blurCanvas.save(); blurCanvas.translate(child.getX(), child.getY()); ChatMessageCell cell = (ChatMessageCell) child; if (cell.drawBackgroundInParent()) { blurCanvas.save(); blurCanvas.translate(0, cell.starsPriceTopPadding); cell.drawBackgroundInternal(blurCanvas, true); blurCanvas.restore(); } blurCanvas.restore(); chatListView.drawChild(blurCanvas, child, drawingTime); if (cell.hasOutboundsContent()) { blurCanvas.save(); blurCanvas.translate(cell.getX(), cell.getY()); cell.drawOutboundsContent(blurCanvas); blurCanvas.restore(); } } else if (child instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) child; chatListView.drawChild(blurCanvas, child, drawingTime); blurCanvas.save(); blurCanvas.translate(child.getX(), child.getY()); cell.drawOutboundsContent(blurCanvas); blurCanvas.restore(); } else { chatListView.drawChild(blurCanvas, child, drawingTime); } } chatListView.drawChatForegroundElements(blurCanvas); blurCanvas.restore(); } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { super.addView(child, index, params); if (chatActivityEnterView != null && child == chatActivityEnterView.botCommandsMenuContainer) { BotCommandsMenuContainer botCommandsMenuContainer = (BotCommandsMenuContainer) child; final BlurredBackgroundDrawable drawable = glassBackgroundDrawableFactory.create(botCommandsMenuContainer.listView, blurredBackgroundColorProviderWhite); botCommandsMenuContainer.setBackgroundDrawable(drawable); } if (chatActivityEnterView != null && child == chatActivityEnterView.controlsView) { chatActivityEnterView.controlsView.setBlurredBackgroundFactory(glassBackgroundDrawableFactory); } } @Override protected int getScrollOffset() { return chatListView.computeVerticalScrollOffset(); } @Override protected float getBottomOffset() { return chatListView.getBottom(); } @Override protected float getListTranslationY() { return chatListView.getTranslationY(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (isInsideContainer) { adjustPanLayoutHelper.setResizableView(contentView); } else if (parentLayout != null && parentLayout.isSheet()) { adjustPanLayoutHelper.setResizableView((FrameLayout) parentLayout.getView().getParent().getParent().getParent().getParent()); } 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; private boolean pressActionBar; @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 && scrimView != actionBar.getBackButton()) || chatActivityEnterView != null && chatActivityEnterView.isStickersExpanded() && ev.getY() < expandY) { return false; } lastTouchY = ev.getY(); TextSelectionHelper.TextSelectionOverlay selectionOverlay = textSelectionHelper.getOverlayView(getContext()); ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); if (textSelectionHelper.isInSelectionMode() && textSelectionHelper.getOverlayView(getContext()).onTouchEvent(ev)) { return true; } else { ev.offsetLocation(selectionOverlay.getX(), selectionOverlay.getY()); } if (selectionOverlay.checkOnTap(ev)) { ev.setAction(MotionEvent.ACTION_CANCEL); } boolean r = false; if (searchViewPager != null) { if (searchingHashtag != null && !hashtagHistoryView.isShowing()) { r = searchViewPager.onTouchEventInternal(ev) || r; if (searchViewPager.isTouch()) { ev.setAction(MotionEvent.ACTION_CANCEL); } } else { searchViewPager.resetTouch(); } } if (ev.getAction() == MotionEvent.ACTION_DOWN && textSelectionHelper.isInSelectionMode() && (ev.getY() < chatListView.getTop() || ev.getY() > chatListView.getBottom())) { ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); if (textSelectionHelper.getOverlayView(getContext()).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; } if (isInPreviewMode() && allowExpandPreviewByClick) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { boolean pressedOnPageDownButtons = false, pressedOnAction = false; int[] off = new int[2]; getLocationInWindow(off); int[] pos = new int[2]; if (sideControlsButtonsLayout != null) { for (int a = 0; a < 3; a++) { final int buttonId = a == 0 ? ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN: a == 1 ? ChatActivitySideControlsButtonsLayout.BUTTON_MENTION: ChatActivitySideControlsButtonsLayout.BUTTON_REACTIONS; if (sideControlsButtonsLayout.getButtonLocationInWindow(buttonId, pos)) { AndroidUtilities.rectTmp2.set(pos[0] - off[0], pos[1] - off[1], pos[0] - off[0] + dp(56), pos[1] - off[1] + dp(61)); if (AndroidUtilities.rectTmp2.contains((int) ev.getX(), (int) ev.getY())) { pressedOnPageDownButtons = true; break; } } } } if (avatarContainer != null) { avatarContainer.getLocationInWindow(pos); AndroidUtilities.rectTmp2.set(pos[0] - off[0], pos[1] - off[1], pos[0] - off[0] + avatarContainer.getMeasuredWidth(), pos[1] - off[1] + avatarContainer.getMeasuredHeight()); if (AndroidUtilities.rectTmp2.contains((int) ev.getX(), (int) ev.getY())) { pressedOnAction = true; } } if (!pressedOnPageDownButtons) { x = ev.getX(); y = ev.getY(); pressTime = SystemClock.elapsedRealtime(); pressActionBar = pressedOnAction; if (avatarContainer != null) { avatarContainer.bounce.setPressed(pressActionBar); } r = true; } else { pressTime = -1; } } else if (ev.getAction() == MotionEvent.ACTION_UP) { if (avatarContainer != null) { avatarContainer.bounce.setPressed(false); } if (pressActionBar || MathUtils.distance(x, y, ev.getX(), ev.getY()) < AndroidUtilities.dp(6) && SystemClock.elapsedRealtime() - pressTime <= ViewConfiguration.getTapTimeout()) { if (pressActionBar) { final INavigationLayout layout = parentLayout; removeSelfFromStack(false); layout.presentFragment(ProfileActivity.of(dialog_id)); } else { 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 && (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 == sideControlsButtonsLayout || child == floatingDateView || child == floatingTopicSeparator || child == fireworksOverlay || child == quickShareSelectorOverlay || child == gifHintTextView || child == emojiHintTextView || 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 (switchingFromTopics && child == actionBar) { return true; } if (child == instantCameraView) { 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 == chatInputViewsContainer || child == bottomChannelButtonsLayout; } if (!needBlur) { return false; } } else if (getTag(BlurBehindDrawable.TAG_DRAWING_AS_BACKGROUND) == null && ((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(isSideMenued()) + AndroidUtilities.dp(6), y + AndroidUtilities.roundPlayingMessageSize(isSideMenued()) + 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 { if (child == chatInputViewsContainer && instantCameraView != null && instantCameraView.getVisibility() == VISIBLE) { super.drawChild(canvas, instantCameraView, drawingTime); } result = super.drawChild(canvas, child, drawingTime); if (isVideo && child == chatListView && messageObject.type != MessageObject.TYPE_ROUND_VIDEO && 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() + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0) + (hashtagSearchTabs != null ? hashtagSearchTabs.getCurrentHeight() : 0) : 0); } return result; } @Override protected boolean isActionBarVisible() { return actionBar.getVisibility() == VISIBLE; } private void drawChildElement(Canvas canvas, float listTop, ChatMessageCell cell, int type) { int restoreCount = canvas.save(); float canvasOffsetX = chatListView.getLeft() + cell.getX(); float canvasOffsetY = chatListView.getY() + cell.getY() + cell.getPaddingTop(); float alpha = cell.shouldDrawAlphaLayer() ? cell.getAlpha() : 1f; canvas.clipRect(chatListView.getLeft(), listTop, chatListView.getRight(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset - windowInsetsStateHolder.getCurrentMaxBottomInset() - inputIslandHeightCurrent - dp(9)); canvas.translate(canvasOffsetX, canvasOffsetY); cell.setInvalidatesParent(true); if (type == 0) { cell.drawTime(canvas, alpha, true); } else if (type == 1) { cell.drawNamesLayout(canvas, alpha); } else if (type == 2) { cell.drawCaptionLayout(canvas, cell.getCurrentPosition() != null && (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0, alpha); } else if (type == 3) { final boolean selectionOnly = cell.getCurrentPosition() != null && (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0; cell.drawCommentLayout(canvas, alpha); if (!selectionOnly) { cell.drawReactionsLayout(canvas, alpha, null); } } else if (type == 4) { final boolean selectionOnly = cell.getCurrentPosition() != null && (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0; if (!selectionOnly) { if (scrimViewReaction != null) { final float scrimProgress = scrimPaintAlpha * scrimViewAlpha / 0.2f; canvas.save(); cell.drawScrimReaction(canvas, scrimViewReaction, scrimProgress, scrimProgressDirection); canvas.restore(); canvas.restore(); canvas.save(); canvas.translate(canvasOffsetX, canvasOffsetY); cell.drawScrimReactionPreview(this, canvas, scrimViewReactionOffset, scrimViewReaction, scrimProgress); canvas.restore(); } } } cell.setInvalidatesParent(false); canvas.restoreToCount(restoreCount); } @Override protected void dispatchDraw(Canvas canvas) { final int width = getMeasuredWidth(); final int height = getMeasuredHeight(); if (Build.VERSION.SDK_INT >= 31 && canvas.isHardwareAccelerated() && scrollableViewNoiseSuppressor != null) { if (navbarContentSourceMessages != null && !navbarContentSourceMessages.inRecording()) { if (navbarContentSourceMessages.needUpdateDisplayList(width, height) || glassSourcesInvalidated) { final Canvas c = navbarContentSourceMessages.beginRecording(width, height); scrollableViewNoiseSuppressor.draw(c, DownscaleScrollableNoiseSuppressor.DRAW_FROSTED_GLASS_NO_SATURATION); navbarContentSourceMessages.endRecording(); } } if (navbarContentSourceWallpaperAndMessagesRenderNode != null && !navbarContentSourceWallpaperAndMessagesRenderNode.inRecording() && navbarContentSourceMessagesDrawable != null) { if (navbarContentSourceWallpaperAndMessagesRenderNode.needUpdateDisplayList(width, height) || glassSourcesInvalidated) { final Canvas c = navbarContentSourceWallpaperAndMessagesRenderNode.beginRecording(width, height); navbarContentSourceWallpaper.draw(c, 0, 0, width, height); navbarContentSourceMessagesDrawable.setBounds(0, 0, width, height); navbarContentSourceMessagesDrawable.setAlpha(themeDelegate != null && themeDelegate.isDark() ? 80 : 180); navbarContentSourceMessagesDrawable.draw(c); navbarContentSourceWallpaperAndMessagesRenderNode.endRecording(); } } if (glassBackgroundSourceRenderNode != null && !glassBackgroundSourceRenderNode.inRecording()) { if (glassBackgroundSourceRenderNode.needUpdateDisplayList(width, height) || glassSourcesInvalidated) { final Canvas c = glassBackgroundSourceRenderNode.beginRecording(width, height); navbarContentSourceWallpaper.draw(c, 0, 0, width, height); scrollableViewNoiseSuppressor.draw(c, DownscaleScrollableNoiseSuppressor.DRAW_GLASS); glassBackgroundSourceRenderNode.endRecording(); } } if (glassBackgroundSourceFrostedRenderNode != null && !glassBackgroundSourceFrostedRenderNode.inRecording()) { if (glassBackgroundSourceFrostedRenderNode.needUpdateDisplayList(width, height) || glassSourcesInvalidated) { final Canvas c = glassBackgroundSourceFrostedRenderNode.beginRecording(width, height); navbarContentSourceWallpaper.draw(c, 0, 0, width, height); scrollableViewNoiseSuppressor.draw(c, DownscaleScrollableNoiseSuppressor.DRAW_FROSTED_GLASS); glassBackgroundSourceFrostedRenderNode.endRecording(); } } glassSourcesInvalidated = false; } chatActivityEnterView.checkAnimation(); updateChatListViewTopPadding(); if (invalidateMessagesVisiblePart || (chatListItemAnimator != null && chatListItemAnimator.isRunning())) { invalidateMessagesVisiblePart = false; updateMessagesVisiblePart(false); } updateTextureViewPosition(false, false); updatePagedownButtonsPosition(); if (scheduledOrNoSoundHint != null && scheduledOrNoSoundHint.isShowing()) { scheduledOrNoSoundHint.updatePosition(); } if (scheduledHint != null && scheduledHint.isShowing()) { scheduledHint.updatePosition(); } int restoreToCount = -1; if (switchingFromTopics) { restoreToCount = canvas.saveLayerAlpha(0, actionBar.getBottom(), getMeasuredWidth(), getMeasuredHeight(), (int) (255 * switchingFromTopicsProgress), Canvas.ALL_SAVE_FLAG); float s = 0.8f + 0.2f * switchingFromTopicsProgress; canvas.scale(s, s, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); } 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(); } fragmentView.invalidate(); } 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(); final int actionBarBottom = actionBar.getVisibility() == VISIBLE ? (int) actionBar.getTranslationY() + actionBar.getMeasuredHeight() + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0) + (hashtagSearchTabs != null ? hashtagSearchTabs.getCurrentHeight() : 0) + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0) : 0; canvas.clipRect(0, actionBarBottom + paddingTopHeight, getWidth(), getHeight()); ImageReceiver imageReceiver = cell.getPhotoImage(); cell.getLocationInWindow(AndroidUtilities.pointTmp2); int finalY = AndroidUtilities.pointTmp2[1]; finalY -= cell.getTranslationY() * (1.0f - data.progress); finalY += chatActivityEnterView.topViewVisible() * AndroidUtilities.dp(48); if (!data.fromPreview) { canvas.translate(data.currentX, lerp(data.y, finalY + imageReceiver.getCenterY(), data.progress)); } else { canvas.translate(data.currentX, lerp(data.y, finalY, data.progress)); } canvas.scale(data.currentScale, data.currentScale); if (!data.fromPreview) { canvas.translate(-imageReceiver.getCenterX(), -imageReceiver.getCenterY()); } cell.setTimeAlpha(data.timeAlpha); cell.draw(canvas); canvas.restore(); } } if (scrimViewReaction == null || scrimView == null) { if (scrimBlurBitmapPaint != null) { scrimBlurMatrix.reset(); final float s = (float) getMeasuredWidth() / scrimBlurBitmap.getWidth(); scrimBlurMatrix.postScale(s, s); scrimBlurBitmapShader.setLocalMatrix(scrimBlurMatrix); scrimBlurBitmapPaint.setAlpha((int) (0xFF * scrimViewProgress)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimBlurBitmapPaint); } else { scrimPaint.setAlpha((int) (0xFF * scrimPaintAlpha * (scrimView != null ? scrimViewAlpha : 1f))); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } } if (scrimViewReaction != null && scrimViewReactionAnimated) { invalidate(); } if (scrimView != null) { if (scrimView == sideControlsButtonsLayout) { 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; ChatActionCell actionCell; if (child instanceof ChatMessageCell) { cell = (ChatMessageCell) child; actionCell = null; group = cell.getCurrentMessagesGroup(); position = cell.getCurrentPosition(); } else { position = null; group = null; cell = null; actionCell = child instanceof ChatActionCell ? ((ChatActionCell) child) : 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(); float viewClipBottom2 = getMeasuredHeight() - windowInsetsStateHolder.getCurrentMaxBottomInset() - inputIslandHeightCurrent - dp(9) - (mentionContainer != null ? mentionContainer.clipBottom() : 0); canvas.clipRect(0, listTop + (mentionContainer != null ? mentionContainer.clipTop() : 0), getMeasuredWidth(), viewClipBottom2); 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, 0); canvas.restore(); groupedBackgroundWasDraw = true; } if (cell != null && cell.getPhotoImage().isAnimationRunning()) { invalidate(); } float viewClipLeft = chatListView.getLeft(); float viewClipTop = listTop; float viewClipRight = chatListView.getRight(); float viewClipBottom = getMeasuredHeight() - windowInsetsStateHolder.getCurrentMaxBottomInset() - inputIslandHeightCurrent - dp(9); float clipTop = 0, clipBottom = 0; if (mentionContainer != null) { clipTop = Math.max(clipTop, mentionContainer.clipTop()); clipBottom = Math.max(clipBottom, mentionContainer.clipBottom()); } if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuContainer != null) { clipBottom = Math.max(clipBottom, chatActivityEnterView.botCommandsMenuContainer.clipBottom()); } viewClipTop += clipTop; viewClipBottom -= clipBottom; if (cell == null || !cell.getTransitionParams().animateBackgroundBoundsInner) { viewClipLeft = Math.max(viewClipLeft, chatListView.getLeft() + child.getX()); viewClipTop = Math.max(viewClipTop, chatListView.getY() + child.getY()); viewClipRight = Math.min(viewClipRight, chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); viewClipBottom = Math.min(viewClipBottom, chatListView.getY() + child.getY() + child.getMeasuredHeight()); } viewClipLeft = Math.max(viewClipLeft, getSideMenuWidth()); if (scrimViewTask != null) { final int index = cell.getTodoIndex(scrimViewTask); viewClipTop = Math.max(viewClipTop, chatListView.getY() + cell.getY() + cell.getPollButtonTop(index)); viewClipBottom = Math.min(viewClipBottom, chatListView.getY() + cell.getY() + cell.getPollButtonBottom(index)); } 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); } else if (actionCell != null) { actionCell.setInvalidatesParent(true); actionCell.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()) { canvas.save(); canvas.translate(0, cell.getPaddingTop()); cell.drawBackgroundInternal(canvas, true); canvas.restore(); } child.draw(canvas); if (cell != null && cell.hasOutboundsContent()) { canvas.save(); canvas.translate(0, cell.getPaddingTop()); cell.drawOutboundsContent(canvas); canvas.restore(); } if (actionCell != null) { actionCell.drawOutboundsContent(canvas); } canvas.restore(); if (cell != null) { cell.setInvalidatesParent(false); cell.setScrimReaction(null); } else if (actionCell != null) { actionCell.setInvalidatesParent(false); actionCell.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 & cell.captionFlag()) != 0) { drawCaptionAfter.add(cell); } if (position == null || (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (position.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { drawReactionsAfter.add(cell); } } if (scrimViewReaction != null && cell != null && scrimGroup == null) { if (scrimBlurBitmapPaint != null) { scrimBlurMatrix.reset(); final float s = (float) getMeasuredWidth() / scrimBlurBitmap.getWidth(); scrimBlurMatrix.postScale(s, s); scrimBlurBitmapShader.setLocalMatrix(scrimBlurMatrix); scrimBlurBitmapPaint.setAlpha((int) (0xFF * scrimViewProgress)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimBlurBitmapPaint); } else { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } if (viewClipTop < viewClipBottom) { final float scrimProgress = scrimPaintAlpha * scrimViewAlpha / 0.2f; 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() + child.getPaddingTop()); cell.drawScrimReaction(canvas, scrimViewReaction, scrimProgress, scrimProgressDirection); canvas.restore(); canvas.save(); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY() + child.getPaddingTop()); cell.drawScrimReactionPreview(this, canvas, scrimViewReactionOffset, scrimViewReaction, scrimProgress); canvas.restore(); } } else if (scrimViewReaction != null && actionCell != null) { if (scrimBlurBitmapPaint != null) { scrimBlurMatrix.reset(); final float s = (float) getMeasuredWidth() / scrimBlurBitmap.getWidth(); scrimBlurMatrix.postScale(s, s); scrimBlurBitmapShader.setLocalMatrix(scrimBlurMatrix); scrimBlurBitmapPaint.setAlpha((int) (0xFF * scrimViewProgress)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimBlurBitmapPaint); } else { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } if (viewClipTop < viewClipBottom) { final float scrimProgress = scrimPaintAlpha * scrimViewAlpha / 0.2f; 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() + child.getPaddingTop()); actionCell.drawScrimReaction(canvas, scrimViewReaction, scrimProgress, scrimProgressDirection); canvas.restore(); canvas.save(); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY() + child.getPaddingTop()); actionCell.drawScrimReactionPreview(this, canvas, scrimViewReactionOffset, scrimViewReaction, scrimProgress); 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(); } size = drawReactionsAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawReactionsAfter.get(a); if (cell.getCurrentPosition() == null && !cell.getTransitionParams().animateBackgroundBoundsInner) { continue; } drawChildElement(canvas, listTop, cell, 3); } } if (scrimViewReaction != null && scrimGroup != null) { if (scrimBlurBitmapPaint != null) { scrimBlurMatrix.reset(); final float s = (float) getMeasuredWidth() / scrimBlurBitmap.getWidth(); scrimBlurMatrix.postScale(s, s); scrimBlurBitmapShader.setLocalMatrix(scrimBlurMatrix); scrimBlurBitmapPaint.setAlpha((int) (0xFF * scrimViewProgress)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimBlurBitmapPaint); } else { scrimPaint.setAlpha((int) (255 * scrimPaintAlpha * scrimViewAlpha)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); } } size = drawReactionsAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { ChatMessageCell cell = drawReactionsAfter.get(a); if (cell.getCurrentPosition() == null && !cell.getTransitionParams().animateBackgroundBoundsInner) { continue; } drawChildElement(canvas, listTop, cell, 4); } drawReactionsAfter.clear(); } } if (scrimViewReaction == null && scrimViewAlpha < 1f) { if (scrimBlurBitmapPaint != null) { scrimBlurMatrix.reset(); final float s = (float) getMeasuredWidth() / scrimBlurBitmap.getWidth(); scrimBlurMatrix.postScale(s, s); scrimBlurBitmapShader.setLocalMatrix(scrimBlurMatrix); scrimBlurBitmapPaint.setAlpha((int) (0xFF * scrimViewProgress)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimBlurBitmapPaint); } else { 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) { super.drawChild(canvas, sideControlsButtonsLayout, SystemClock.uptimeMillis()); } if (floatingDateView != null && floatingDateView.getTag() != null) { super.drawChild(canvas, floatingDateView, SystemClock.uptimeMillis()); } if (floatingTopicSeparator != null && floatingTopicSeparator.getTag() != null) { super.drawChild(canvas, floatingTopicSeparator, SystemClock.uptimeMillis()); } if (fireworksOverlay != null) { super.drawChild(canvas, fireworksOverlay, SystemClock.uptimeMillis()); } if (quickShareSelectorOverlay != null) { super.drawChild(canvas, quickShareSelectorOverlay, SystemClock.uptimeMillis()); } if (gifHintTextView != null) { super.drawChild(canvas, gifHintTextView, SystemClock.uptimeMillis()); } if (emojiHintTextView != null) { super.drawChild(canvas, emojiHintTextView, SystemClock.uptimeMillis()); } if (undoView != null && undoView.getVisibility() == View.VISIBLE) { super.drawChild(canvas, undoView, SystemClock.uptimeMillis()); } if (topUndoView != null && topUndoView.getVisibility() == View.VISIBLE) { super.drawChild(canvas, topUndoView, SystemClock.uptimeMillis()); } if (savedMessagesTagHint != null && savedMessagesTagHint.getVisibility() == View.VISIBLE) { super.drawChild(canvas, savedMessagesTagHint, SystemClock.uptimeMillis()); } if (videoConversionTimeHint != null && videoConversionTimeHint.getVisibility() == View.VISIBLE) { super.drawChild(canvas, videoConversionTimeHint, SystemClock.uptimeMillis()); } if (botMessageHint != null && botMessageHint.getVisibility() == View.VISIBLE) { super.drawChild(canvas, botMessageHint, SystemClock.uptimeMillis()); } if (chatActivityEnterView != null && chatActivityEnterView.birthdayHint != null) { canvas.save(); canvas.translate(chatActivityEnterView.getX() + chatActivityEnterView.birthdayHint.getX(), chatActivityEnterView.getY() + chatActivityEnterView.birthdayHint.getY()); chatActivityEnterView.birthdayHint.draw(canvas); canvas.restore(); } } 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; top = (int) chatInputViewsContainer.getInputBubbleTop(); bottom = (int) chatInputViewsContainer.getInputBubbleBottom(); 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); if (restoreToCount >= 0) { canvas.restore(); } if (switchingFromTopics) { canvas.save(); canvas.translate(actionBar.getX(), actionBar.getY()); canvas.saveLayerAlpha(0, 0, actionBar.getWidth(), actionBar.getHeight(), (int) (255 * switchingFromTopicsProgress), Canvas.ALL_SAVE_FLAG); actionBar.draw(canvas); canvas.restore(); canvas.restore(); } /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && scrollableViewNoiseSuppressor != null) { scrollableViewNoiseSuppressor.drawDebugPositions(canvas); }*/ } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { invalidateBlurredSourcesView.bringToFrontIfNeeded(); int allHeight; int widthSize = View.MeasureSpec.getSize(widthMeasureSpec); int heightSize = allHeight = View.MeasureSpec.getSize(heightMeasureSpec); if (navbarContentSourceWallpaper.getSource() instanceof BlurredBackgroundSourceBitmap) { ((BlurredBackgroundSourceBitmap) navbarContentSourceWallpaper.getSource()) .setParentSize(widthSize, heightSize, ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight); } if (lastWidth != widthSize) { globalIgnoreLayout = false; 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 if (chatMode == MODE_SUGGESTIONS) { showSearchAsIcon = true; }*/ else { showSearchAsIcon = false; } if (showSearchAsIcon || showAudioCallAsIcon) { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { ((ViewGroup.MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin = AndroidUtilities.dp(chatMode == MODE_SAVED ? 40 : 96); } } else { if (avatarContainer != null && avatarContainer.getLayoutParams() != null) { ((ViewGroup.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(); if (webBotTitle != null) { ((LayoutParams) webBotTitle.getLayoutParams()).topMargin = AndroidUtilities.statusBarHeight; webBotTitle.setTextSize(!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 18 : 20); } 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(isSideMenued()))) / 2), false); chatAdapter.notifyItemChanged(p); adjustPanLayoutHelper.delayAnimation(); waitingChatListItemAnimator = true; break; } } } } } if (!waitingChatListItemAnimator) { chatActivityEnterView.runEmojiPanelAnimation(); } int childCount = getChildCount(); measureChildWithMargins(chatActivityEnterView, widthMeasureSpec, 0, heightMeasureSpec, 0); if (inPreviewMode || isInsideContainer) { inputFieldHeight = 0; } else { inputFieldHeight = chatActivityEnterView.getMeasuredHeight(); } blurredViewTopOffset = 0; blurredViewBottomOffset = 0; if (SharedConfig.chatBlurEnabled() && !isInsideContainer) { if (scrollableViewNoiseSuppressor != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { blurredViewTopOffset = actionBarHeight + recommendedAdditionalSizeY; blurredViewBottomOffset = recommendedAdditionalSizeY; } } 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 = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight, View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == blurredView) { int h = allHeight; int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == chatListView || child == chatListThanosEffect) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int h = heightSize + blurredViewTopOffset + blurredViewBottomOffset + chatListViewPaddingsAnimator.getCurrentAdditionalHeight(); int contentHeightSpec = MeasureSpec.makeMeasureSpec( Math.max(dp(10), h), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == progressView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - inputFieldHeight - (inPreviewMode ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.dp(2 + (chatActivityEnterView.isTopViewVisible() ? 48 : 0))), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == instantCameraView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight, View.MeasureSpec.EXACTLY); instantCameraView.setInternalPadding(windowInsetsStateHolder.getCurrentMaxBottomInset() + (int) inputIslandHeightTarget + dp(9 + 3)); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == overlayView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - windowInsetsStateHolder.getCurrentMaxBottomInset() - (int) inputIslandHeightTarget - dp(9 + 3), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == emptyViewContainer) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == messagesSearchListContainer) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - (isInsideContainer ? 0 : actionBarHeight) - AndroidUtilities.dp(44 + 9 + 1) // input field with margins - windowInsetsStateHolder.getCurrentNavigationBarInset(), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (chatActivityEnterView.isPopupView(child)) { int height = chatActivityEnterView.getPopupViewHeight(child); if (inBubbleMode) { int maxHeight = (heightSize - inputFieldHeight + actionBarHeight + getPaddingTop()); if (height < 0) { height = Math.max(Math.min(maxHeight, AndroidUtilities.dp(350)), maxHeight / 2); } child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); } else if (AndroidUtilities.isInMultiwindow) { int maxHeight = (heightSize - inputFieldHeight + actionBarHeight - AndroidUtilities.statusBarHeight + getPaddingTop()); if (height < 0) { height = Math.max(Math.min(maxHeight, AndroidUtilities.dp(350)), maxHeight / 2); } child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); } else { child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, View.MeasureSpec.EXACTLY)); } } else if (child == mentionContainer) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mentionContainer.getLayoutParams(); if (mentionContainer.getAdapter().isBannedInline()) { child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.AT_MOST)); } else { mentionContainer.setIgnoreLayout(true); layoutParams.height = heightSize; layoutParams.topMargin = 0; mentionContainer.setIgnoreLayout(false); child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(layoutParams.height, View.MeasureSpec.EXACTLY)); } } else if (child == textSelectionHelper.getOverlayView(getContext())) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = heightSize + blurredViewTopOffset; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0 && !isInsideContainer) { h += keyboardSize; textSelectionHelper.setKeyboardSize(keyboardSize); } else { textSelectionHelper.setKeyboardSize(0); } child.measure(contentWidthSpec, View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY)); } else if (child instanceof MessagePreviewView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = allHeight - AndroidUtilities.statusBarHeight; int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == hashtagHistoryView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight - (isInsideContainer ? 0 : actionBarHeight) - (hashtagSearchTabs != null ? hashtagSearchTabs.getHeight() : 0), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == searchViewPager) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(allHeight, View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == topicsTabs) { int height = allHeight; if (actionBar.getVisibility() == VISIBLE) { height -= actionBar.getMeasuredHeight(); } int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else { measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); } } if (fixPaddingsInLayout) { globalIgnoreLayout = true; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); fixPaddingsInLayout = false; chatListView.measure(View.MeasureSpec.makeMeasureSpec(chatListView.getMeasuredWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(chatListView.getMeasuredHeight(), View.MeasureSpec.EXACTLY)); globalIgnoreLayout = false; } if (scrollToPositionOnRecreate != -1) { final int scrollTo = scrollToPositionOnRecreate; AndroidUtilities.runOnUIThread(() -> chatLayoutManager.scrollToPositionWithOffset(scrollTo, scrollToOffsetOnRecreate)); scrollToPositionOnRecreate = -1; } updateBulletinLayout(); checkInsets(); lastHeight = allHeight; } @Override public void requestLayout() { if (globalIgnoreLayout) { return; } super.requestLayout(); } @Override public int getKeyboardHeight() { if (isInsideContainer) return 0; return super.getKeyboardHeight(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); int paddingBottom = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child == null || child.getVisibility() == GONE) { continue; } final FrameLayout.LayoutParams lp = (FrameLayout.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(); } 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 || child == quickShareSelectorOverlay || child == chatInputViewsContainer || child == chatInputViewsContainer.getFadeView()) { childTop = 0; } else if (child instanceof HintView || child instanceof ChecksHintView) { childTop = 0; } else if (child == emptyViewContainer) { childTop += (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 (chatActivityEnterView != null && chatActivityEnterView.isRecordCircleOrControlsView(child)) { childTop -= windowInsetsStateHolder.getCurrentMaxBottomInset() + dp(7); } else if (child == emojiButtonRed) { childTop -= windowInsetsStateHolder.getCurrentMaxBottomInset() + dp(7); } else if (chatActivityEnterView != null && child == chatActivityEnterView.recordedAudioPanel) { childTop -= windowInsetsStateHolder.getCurrentMaxBottomInset() + dp(9); } else if (child == gifHintTextView || child == voiceHintTextView || child == mediaBanTooltip || child == emojiHintTextView) { childTop -= inputFieldHeight; } else if (child == chatListView || child == chatListThanosEffect || child == floatingDateView || child == floatingTopicSeparator || child == infoTopView) { childTop -= blurredViewTopOffset + chatListViewPaddingsAnimator.getCurrentAdditionalHeight(); } else if (child == progressView) { if (chatActivityEnterView.isTopViewVisible()) { childTop -= AndroidUtilities.dp(48); } } else if (child == actionBar) { childTop -= getPaddingTop(); } else if (child == videoPlayerContainer) { childTop = actionBar.getMeasuredHeight(); } else if (child == instantCameraView || child == overlayView || child == animatingImageView) { childTop = 0; } else if (child == textSelectionHelper.getOverlayView(getContext())) { childTop -= blurredViewTopOffset; } else if (child instanceof MessagePreviewView) { childTop = AndroidUtilities.statusBarHeight; } else if (child == searchViewPager) { childTop = 0; } else if (child == messagesSearchListContainer) { if (isInsideContainer && parentChatActivity != null) { childTop += chatMode != MODE_SEARCH ? contentPaddingTop : actionBar.getMeasuredHeight(); } } child.layout(childLeft, childTop, childLeft + width, childTop + height); } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); updateTextureViewPosition(false, false); if (getParentActivity() instanceof LaunchActivity && !((LaunchActivity) getParentActivity()).drawerLayoutContainer.allowDrawContent) { updateChatListViewTopPadding(); } notifyHeightChanged(); } private void setNonNoveTranslation(float y) { contentView.setTranslationY(y); actionBar.setTranslationY(0); if (tagSelector != null) { tagSelector.setTranslationY((actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0)); } if (savedMessagesSearchHint != null) { savedMessagesSearchHint.setTranslationY(0); } if (savedMessagesHint != null) { savedMessagesHint.setTranslationY(0); } if (actionBarSearchTags != null) { actionBarSearchTags.setTranslationY(0); } if (topicsTabs != null) { topicsTabs.setTranslationY(0); } if (hashtagSearchTabs != null) { hashtagSearchTabs.setTranslationY(0); } emptyViewContainer.setTranslationY(0); progressView.setTranslationY(0); contentPanTranslation = 0; contentPanTranslationT = 0; contentView.setBackgroundTranslation(0); if (contentView != null) { contentView.updateBlurContent(); } if (instantCameraView != null) { 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(); } protected boolean getNewDrawableMotion() { if (themeDelegate.wallpaper == null) { return super.getNewDrawableMotion(); } return themeDelegate.wallpaper.settings != null && themeDelegate.wallpaper.settings.motion; } @Override public void invalidateBlur() { /*super.invalidateBlur(); if (parentChatActivity != null) { parentChatActivity.contentView.invalidateBlur(); }*/ } @Override public void updateBlurContent() { /*super.updateBlurContent(); if (parentChatActivity != null) { parentChatActivity.contentView.updateBlurContent(); }*/ } }; private void updateSecretStatus() { if (bottomOverlay == null) { return; } boolean hideKeyboard = false; bottomOverlayText.setBackground(null); bottomOverlayText.setOnClickListener(null); if (chatMode == MODE_SAVED && getSavedDialogId() == UserObject.ANONYMOUS) { bottomOverlayText.setText(LocaleController.getString(R.string.AuthorHiddenDescription)); 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 (currentChat != null && !ChatObject.canSendMessages(currentChat) && !ChatObject.canSendAnyMedia(currentChat) && !currentChat.gigagroup && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) { if (currentChat.default_banned_rights != null && currentChat.default_banned_rights.send_messages) { boolean unlockByBoosts = ChatObject.isPossibleRemoveChatRestrictionsByBoosts(currentChat); if (unlockByBoosts) { Drawable drawable = ContextCompat.getDrawable(getContext(), R.drawable.filled_limit_boost).mutate(); DrawableCompat.setTint(drawable, getThemedColor(Theme.key_featuredStickers_addButton)); drawable.setBounds(0, 0, dp(14), dp(14)); CombinedDrawable combinedDrawable = new CombinedDrawable(null, drawable, dp(-6), dp(-6)); combinedDrawable.setIconSize(dp(14), dp(14)); combinedDrawable.setCustomSize(dp(14), dp(14)); SpannableStringBuilder builder = new SpannableStringBuilder("d " + LocaleController.getString(R.string.BoostingBoostToSendMessages)); builder.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_featuredStickers_addButton)), 0, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); builder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); builder.setSpan(new ImageSpan(combinedDrawable, ImageSpan.ALIGN_BASELINE), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); bottomOverlayText.setBackground(Theme.createSelectorWithBackgroundDrawable(0, Theme.getColor(Theme.key_listSelector))); bottomOverlayText.setText(builder); bottomOverlayText.setOnClickListener(v -> LimitReachedBottomSheet.openBoostsForRemoveRestrictions(this, boostsStatus, canApplyBoosts, dialog_id, false)); } else { bottomOverlayText.setText(LocaleController.getString(R.string.GlobalSendMessageRestricted)); } } else if (AndroidUtilities.isBannedForever(currentChat.banned_rights)) { bottomOverlayText.setText(LocaleController.getString(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 { createEmptyView(false); 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(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(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 && !isInsideContainer && chatMode != MODE_SAVED) { 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) { if (chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().checkStorage(); } if (chatThemeBottomSheet != null && chatThemeBottomSheet.chatAttachAlert != null) { chatThemeBottomSheet.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(R.string.AppName)); builder.setMessage(LocaleController.getString(R.string.PermissionNoAudioVideoWithHint)); builder.setNegativeButton(LocaleController.getString(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(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 (viewAsTopics != null) { viewAsTopics.setVisibility(currentChat != null && currentChat.forum ? View.VISIBLE : View.GONE); } if (avatarContainer != null) { avatarContainer.setStars(currentChat != null && (currentChat.flags2 & 2048) != 0, animated); 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 && !ChatObject.isPublic(currentChat); 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 == MessageObject.TYPE_LOADING) { return -1; } else if (messageObject.type == MessageObject.TYPE_DATE || messageObject.type == MessageObject.TYPE_GIFT_THEME_UPDATE || messageObject.type == MessageObject.TYPE_ACTION_PHOTO || messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || messageObject.type == MessageObject.TYPE_GIFT_STARS || messageObject.isWallpaperAction()) { 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 == MessageObject.TYPE_CONTACT) { 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 == MessageObject.TYPE_ACTION_PHOTO) { 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 == MessageObject.TYPE_CONTACT) { 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) && !isThreadChat()) { 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 (!isReport()) { if ((messageObject.type == MessageObject.TYPE_TEXT || 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); Vibrator vibrator = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null) { vibrator.vibrate(200); } return; } selectedMessagesIds[index].put(messageObject.getId(), messageObject); if (!isReport()) { if ((messageObject.type == MessageObject.TYPE_TEXT || 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() && !messageObject.isRoundOnce() && !messageObject.isVoiceOnce() && !noforwards) { canSaveDocumentsCount++; } else { cantSaveMessagesCount++; } if (outside) { showTextSelectionHint(messageObject); } } } } if (last && actionBar.isActionModeShowed() && !isReport()) { int selectedCount = selectedMessagesIds[0].size() + selectedMessagesIds[1].size(); if (selectedCount == 0) { hideActionMode(); updatePinnedMessageView(true); } else { createActionMode(); 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); ActionBarMenuItem deleteItem = actionBar.createActionMode().getItem(delete); ActionBarMenuItem tagItem = actionBar.createActionMode().getItem(tag_message); ActionBarMenuItem shareItem = actionBar.createActionMode().getItem(share); 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 (actionsButtonsLayout != null) { actionsButtonsLayout.setForwardButtonEnabled(cantForwardMessagesCount == 0 || noforwards, true); } 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) { } else if (forwardItem.getBackground() == null) { forwardItem.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 3)); } } if (actionsButtonsLayout != null) { actionsButtonsLayout.setForwardButtonEnabled(cantForwardMessagesCount == 0 || noforwards, false); } } 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(R.string.SaveToMusic) : LocaleController.getString(R.string.SaveToDownloads)); } int copyVisible = View.GONE, starVisible = View.GONE, newCopyVisible = View.GONE, newStarVisible = View.GONE; if (copyItem != null) { copyVisible = copyItem.getVisibility(); copyItem.setVisibility(!noforwards && selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); newCopyVisible = copyItem.getVisibility(); } if (starItem != null) { starVisible = starItem.getVisibility(); starItem.setVisibility(getMediaDataController().canAddStickerToFavorites() && (selectedMessagesCanStarIds[0].size() + selectedMessagesCanStarIds[1].size()) == selectedCount ? View.VISIBLE : View.GONE); newStarVisible = starItem.getVisibility(); } if (deleteItem != null) { deleteItem.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 (msg != null && !getMediaDataController().isStickerInFavorites(msg.getDocument())) { hasUnfavedSelected = true; break; } } if (hasUnfavedSelected) { break; } } if (starItem != null) { starItem.setIcon(hasUnfavedSelected ? R.drawable.msg_fave : R.drawable.msg_unfave); } final int newEditVisibility = canEditMessagesCount == 1 && selectedCount == 1 ? View.VISIBLE : View.GONE; if (actionsButtonsLayout != null) { boolean allowChatActions = true; if (bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE && !bottomOverlayChatWaitsReply || 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; for (int b = 0, N = selectedMessagesIds[0].size(); b < N; b++) { MessageObject message = selectedMessagesIds[0].valueAt(b); if (ChatObject.isForum(currentChat) && !canSendMessageToTopic(message)) { newVisibility = View.GONE; break; } } } 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 || (ChatObject.isForum(currentChat) && !canSendMessageToTopic(message))) { 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; } } } actionsButtonsLayout.showReplyButton(newVisibility == View.VISIBLE, true); } 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(); } } if (shareItem != null) { boolean show = selectedCount == 1 && !noforwards; if (show) { show = false; for (int a = 0; a < 2; ++a) { for (int i = 0; i < selectedMessagesIds[a].size(); ++i) { MessageObject msg = selectedMessagesIds[a].valueAt(i); if (msg == null) continue; if (msg.isVoiceOnce() || msg.isRoundOnce()) continue; if (msg.messageOwner.noforwards) continue; if (msg.isVoice() || msg.isRoundVideo()) show = true; } } } shareItem.setVisibility(show ? View.VISIBLE : View.GONE); } if (tagItem != null) { tagItem.setVisibility(getUserConfig().isPremium() && ( (editItem != null && editItem.getVisibility() == View.VISIBLE ? 1 : 0) + (forwardItem != null && forwardItem.getVisibility() == View.VISIBLE ? 1 : 0) + (saveItem != null && saveItem.getVisibility() == View.VISIBLE ? 1 : 0) + (copyItem != null && copyItem.getVisibility() == View.VISIBLE ? 1 : 0) + (deleteItem != null && deleteItem.getVisibility() == View.VISIBLE ? 1 : 0) + (starItem != null && starItem.getVisibility() == View.VISIBLE ? 1 : 0) + (shareItem != null && shareItem.getVisibility() == View.VISIBLE ? 1 : 0) ) < 4 ? View.VISIBLE : View.GONE); } } } updateSelectedMessageReactions(); } private void updateSelectedMessageReactions() { if (getDialogId() == getUserConfig().getClientUserId()) { ArrayList messageObjects = new ArrayList<>(); for (int a = 0; a < selectedMessagesIds.length; ++a) { for (int k = 0; k < selectedMessagesIds[a].size(); ++k) { MessageObject messageObject = selectedMessagesIds[a].valueAt(k); if (messageObject.hasValidGroupId()) { MessageObject.GroupedMessages group = getValidGroupedMessage(messageObject); MessageObject.GroupedMessagePosition position = group != null ? group.getPosition(messageObject) : null; if (position == null || !position.last) { continue; } } messageObjects.add(messageObject); } } boolean hasReactions = false; if (tagSelector != null) { tagSelector.setSelectedReactionsInclusive(messageObjects); hasReactions = !tagSelector.getSelectedReactions().isEmpty(); tagSelector.setHint(LocaleController.getString(!hasReactions ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); AndroidUtilities.runOnUIThread(() -> { if (tagSelector != null) { tagSelector.requestLayout(); } }, 120); } else { hasReactions = !ReactionsContainerLayout.getInclusiveReactions(messageObjects).isEmpty(); } ActionBarMenuItem tagItem = actionBar.createActionMode().getItem(tag_message); if (tagItem != null) { tagItem.setIcon(hasReactions ? R.drawable.menu_tag_edit : R.drawable.menu_tag_plus, true); } } if (selectionReactionsOverlay != null) { List selected = new ArrayList<>(); SparseArray objs = selectedMessagesIds[0]; for (int i = 0; i < objs.size(); i++) { selected.add(objs.valueAt(i)); } objs = selectedMessagesIds[1]; for (int i = 0; i < objs.size(); i++) { selected.add(objs.valueAt(i)); } selectionReactionsOverlay.setSelectedMessages(selected); } } private void processRowSelect(View view, boolean outside, float touchX, float touchY) { 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 (message != null && message.isAnyGift()) { return; } if (type < 2 || type == 20 || type == MessageObject.TYPE_SUGGEST_PHOTO || message != null && (message.type == MessageObject.TYPE_JOINED_CHANNEL || message.type == MessageObject.TYPE_GIFT_STARS) || (message != null && message.isWallpaperAction())) { return; } addToSelectedMessages(message, outside); updateActionModeTitle(); updateVisibleRows(); } private void updateActionModeTitle() { if (!isReport()) { if (!actionBar.isActionModeShowed()) { return; } if (selectedMessagesCountTextView != null && (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(R.string.ReportMessagesNoCaps)); bottomOverlayChatText.setAlpha(0.5f); bottomOverlayChatText.setEnabled(false); } else { bottomOverlayChatText.setText(LocaleController.formatString(R.string.ReportMessagesCountNoCaps, LocaleController.formatPluralString("messages", size)).toUpperCase()); bottomOverlayChatText.setAlpha(1.0f); bottomOverlayChatText.setEnabled(true); } } } public void updateTitle(boolean animated) { if (avatarContainer == null) { return; } if (chatMode == MODE_SUGGESTIONS && currentChat != null) { if (isSubscriberSuggestions) { avatarContainer.setTitle(ForumUtilities.getMonoForumTitle(currentAccount, currentChat), currentChat.scam, currentChat.fake, currentChat.verified, false, null, animated); } else if (ChatObject.isMonoForum(currentChat)) { if (threadMessageId == 0) { if (currentChat.linked_monoforum_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(currentChat.linked_monoforum_id); if (chat == null) chat = currentChat; avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(chat.title)), chat.scam, chat.fake, chat.verified, false, chat.emoji_status, animated); } else { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(currentChat.title)), currentChat.scam, currentChat.fake, currentChat.verified, false, currentChat.emoji_status, animated); } } else if (threadMessageId > 0) { final TLRPC.User user = getMessagesController().getUser(threadMessageId); avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(UserObject.getUserName(user))), user.scam, user.fake, user.verified, user.premium, user.emoji_status, animated); } else { TLRPC.Chat chat = getMessagesController().getChat(-threadMessageId); if (chat == null) chat = currentChat; avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(chat.title)), chat.scam, chat.fake, chat.verified, false, chat.emoji_status, animated); } } else { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(currentChat.title)), currentChat.scam, currentChat.fake, currentChat.verified, false, currentChat.emoji_status, animated); } } else if (chatMode == MODE_QUICK_REPLIES) { if (QuickRepliesController.GREETING.equalsIgnoreCase(quickReplyShortcut)) { avatarContainer.setTitle(LocaleController.getString(R.string.BusinessGreet)); } else if (QuickRepliesController.AWAY.equalsIgnoreCase(quickReplyShortcut)) { avatarContainer.setTitle(LocaleController.getString(R.string.BusinessAway)); } else { avatarContainer.setTitle(quickReplyShortcut); } } else if (chatMode == MODE_EDIT_BUSINESS_LINK) { if (!TextUtils.isEmpty(businessLink.title)) { avatarContainer.setTitle(businessLink.title); } else { avatarContainer.setTitle(LocaleController.getString(R.string.BusinessLink)); } } else if (chatMode == MODE_SAVED) { long dialogId = threadMessageId; TLRPC.User user = null; TLRPC.Chat chat = null; if (dialogId > 0) { user = getMessagesController().getUser(dialogId); } else { chat = getMessagesController().getChat(-dialogId); } if (UserObject.isReplyUser(user)) { avatarContainer.setTitle(LocaleController.getString(R.string.RepliesTitle)); } else if (UserObject.isAnonymous(user)) { avatarContainer.setTitle(LocaleController.getString(R.string.AnonymousForward)); } else if (UserObject.isUserSelf(user)) { avatarContainer.setTitle(LocaleController.getString(R.string.MyNotes)); } else if (user != null) { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(UserObject.getUserName(user)))); } else if (chat != null) { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(chat.title))); } else { avatarContainer.setTitle(""); } } else if (isThreadChat() && !UserObject.isBotForum(currentUser)) { if (isTopic) { updateTopicHeader(); } else if (isComments) { if (threadMessageObject.hasReplies()) { avatarContainer.setTitle(LocaleController.formatPluralString("Comments", threadMessageObject.getRepliesCount())); } else { avatarContainer.setTitle(LocaleController.getString(R.string.CommentsTitle)); } } else { avatarContainer.setTitle(LocaleController.formatPluralString("Replies", threadMessageObject.getRepliesCount())); } } else if (UserObject.isReplyUser(currentUser)) { avatarContainer.setTitle(LocaleController.getString(R.string.RepliesTitle)); } else if (UserObject.isAnonymous(currentUser)) { avatarContainer.setTitle(LocaleController.getString(R.string.AnonymousForward)); } else if (chatMode == MODE_SCHEDULED) { if (UserObject.isUserSelf(currentUser)) { avatarContainer.setTitle(LocaleController.getString(R.string.Reminders)); } else { avatarContainer.setTitle(LocaleController.getString(R.string.ScheduledMessages)); } } else if (chatMode == MODE_PINNED) { avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } else if (currentChat != null) { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(currentChat.title)), currentChat.scam, currentChat.fake, currentChat.verified, false, currentChat.emoji_status, animated); } else if (currentUser != null) { if (currentUser.self) { avatarContainer.setTitle(LocaleController.getString(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), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), currentUser.emoji_status, animated); } else { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(UserObject.getUserName(currentUser))), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), currentUser.emoji_status, animated); } } else { avatarContainer.setTitle(AndroidUtilities.removeRTL(AndroidUtilities.removeDiacritics(UserObject.getUserName(currentUser))), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser), !MessagesController.isSupportUser(currentUser) ? currentUser.emoji_status : null, animated); } } setParentActivityTitle(avatarContainer.getTitleTextView().getText()); updateTitleIcons(); } public void updateTopicTitleIcon() { if (UserObject.isBotForum(currentUser) && avatarContainer != null) { avatarContainer.getAvatarImageView().setVisibility(View.VISIBLE); avatarContainer.checkAndUpdateAvatar(); return; } if (forumTopic != null && avatarContainer != null) { avatarContainer.getAvatarImageView().setVisibility(View.VISIBLE); ForumUtilities.setTopicIcon(avatarContainer.getAvatarImageView(), forumTopic, true, true, themeDelegate); } } private int getPinnedMessagesCount() { return Math.max(loadedPinnedMessagesCount, totalPinnedMessagesCount); } private void updateTopicButtons() { if (closeTopicItem != null) { closeTopicItem.setVisibility(currentChat != null && ChatObject.canManageTopic(currentAccount, currentChat, forumTopic) && forumTopic != null && !forumTopic.closed ? View.VISIBLE : View.GONE); } } 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++) { TL_bots.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 && chatMode != MODE_SUGGESTIONS) { return; } boolean isMuted = getMessagesController().isDialogMuted(dialog_id, getTopicId()); if (forceToggleMuted) { isMuted = !isMuted; } Drawable rightIcon = null; if (!UserObject.isReplyUser(currentUser) && (!isThreadChat() || isTopic) && isMuted) { rightIcon = getThemedDrawable(Theme.key_drawable_muteIconDrawable); } Drawable leftIcon = null; if (currentEncryptedChat != null) { leftIcon = getThemedDrawable(Theme.key_drawable_lockIconDrawable); } else if (currentChat != null) { leftIcon = avatarContainer.getBotVerificationDrawable(DialogObject.getBotVerificationIcon(currentChat), false); } else if (currentUser != null && !UserObject.isUserSelf(currentUser)) { leftIcon = avatarContainer.getBotVerificationDrawable(DialogObject.getBotVerificationIcon(currentUser), false); } avatarContainer.setTitleIcons(leftIcon, rightIcon); if (!forceToggleMuted && muteItem != null) { if (isMuted) { muteItem.setRightIconVisibility(View.GONE); muteItem.setText(LocaleController.getString(R.string.Unmute)); muteItem.setIcon(R.drawable.msg_mute); } else { muteItem.setRightIconVisibility(View.VISIBLE); if (getMessagesController().isDialogNotificationsSoundEnabled(dialog_id, getTopicId())) { muteItem.setText(LocaleController.getString(R.string.Mute)); muteItem.setIcon(R.drawable.msg_unmute); } else { muteItem.setText(LocaleController.getString(R.string.Mute)); muteItem.setIcon(R.drawable.msg_silent); } } } if (chatNotificationsPopupWrapper != null) { chatNotificationsPopupWrapper.update(dialog_id, getTopicId(), null); } } public void checkAndUpdateAvatar() { if (isTopic) { return; } 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(this, 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); if (PhotoViewer.getInstance().isVisible()) { PhotoViewer.getInstance().closePhoto(false, false); } 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, int scheduleRepeatPeriod, boolean forceDocument) { sendMedia((MediaController.PhotoEntry) cameraPhoto.get(0), videoEditedInfo, notify, scheduleDate, 0, forceDocument, 0); } @Override public boolean canScrollAway() { return false; } @Override public boolean canCaptureMorePhotos() { return false; } }, this); } else { fillEditingMediaWithCaption(caption, null); SendMessagesHelper.prepareSendingVideo(getAccountInstance(), videoPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, null, 0, editingMessageObject, true, 0, 0, false, false, null, quickReplyShortcut, getQuickReplyId(), 0, 0, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); afterMessageSend(); } } public static ArrayList createEntriesFromMedia(ArrayList photoPathes, boolean isSecretChat, 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; } Pair orientation = AndroidUtilities.getImageOrientation(path); MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, path, orientation.first, photoInfo.isVideo, 0, 0, 0).setOrientation(orientation); if (a == photoPathes.size() - 1 && caption != null) { entry.caption = caption; } entries.add(entry); } return entries; } public boolean openPhotosEditor(ArrayList photoPathes, CharSequence caption) { final ArrayList entries = createEntriesFromMedia(photoPathes,isSecretChat(), caption); if (entries.isEmpty()) { return false; } if (getParentActivity() != null) { final boolean[] checked = new boolean[entries.size()]; Arrays.fill(checked, true); PhotoViewer.getInstance().setParentActivity(this, 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, int scheduleRepeatPeriod, 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.coverPath = entry.coverPath; 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, replyingMessageObject, getThreadMessage(), null, replyingQuote, forceDocument, true, null, notify, scheduleDate, 0, chatMode, photos.get(0).updateStickersOrder, null, quickReplyShortcut, getQuickReplyId(), 0, false, 0, getSendMonoForumPeerId(), messageSuggestionParams); afterMessageSend(); if (chatActivityEnterView != null) { 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, false, true); } if (file != null && !file.exists()) { file = FileLoader.getInstance(currentAccount).getPathToMessage(object.messageOwner, true, true); } if (!file.exists()) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), themeDelegate); builder.setTitle(getString("AppName", R.string.AppName)); builder.setPositiveButton(getString("OK", R.string.OK), null); boolean alreadyDownloading = object != null && object.isVideo() && FileLoader.getInstance(object.currentAccount).isLoadingFile(object.getFileName()); if (alreadyDownloading) { builder.setMessage(getString(R.string.PleaseStreamDownload)); } else { builder.setMessage(getString(R.string.PleaseDownload)); } showDialog(builder.create()); return; } PhotoViewer.getInstance().setParentActivity(this, 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(); entry.duration = (int) object.getDuration(); entry.coverPhoto = object.getVideoCover(); if (entry.coverPhoto != null) { entry.coverPhotoParentObject = object; } 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, boolean closing) { return ChatActivity.this.getPlaceForPhoto(object, null, index, needPreview, true); } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, int scheduleRepeatPeriod, boolean forceDocument) { if (editingMessageObject != object) { return; } if (entry.isCropped || entry.isPainted || entry.isFiltered || videoEditedInfo != null) { sendMedia(entry, videoEditedInfo, notify, scheduleDate, 0, forceDocument, 0); } 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 void onApplyCaption(CharSequence caption) { 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, int index, 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(index); } } } 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.local_id == fileLocation.local_id) { imageReceiver = cell.getPhotoImage(); break; } } if (imageReceiver == null && message.messageOwner != null && message.messageOwner.action != null && message.messageOwner.action.photo != null && message.messageOwner.action.photo.video_sizes != null && !message.messageOwner.action.photo.video_sizes.isEmpty()) { TLRPC.VideoSize photoSize = message.messageOwner.action.photo.video_sizes.get(0); if (photoSize.location != null && photoSize.location.volume_id == fileLocation.volume_id && photoSize.location.local_id == fileLocation.local_id) { imageReceiver = cell.getPhotoImage(); } } } } } 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] - 0 + view.getPaddingTop(); object.parentView = chatListView; object.animatingImageView = null; object.imageReceiver = imageReceiver; if (needPreview) { object.thumb = imageReceiver.getBitmapSafe(); } object.radius = imageReceiver.getRoundRadius(true); if (view instanceof ChatActionCell && currentChat != null) { object.dialogId = -currentChat.id; } object.clipTopAddition = (int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4)); object.clipBottomAddition = (int) (blurredViewBottomOffset + dp(9) + windowInsetsStateHolder.getAnimatedMaxBottomInset() + inputIslandHeightCurrent); return object; } } return null; } private void showAttachmentError() { if (getParentActivity() == null) { return; } BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(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 (editingMessageObject.isMediaEmpty()) { editingMessageObject.editingMessage = ""; editingMessageObject.editingMessageEntities = new ArrayList<>(); } else if (chatActivityEnterView != null) { editingMessageObject.editingMessage = chatActivityEnterView.getFieldText(); if (editingMessageObject.editingMessage == null && !TextUtils.isEmpty(editingMessageObject.messageOwner.message)) { editingMessageObject.editingMessage = ""; } } } private void sendUriAsDocument(Uri uri) { sendUriAsDocument(uri, true, 0); } private void sendUriAsDocument(Uri uri, boolean notify, int schedule_date) { 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, replyingQuote, editingMessageObject, notify, schedule_date, null, quickReplyShortcut, getQuickReplyId(), false); } else { SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, editingMessageObject, notify, schedule_date, null, quickReplyShortcut, getQuickReplyId(), false); } 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, scheduleRepeatPeriod) -> { fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), replyingQuote, null, null, null, null, 0, editingMessageObject, notify, scheduleDate, chatMode, quickReplyShortcut, getQuickReplyId()); }, themeDelegate); } else { fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), replyingQuote, null, null, null, null, 0, editingMessageObject, true, 0, chatMode, quickReplyShortcut, getQuickReplyId()); } } afterMessageSend(); } else if (requestCode == 21) { if (data == null) { showAttachmentError(); return; } if (editingMessageObject == null && chatMode == MODE_SCHEDULED) { if (data.getData() != null) { if (chatAttachAlert != null) { chatAttachAlert.dismiss(); } AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate, scheduleRepeatPeriod) -> { fillEditingMediaWithCaption(null, null); sendUriAsDocument(data.getData(), notify, scheduleDate); afterMessageSend(); }, themeDelegate); return; } else if (data.getClipData() != null) { if (chatAttachAlert != null) { chatAttachAlert.dismiss(); } AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate, scheduleRepeatPeriod) -> { fillEditingMediaWithCaption(null, null); ClipData clipData = data.getClipData(); for (int i = 0; i < clipData.getItemCount(); i++) { sendUriAsDocument(clipData.getItemAt(i).getUri(), notify, scheduleDate); } afterMessageSend(); }, themeDelegate); return; } else { showAttachmentError(); } } else { fillEditingMediaWithCaption(null, null); 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 boolean isSkeletonVisible() { if (justCreatedTopic || justCreatedChat || currentUser != null || chatListView == null || !SharedConfig.animationsEnabled() || !getLiteModeChat()) { return false; } int childHeight = 0; int maxTop = Integer.MAX_VALUE; for (int i = 0; i < chatListView.getChildCount(); i++) { childHeight += chatListView.getChildAt(i).getHeight(); int top = chatListView.getChildAt(i).getTop(); if (top < maxTop) { maxTop = top; } } if (maxTop <= chatListViewPaddingTop) { checkDispatchHideSkeletons(fragmentBeginToShow); } boolean visible = (!endReached[0] || mergeDialogId != 0 && !endReached[1] || messages.isEmpty()) && loading && maxTop > chatListViewPaddingTop && (messages.isEmpty() ? animateProgressViewTo : childHeight != 0); if (visible && inTransitionAnimation && emptyViewContainer != null && emptyViewContainer.getVisibility() == View.VISIBLE && emptyViewContainer.getChildCount() > 0) { return false; } if (!visible && startMessageAppearTransitionMs == 0) { checkDispatchHideSkeletons(fragmentBeginToShow); } if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW && !fromPullingDownTransition && fragmentBeginToShow) { boolean rotate = visible && startMessageAppearTransitionMs == 0; Drawable wallpaper = themeDelegate.getWallpaperDrawable(); if (contentView != null) { wallpaper = contentView.getBackgroundImage(); } if (wallpaper instanceof MotionBackgroundDrawable) { MotionBackgroundDrawable motion = (MotionBackgroundDrawable) wallpaper; if (((MotionBackgroundDrawable) wallpaper).isIndeterminateAnimation() != rotate) { if (!rotate) { motion.generateNextGradient(); } motion.setIndeterminateAnimation(rotate); motion.setIndeterminateSpeedScale(rotate ? 1.5f : 1f); motion.updateAnimation(true); } else if (rotate) { motion.updateAnimation(false); } } } return visible || startMessageAppearTransitionMs != 0 && System.currentTimeMillis() - startMessageAppearTransitionMs <= SKELETON_DISAPPEAR_MS; } private void checkDispatchHideSkeletons(boolean animate) { if (startMessageAppearTransitionMs == 0) { if (animate && !messageSkeletons.isEmpty()) { startMessageAppearTransitionMs = System.currentTimeMillis(); } else { startMessageAppearTransitionMs = 1; } isSkeletonVisible(); if (chatListView != null) { chatListView.invalidate(); } } } 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; boolean fakePostponedScroll = this.fakePostponedScroll; this.fakePostponedScroll = false; if (postponedScroll) { postponedScrollToLastMessageQueryIndex = 0; } ArrayList messArr = (ArrayList) args[2]; boolean universalNotify = false; HashMap oldMessages = null; if (clearOnLoad && (mode == MODE_DEFAULT || mode == MODE_SUGGESTIONS)) { final boolean isBotForum = isInBotForumMode(); clearOnLoad = false; oldMessages = new HashMap(); for (MessageObject msg : messages) { if (msg.getId() >= 0 || isBotForum) { oldMessages.put(msg.getId(), msg); } } messages.clear(); messagesByDays.clear(); messagesByDaysSorted.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(); if (clearOnLoadButIsNewTopic) { endReached[a] = true; } else { endReached[a] = false; } forwardEndReached[a] = true; } clearOnLoadButIsNewTopic = false; hideForwardEndReached = false; hideActionMode(); updatePinnedMessageView(true); universalNotify = true; toggleIsAllChats(); } 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++, isTopic); } return; } else if (!doNotRemoveLoadIndex) { waitingForLoad.remove(index); } 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); checkDispatchHideSkeletons(true); if (chatListView != null) { createEmptyView(false); if (!fragmentOpened) { chatListView.setAnimateEmptyView(false, 1); chatListView.setEmptyView(emptyViewContainer); chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); } else { chatListView.setEmptyView(emptyViewContainer); } if (chatAdapter != null) { 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 && (chatMode != MODE_SAVED || getSavedDialogId() == getUserConfig().getClientUserId())) { if (chatMode != MODE_SCHEDULED && chatMode != MODE_QUICK_REPLIES) { if (isTopic) { ForumUtilities.filterMessagesByTopic(threadMessageId, messArr); } scheduledMessagesCount = messArr.size(); updateScheduledInterface(true); } return; } else if (chatMode == MODE_SCHEDULED && isTopic) { ForumUtilities.filterMessagesByTopic(threadMessageId, messArr); } boolean createUnreadLoading = false; boolean showDateAfter = waitingForReplyMessageLoad; SparseArray oldMessagesDict = null; 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; oldMessagesDict = messagesDict[0].clone(); clearChatData(!fakePostponedScroll); if (chatMode == 0 || chatMode == MODE_SAVED) { 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++, isTopic); return; } if (load_type == 4) { postponedScrollMessageId = startLoadFromMessageId; } if (progressDialog != null) { progressDialog.dismiss(); } resetProgressDialogLoading(); showPinnedProgress(false); if (postponedScrollIsCanceled) { return; } if (postponedScrollMessageId == 0) { clearChatData(true); } 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(R.string.MessageNotFound), themeDelegate).show(); } return; } showScrollToMessageError = false; } int startLoadFrom = startLoadFromMessageId; boolean needSelect = needSelectFromMessageId; int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; clearChatData(!fakePostponedScroll); if (chatMode == 0 || chatMode == MODE_SAVED) { 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 { if (isTopic) { if (first_unread_id == 0) { for (int i = messArr.size() - 1; i >= 0; i--) { if (messArr.get(i).getId() > threadMaxInboxReadId) { first_unread_id = messArr.get(i).getId(); break; } } } } 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() && !isTopic && 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; checkDispatchHideSkeletons(true); } if (chatMode == MODE_SCHEDULED || chatMode == MODE_QUICK_REPLIES) { endReached[0] = cacheEndReached[0] = true; forwardEndReached[0] = forwardEndReached[0] = true; } if ((!isThreadChat() || isTopic) && 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(); messagesByDaysSorted.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; } if (isThreadChat() && !isTopic && (load_type == 2 || load_type == 3) && !isCache) { if (load_type == 3 && scrollToThreadMessage) { startLoadFromMessageId = (int) 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; checkDispatchHideSkeletons(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 (!isTopic && !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(R.string.NoComments); } else { msg.message = LocaleController.getString(R.string.NoReplies); } } else { msg.message = LocaleController.getString(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 && chatMode != MODE_QUICK_REPLIES) { getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode, 0, null, classGuid, 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 moveCurrentConversionObject = 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(); } } else if (ChatObject.isForum(currentChat) || ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { long topicId = ChatObject.isForum(currentChat) ? MessageObject.getTopicId(currentAccount, obj.messageOwner, true) : MessageObject.getMonoForumTopicId(obj.messageOwner); TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, topicId); if (topic != null) { if (messageId <= (obj.isOut() ? topic.read_outbox_max_id : topic.read_inbox_max_id)) { obj.setIsRead(); } } } if (approximateHeightSum <= AndroidUtilities.displaySize.y / 2) { approximateHeightSum += getHeightForMessage(obj, false); } 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 (obj.messageOwner instanceof TLRPC.TL_messageEmpty) { continue; } if (getTopicId() != 0 && obj.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate) { if (obj.isUnread()) { obj.setIsRead(); newUnreadMessageCount--; if (newUnreadMessageCount < 0) { newUnreadMessageCount = 0; } getMessagesStorage().updateRepliesMaxReadId(replyOriginalChat.id, replyOriginalMessageId, obj.getId(), newUnreadMessageCount, true); } endReached[0] = true; 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 && (chatMode != MODE_QUICK_REPLIES || messages.size() + 1 < getMessagesController().quickReplyMessagesLimit)) { obj = needAnimateToMessage; animatingMessageObjects.add(obj); needAnimateToMessage = null; } MessageObject oldMessage = null; if (oldMessage == null && filteredMessagesDict != null) { oldMessage = filteredMessagesDict.get(obj.getId()); } if (oldMessage == null) { oldMessage = messagesDict[loadIndex].get(messageId); } if (oldMessage == null && oldMessagesDict != null) { oldMessage = oldMessagesDict.get(messageId); } messagesDict[loadIndex].put(messageId, obj); ArrayList dayArray = messagesByDays.get(obj.dateKey); final boolean addDateObjects = chatMode != MODE_QUICK_REPLIES;// && chatMode != MODE_SCHEDULED; if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); messagesByDaysSorted.put(obj.dateKeyInt, dayArray); if (addDateObjects) { TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { dateMsg.message = LocaleController.getString(R.string.MessageScheduledUntilOnline); } else { dateMsg.message = LocaleController.formatString(R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); } } else { dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); } dateMsg.id = 0; if (chatMode == MODE_SCHEDULED && obj.messageOwner.date == 0x7ffffffe) { dateMsg.date = 0x7ffffffe; } else { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); } MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = MessageObject.TYPE_DATE; dateObj.contentType = 1; dateObj.isDateObject = true; dateObj.stableId = getStableIdForDateObject(obj.dateKeyInt); 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 == MessagesController.LOAD_FORWARD) { previous = messages.get(0); } else { previous = messages.get(messages.size() - (reversed || !addDateObjects ? 1 : 2)); } if (previous.getGroupIdForUse() == obj.getGroupIdForUse()) { if (previous.localGroupId != 0) { obj.localGroupId = previous.localGroupId; groupedMessages = groupedMessagesMap.get(previous.localGroupId); } } else { if (reversed || !addDateObjects) { 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 { obj.localGroupId = Utilities.random.nextLong(); groupedMessages = null; } } else { obj.localGroupId = Utilities.random.nextLong(); groupedMessages = null; } } } } if (groupedMessages == null) { groupedMessages = new MessageObject.GroupedMessages(); groupedMessages.reversed = reversed; 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); if (oldMessage == null && oldMessages != null) { oldMessage = oldMessages.get(obj.getId()); } if (oldMessage != null) { obj.copyStableParams(oldMessage); } else { obj.stableId = lastStableId++; } getMessagesController().getTranslateController().checkTranslation(obj, false); if (load_type == 1) { messages.add(0, obj); } else { if (!messages.isEmpty()) { messages.get(messages.size() - 1).stableId = lastStableId++; } if (reversed || !addDateObjects) { messages.add(obj); } else { messages.add(messages.size() - 1, obj); } } if (obj.messageOwner != null && obj.messageOwner.video_processing_pending && ( !obj.hasValidGroupId() || (a + 1) >= messArr.size() || obj.getGroupIdForUse() != messArr.get(a + 1).getGroupIdForUse() )) { TLRPC.Message msg = new TLRPC.TL_message(); msg.message = getString(R.string.VideoConversionAction); if (chatMode == MODE_SCHEDULED && obj.messageOwner.date == 0x7ffffffe) { msg.date = 0x7ffffffe; } else { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); msg.date = (int) (calendar.getTimeInMillis() / 1000); } MessageObject dateObj = new MessageObject(currentAccount, msg, false, false); dateObj.type = MessageObject.TYPE_DATE; dateObj.contentType = 1; dateObj.isDateObject = true; dateObj.isVideoConversionObject = true; dateObj.stableId = getStableIdForConversionObject(obj.getId()); if (load_type == 1) { messages.add(0, dateObj); } else { if (!messages.isEmpty()) { messages.get(messages.size() - 1).stableId = lastStableId++; } if (reversed || !addDateObjects) { messages.add(dateObj); } else { messages.add(messages.size() - 1, dateObj); } } conversionMessages.put(obj.getId(), dateObj); newRowsCount++; } 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 && chatMode != MODE_SAVED && chatMode != MODE_QUICK_REPLIES) { 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 = MessageObject.TYPE_LOADING; 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) && !fakePostponedScroll) { final Integer taskId = highlightTaskId; removeSelectedMessageHighlight(); if (needSelectFromMessageId && messageId == startLoadFromMessageId) { highlightMessageId = messageId; highlightTaskId = taskId; } if (showScrollToMessageError && messageId != startLoadFromMessageId) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(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) && chatMode != MODE_SAVED && chatMode != MODE_QUICK_REPLIES) { TLRPC.Message dateMsg = new TLRPC.TL_message(); dateMsg.message = ""; dateMsg.id = 0; MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = MessageObject.TYPE_LOADING; 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++; } } checkGroupMessagesOrder(); 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; if (!universalNotify && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.loadingDownRow); } } startLoadFromMessageId = 0; } if (newRowsCount > 0 && !chatAdapter.isFiltered) { int top = 0; MessageObject scrollToMessageObject = null; for (int i = 0; i < chatListView.getChildCount(); i++) { View v = chatListView.getChildAt(i); if (v instanceof ChatMessageCell) { scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); top = getScrollingOffsetForView(v); break; } } if (!universalNotify && !postponedScroll) { chatAdapter.notifyItemRangeInserted(1, newRowsCount); chatAdapter.updateRowsSafe(); 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(fragmentBeginToShow); if (chatListView != null && chatScrollHelper != null) { if (chatAdapter.isFiltered) { scrollToMessagePosition = -10000; scrollToMessage = null; } else if (first || scrollToTopOnResume || forceScrollToTop) { forceScrollToTop = false; if (!universalNotify && !postponedScroll && chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } if (isTopic && startLoadFromMessageId == getTopicId() && messArr.size() > 0 && messages.size() > 0 && messArr.size() - 1 < messages.size()) { scrollToMessage = messages.get(messArr.size() - 1); } if (scrollToMessage != null) { addSponsoredMessages(!isFirstLoading); int yOffset; boolean opt = false; boolean bottom = true; if (startLoadFromMessageOffset != Integer.MAX_VALUE) { yOffset = -startLoadFromMessageOffset - chatListView.getPaddingBottom(); startLoadFromMessageOffset = Integer.MAX_VALUE; } else if (scrollToMessagePosition == -9000) { opt = true; 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 (!opt) { yOffset -= scrollOffsetForQuote(scrollToMessage); } if (!postponedScroll) { if (!messages.isEmpty()) { chatAdapter.updateRowsSafe(); 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 (sideControlsButtonsLayout != null) { if (prevSetUnreadCount != newUnreadMessageCount) { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, newUnreadMessageCount = unread_to_load, openAnimationEnded); prevSetUnreadCount = newUnreadMessageCount; } } } } scrollToMessagePosition = -10000; scrollToMessage = null; } else if (!fakePostponedScroll) { addSponsoredMessages(!isFirstLoading); moveScrollToLastMessage(true); } if (loaded_mentions_count != 0) { showMentionDownButton(true, true); if (sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonCount( ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount = loaded_mentions_count, true); } } } else if (!universalNotify) { if (newRowsCount != 0) { int top = 0; MessageObject scrollToMessageObject = null; for (int i = 0; i < chatListView.getChildCount(); i++) { View v = chatListView.getChildAt(i); if (v instanceof ChatMessageCell) { scrollToMessageObject = ((ChatMessageCell) v).getMessageObject(); top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { scrollToMessageObject = ((ChatActionCell) v).getMessageObject(); top = getScrollingOffsetForView(v); 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); if (chatAdapter.userInfoRow >= 0 && unreadMessageObject != null && messages.indexOf(unreadMessageObject) >= messages.size() - 2) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.userInfoRow, 0, false); } } else { chatAdapter.notifyDataSetChanged(true); } } if (paused) { scrollToTopOnResume = true; if (scrollToMessage != null) { scrollToTopUnReadOnResume = true; } } if (first) { if (chatListView != null) { AndroidUtilities.runOnUIThread(() -> { createEmptyView(false); if (!fragmentBeginToShow) { chatListView.setAnimateEmptyView(false, 0); chatListView.setEmptyView(emptyViewContainer); chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); } 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 && !universalNotify && !chatAdapter.isFiltered && changedGroups != null && changedGroups.indexOfKey(newGroups.keyAt(a)) >= 0) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int idx = messages.indexOf(messageObject); if (idx >= 0) { 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); showFloatingTopicView(false); } addSponsoredMessages(!isFirstLoading); checkScrollForLoad(false); if (postponedScroll && !fakePostponedScroll) { if (!universalNotify && chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } if (progressDialog != null) { progressDialog.dismiss(); showMessagesSearchListView(false); } resetProgressDialogLoading(); updatePinnedListButton(false); if (postponedScrollMessageId == 0) { chatScrollHelperCallback.scrollTo = null; chatScrollHelperCallback.lastBottom = true; chatScrollHelperCallback.lastItemOffset = 0; chatScrollHelperCallback.lastPadding = (int) chatListViewPaddingTop; chatScrollHelper.scrollToPosition(chatScrollHelperCallback.position = 0, chatScrollHelperCallback.offset = 0, chatScrollHelperCallback.bottom = 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(chatScrollHelperCallback.position = chatAdapter.messagesStartRow + k, chatScrollHelperCallback.offset = yOffset, chatScrollHelperCallback.bottom = false, true); } } } } chatWasReset = false; if (isFirstLoading) { AndroidUtilities.runOnUIThread(() -> { resumeDelayedFragmentAnimation(); AndroidUtilities.cancelRunOnUIThread(fragmentTransitionRunnable); fragmentTransitionRunnable.run(); getNotificationCenter().runDelayedNotifications(); }); } if (did == dialog_id && !messages.isEmpty() && currentUser != null && (bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() == View.VISIBLE)) { if (!TextUtils.isEmpty(botUser) && !sentBotStart && chatMode == 0) { sentBotStart = true; getMessagesController().sendBotStart(currentUser, botUser); bottomChannelButtonsLayout.setVisibility(View.GONE); if (!isInsideContainer) { chatActivityEnterView.setVisibility(View.VISIBLE); } chatActivityEnterView.setBotInfo(botInfo); } } if (!UserObject.isBotForum(currentUser)) { checkNewMessagesOnQuoteEdit(true); } invalidatePremiumBlocked(); if (chatMode == MODE_QUICK_REPLIES) { updateBottomOverlay(); } if (fakePostponedScroll) { setFilterMessages(false, true, true); } if (chatMode == MODE_SEARCH) { updateSearchUpDownButtonVisibility(true); } if (startReplyTo != 0) { MessageObject msg = messagesDict[0].get(startReplyTo); if (msg != null) { showFieldPanelForReply(msg); startReplyTo = 0; } } if (chatAdapter != null && universalNotify) { chatAdapter.notifyDataSetChanged(true); if (clearOnLoadAndScrollMessageId >= 0) { final int messageId = clearOnLoadAndScrollMessageId; clearOnLoadAndScrollMessageId = -1; for (int i = 0; i < messages.size(); ++i) { MessageObject messageObject = messages.get(i); if (messageObject != null && messageObject.getId() == messageId) { final int position = chatAdapter.messagesStartRow + i; if (position >= 0 && position < chatAdapter.getItemCount()) { chatLayoutManager.scrollToPositionWithOffset(position, clearOnLoadAndScrollOffset); } break; } } } } } else if (id == NotificationCenter.invalidateMotionBackground) { if (chatListView != null) { chatListView.invalidateViews(); } if (messageEnterTransitionContainer != null) { messageEnterTransitionContainer.invalidate(); } } else if (id == NotificationCenter.loadingMessagesFailed) { if ((Integer) args[0] == classGuid && args[2] instanceof TLRPC.TL_error) { TLRPC.TL_error e = (TLRPC.TL_error) args[2]; if ("FROZEN_METHOD_INVALID".equals(e.text)) { finishFragment(); AccountFrozenAlert.show(currentAccount); return; } } } else if (id == NotificationCenter.customStickerCreated) { boolean isSending = args.length > 0 ? (Boolean) args[0] : false; if (chatAttachAlert != null && chatAttachAlert.isShowing()) { chatAttachAlert.dismiss(true); } if (isSending && chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) { chatActivityEnterView.hidePopup(true); } if (args.length > 1 && args[1] instanceof TLRPC.TL_messages_stickerSet) { TLRPC.StickerSet set = ((TLRPC.TL_messages_stickerSet) args[1]).set; TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); inputStickerSet.access_hash = set.access_hash; inputStickerSet.id = set.id; final boolean replacing = args.length > 4 ? (boolean) args[4] : false; if (visibleDialog instanceof StickersAlert) { StickersAlert existingAlert = (StickersAlert) visibleDialog; if (existingAlert.stickerSet != null && existingAlert.stickerSet.set != null && existingAlert.stickerSet.set.id == set.id) { existingAlert.updateStickerSet(((TLRPC.TL_messages_stickerSet) args[1])); if (args.length > 2 && args[2] instanceof TLRPC.Document) { TLRPC.Document stickerDocument = (TLRPC.Document) args[2]; if (args.length > 3 && args[3] instanceof String) { stickerDocument.localThumbPath = (String) args[3]; } BulletinFactory.of(existingAlert.container, resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(replacing ? R.string.StickersStickerEditedInSetToast : R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(true); } return; } } StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate, false); alert.setOnShowListener(dialog -> { if (args.length > 2 && args[2] instanceof TLRPC.Document) { TLRPC.Document stickerDocument = (TLRPC.Document) args[2]; if (args.length > 3 && args[3] instanceof String) { stickerDocument.localThumbPath = (String) args[3]; } BulletinFactory.of(alert.container, resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(replacing ? R.string.StickersStickerEditedInSetToast : R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(true); } }); showDialog(alert); } } 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(); if (editText != null) { 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(); } 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 != null) { chatActivityEnterView.updateSendAsButton(true); } } else if (id == NotificationCenter.userIsPremiumBlockedUpadted) { if (chatActivityEnterView != null) { chatActivityEnterView.updateSendButtonPaid(); } } else if (id == NotificationCenter.updateInterfaces) { int updateMask = (Integer) args[0]; if ((updateMask & MessagesController.UPDATE_MASK_NAME) != 0 || (updateMask & MessagesController.UPDATE_MASK_CHAT_NAME) != 0 || (updateMask & MessagesController.UPDATE_MASK_EMOJI_STATUS) != 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(true); } 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 (flagSecure != null) { flagSecure.invalidate(); } } if (avatarContainer != null && updateSubtitle) { avatarContainer.updateSubtitle(true); } if ((updateMask & MessagesController.UPDATE_MASK_USER_PHONE) != 0) { updateTopPanel(true); } if (headerItem != null) { headerItem.setSubItemShown(open_direct, ChatObject.isChannel(currentChat) && !ChatObject.isMonoForum(currentChat) && currentChat.linked_monoforum_id != 0 && ChatObject.canManageMonoForum(currentAccount, -currentChat.linked_monoforum_id)); } } else if (id == NotificationCenter.didReceiveNewMessages) { FileLog.d("ChatActivity didReceiveNewMessages start"); long did = (Long) args[0]; ArrayList arr = (ArrayList) args[1]; if (isInsideContainer) return; if (did == dialog_id) { boolean scheduled = (Boolean) args[2]; int mode = (Integer) args[3]; if (mode != chatMode && chatMode != MODE_SAVED && chatMode != MODE_SUGGESTIONS) { if (chatMode != MODE_SCHEDULED && mode == MODE_SCHEDULED && !isPaused && LaunchActivity.getSafeLastFragment() == this && messagePreviewParams == null) { if (!arr.isEmpty() && arr.get(0).getId() < 0) { openScheduledMessages(arr.get(0).getId(), arr.get(0).messageOwner != null && arr.get(0).messageOwner.video_processing_pending); } } FileLog.d("ChatActivity didReceiveNewMessages return: opened scheduled messages"); 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(); } FileLog.d("ChatActivity didReceiveNewMessages return: done"); } 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.getFragmentStack().size() > 1) { finishFragment(); } else { removeSelfFromStack(true); } } } else if (id == NotificationCenter.closeChatActivity) { final long dialogId = (long) args[0]; final boolean includingLast = (boolean) args[1]; if (dialogId == getDialogId() && (!includingLast ? parentLayout.getLastFragment() != this : true)) { if (parentLayout.getLastFragment() == this) { finishFragment(); } else { removeSelfFromStack(true); } } } 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 || id == NotificationCenter.monoForumMessagesRead) { long did = (Long) args[0]; if (dialog_id != did) { return; } long threadId = 0; if (id == NotificationCenter.threadMessagesRead) { threadId = (Integer) args[1]; } else if (id == NotificationCenter.monoForumMessagesRead) { threadId = (Long) args[1]; } if (threadId != threadMessageId && threadMessageId != 0) { 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, false); } } } } } else if (id == NotificationCenter.messagesRead) { if (chatMode == MODE_SCHEDULED || chatMode == MODE_SAVED) { 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 (sideControlsButtonsLayout != null) { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, 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); MessageObject conversionMsg = conversionMessages.get(mid); if (conversionMsg != null) { conversionMessages.remove(mid); if (b >= 0 && b < messages.size()) { messages.remove(b); b--; } } ArrayList dayArr = messagesByDays.get(obj.dateKey); if (dayArr != null) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); messagesByDaysSorted.remove(obj.dateKeyInt); 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++, isTopic); 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]; boolean update = args.length > 2 && (boolean) args[2]; boolean sent = args.length > 3 && (boolean) args[3]; int scheduledMessageId = args.length > 5 ? (int) args[5] : 0; ArrayList sentMessages = null; if (args.length > 6) sentMessages = (ArrayList) args[6]; boolean movedToScheduled = args.length > 4 && (boolean) args[4] || sentMessages != null && !sentMessages.isEmpty(); final ArrayList messages = new ArrayList<>(); MessageObject conversionMessage = null; boolean conversion = false; boolean deletedThreadMessage = false; for (int msg_id : markAsDeletedMessages) { MessageObject msg = messagesDict[0].get(msg_id); if (msg_id == threadMessageId) { deletedThreadMessage = true; } if (msg != null) { if (msg.messageOwner != null && msg.messageOwner.video_processing_pending) { if (conversionMessage == null) conversionMessage = msg; conversion = true; } messages.add(msg); } } if (scheduleNowDialog != null && selectedObject != null && markAsDeletedMessages.contains(selectedObject.getId())) { scheduleNowDialog.dismiss(); scheduleNowDialog = null; } processDeletedMessages(markAsDeletedMessages, channelId, sent, !movedToScheduled); if (movedToScheduled && chatMode != ChatActivity.MODE_SCHEDULED) { getMessagesController().forceNoReload(dialog_id, ChatActivity.MODE_SCHEDULED); openScheduledMessages(scheduledMessageId, true); } else if (chatMode == ChatActivity.MODE_SCHEDULED && update && conversion && LaunchActivity.getSafeLastFragment() == this && isFullyVisible && sentMessages != null && !sentMessages.isEmpty() && parentLayout != null) { if (this.messages.isEmpty() || markAsDeletedMessages.contains(convertingToastMessageId)) { finishFragment(); if (parentLayout == null) return; BulletinFactory.of(parentLayout.getBackgroundFragment()) .createSimpleBulletin(R.raw.contact_check, getString(R.string.VideoConversionDone)) .show(true); } else { int messageId = sentMessages.get(0); BulletinFactory.of(this) .createSimpleBulletin(R.raw.contact_check, getString(R.string.VideoConversionDone), getString(R.string.VideoConversionDoneView), () -> { if (parentLayout == null) return; BaseFragment fragment = parentLayout.getBackgroundFragment(); if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getDialogId() == dialog_id) { finishFragment(); ((ChatActivity) fragment).scrollToMessageId(messageId, 0, true, 0, true, 0); } else { presentFragment(ChatActivity.of(dialog_id, messageId)); } }) .setDuration(3500) .show(true); } } if (deletedThreadMessage && isThreadChat() && !isTopic) { if (parentLayout != null && parentLayout.getLastFragment() == this) { finishFragment(); } else { removeSelfFromStack(); } } } else if (id == NotificationCenter.quickRepliesDeleted) { if (chatMode != MODE_QUICK_REPLIES) return; if ((Long) args[1] != getQuickReplyId()) return; ArrayList markAsDeletedMessages = (ArrayList) args[0]; processDeletedMessages(markAsDeletedMessages, 0, false); } 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); MessageObject conversionMsg = conversionMessages.get(removed.getId()); if (conversionMsg != null) { conversionMessages.remove(removed.getId()); if (index >= 0 && index < messages.size()) { messages.remove(index); } } ArrayList dayArr = messagesByDays.get(removed.dateKey); dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); messagesByDaysSorted.remove(obj.dateKeyInt); if (index >= 0 && index < messages.size()) { messages.remove(index); } } if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } } return; } TLRPC.Message newMsgObj = (TLRPC.Message) args[2]; if (MessageObject.isQuickReply(newMsgObj) && chatMode == MODE_QUICK_REPLIES) { if (threadMessageId == 0) { threadMessageId = MessageObject.getQuickReplyId(newMsgObj); } else if (threadMessageId != MessageObject.getQuickReplyId(newMsgObj)) return; } 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.isOutOwnerCached = null; } 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 && chatMode != MODE_QUICK_REPLIES) { getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode, 0, null, classGuid, null); } if (chatAdapter != null) { ChatMessageCell cell = null; for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == obj) { cell = (ChatMessageCell) child; break; } } chatAdapter.updateRowWithMessageObject(obj, animateSendingViews.contains(cell), 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 (obj.hasEntitiesFromServer()) { obj.generateLayout(null); } if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(obj, false, 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 && currentChat != null) { 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.groupRestrictionsUnlockedByBoosts) { if (chatActivityEnterView != null) { chatActivityEnterView.checkChannelRights(); chatActivityEnterView.setSlowModeTimer(0); } dismissCurrentDialog(); updateSecretStatus(); AndroidUtilities.runOnUIThread(() -> { String title = LocaleController.getString(R.string.BoostingRemoveRestrictionsSuccessTitle); String subTitle = LocaleController.getString(R.string.BoostingRemoveRestrictionsSuccessSubTitle); BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.chats_infotip, title, subTitle).show(); }, 350); } else if (id == NotificationCenter.chatInfoDidLoad) { TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0]; if (currentChat != null && chatFull.id == currentChat.id) { checkGroupEmojiPackHint(); if (chatFull instanceof TLRPC.TL_channelFull) { if (currentChat.megagroup && !ChatObject.isMonoForum(currentChat)) { 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; gotChatInfo(); if (ChatObject.isBoostSupported(currentChat) && !ChatObject.isMonoForum(currentChat) /*chatMode != MODE_SUGGESTIONS*/) { getMessagesController().getBoostsController().getBoostsStats(dialog_id, boostsStatus -> { if (boostsStatus == null) { return; } this.boostsStatus = boostsStatus; getMessagesController().getBoostsController().userCanBoostChannel(dialog_id, boostsStatus, canApplyBoost -> this.canApplyBoosts = canApplyBoost); }); } groupCall = getMessagesController().getGroupCall(currentChat.id, true); if (ChatObject.isChannel(currentChat) && currentChat.megagroup && fragmentContextView != null) { fragmentContextView.checkCall(openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150); } loadSendAsPeers(fragmentBeginToShow); if (chatActivityEnterView != null) { chatActivityEnterView.updateSendAsButton(fragmentBeginToShow); 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); chatActivityEnterView.checkChannelRights(); } updateSecretStatus(); if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().setChatInfo(chatInfo); } if (!isThreadChat() || isTopic) { 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(); 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++) { TL_bots.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, hasQuickReplies, 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]); checkThemeEmoticonOrWallpaper(); if (pendingRequestsDelegate != null) { pendingRequestsDelegate.setChatInfo(chatInfo, true); } checkLeaveChannelButton(); } } 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(R.string.AppName)); Map colorsReplacement = new HashMap<>(); colorsReplacement.put("info1.**", getThemedColor(Theme.key_dialogTopBackground)); colorsReplacement.put("info2.**", getThemedColor(Theme.key_dialogTopBackground)); builder.setTopAnimation(R.raw.not_available, AlertsCreator.NEW_DENY_DIALOG_TOP_ICON_SIZE, false, getThemedColor(Theme.key_dialogTopBackground), colorsReplacement); builder.setTopAnimationIsNew(true); if (reason == 0) { if (currentChat instanceof TLRPC.TL_channelForbidden) { builder.setTitle(LocaleController.getString(R.string.ChannelCantOpenBannedByAdminTitle)); builder.setMessage(LocaleController.getString(R.string.ChannelCantOpenBannedByAdmin)); } else { builder.setTitle(LocaleController.getString(R.string.ChannelPrivate)); builder.setMessage(LocaleController.getString(R.string.ChannelCantOpenPrivate2)); } } else if (reason == 1) { builder.setMessage(LocaleController.getString(R.string.ChannelCantOpenNa)); } else if (reason == 2) { builder.setMessage(LocaleController.getString(R.string.ChannelCantOpenBanned)); } else if (reason == 3) { builder.setTitle(LocaleController.getString(R.string.ChannelPrivate)); builder.setMessage(LocaleController.getString(R.string.JoinByPeekChannelText)); } builder.setPositiveButton(LocaleController.getString(R.string.Close), 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) { setFilterMessages(false); if (threadMessageId != 0) { if (forwardEndReached[0]) { forwardEndReached[0] = false; hideForwardEndReached = false; if (chatAdapter != null && !chatAdapter.isFiltered) { 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]; MessageObject oldPlayingObject = (MessageObject) args[1]; if (messageObject.eventId != 0) { return; } sendSecretMessageRead(messageObject, true); if ((messageObject.isRoundVideo() || messageObject.isVideo()) && fragmentView != null && fragmentView.getParent() != null) { if (!messageObject.isVoiceTranscriptionOpen()) { MediaController.getInstance().setTextureView(createTextureView(true), aspectRatioFrameLayout, videoPlayerContainer, true); boolean needScroll = false; if (oldPlayingObject != null) { int index1 = messages.indexOf(oldPlayingObject); int index2 = messages.indexOf(messageObject); if (index1 >= 0 && index2 >= 0 && Math.abs(index1 - index2) < 5) { needScroll = true; } } updateTextureViewPosition(true, needScroll); if (!needScroll) { checkTextureViewPosition = true; updateMessagesVisiblePart(false); } } else { MediaController.getInstance().setTextureView(createTextureView(true), aspectRatioFrameLayout, videoPlayerContainer, 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); int offset = (int) ((chatListView.getMeasuredHeight() - topPadding - blurredViewBottomOffset) / 2 - (cell.reactionsLayoutInBubble == null ? 0 : cell.reactionsLayoutInBubble.totalHeight)); if (messageObject1.type != MessageObject.TYPE_ROUND_VIDEO) { offset -= cell.getPhotoImage().getImageY(); } else { offset -= (keyboardIsVisible ? AndroidUtilities.roundMessageSize : isSideMenued() ? AndroidUtilities.roundSidePlayingMessageSize : AndroidUtilities.roundPlayingMessageSize(isSideMenued())) / 2; } chatLayoutManager.scrollToPositionWithOffset(position, offset, false); } chatAdapter.notifyItemChanged(position); } } } else if (messageObject1.isVoice() || messageObject1.isMusic() || messageObject1.isRoundVideo()) { 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() || messageObject1.isRoundVideo())) { 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.isRoundVideo()) { if (!MediaController.getInstance().isPlayingMessage(messageObject)) { Bitmap bitmap = null; if (id == NotificationCenter.messagePlayingDidReset && cell.getMessageObject() != null && 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); } } else 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(); } } } } } } 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.isRoundVideo() || 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, false); } if (isVoted != object.isVoted()) { isVotedChanged = true; } } createUndoView(); 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) { try { pollView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {}; if (voters.correct) { fireworksOverlay.start(); } else { ((ChatMessageCell) pollView).shakeView(); showPollSolution(cell.getMessageObject(), results); cell.showHintButton(false, true, 0); } break; } } } } } } else if (id == NotificationCenter.didUpdateExtendedMedia) { long did = (Long) args[0]; doOnIdle(() -> { int msgId = (Integer) args[1]; MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); if (messageObject != null) { messageObject.messageOwner.media.extended_media = (ArrayList) args[2]; messageObject.forceUpdate = true; messageObject.setType(); updateMessageAnimated(messageObject, false); } }); } else if (id == NotificationCenter.didUpdateReactions) { if (isInScheduleMode()) { return; } long did = (Long) args[0]; doOnIdle(() -> { int msgId = (Integer) args[1]; if (filteredMessagesDict != null) { MessageObject messageObject = filteredMessagesDict.get(msgId); if (messageObject != null) { MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); messageObject.forceUpdate = true; messageObject.reactionsChanged = true; } } MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); if (messageObject != null) { MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); messageObject.forceUpdate = true; messageObject.reactionsChanged = true; updateMessageAnimated(messageObject, true); } }); } else if (id == NotificationCenter.savedReactionTagsUpdate) { if (dialog_id != getUserConfig().getClientUserId()) { return; } long topicId = (long) args[0]; if (topicId != 0 && topicId != getSavedDialogId()) { return; } doOnIdle(() -> { AndroidUtilities.forEachViews(chatListView, view -> { if (view instanceof ChatMessageCell) { MessageObject message = ((ChatMessageCell) view).getMessageObject(); if (message != null) { message.forceUpdate = true; message.reactionsChanged = true; } } }); if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } }); } else if (id == NotificationCenter.updateAllMessages) { long dialogId = (long) args[0]; if (dialog_id != dialogId) return; doOnIdle(() -> { AndroidUtilities.forEachViews(chatListView, view -> { if (view instanceof ChatMessageCell) { MessageObject message = ((ChatMessageCell) view).getMessageObject(); if (message != null) { message.forceUpdate = true; } } }); if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(false); } }); } 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, 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.reversed = reversed; 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 (chatAdapter != null && !chatAdapter.isFiltered && index >= 0) { 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, false); } } else { updateVisibleRows(); } } } else if (id == NotificationCenter.voiceTranscriptionUpdate) { if (chatAdapter != null) { MessageObject messageObject = (MessageObject) args[0]; long transcriptionId = 0; String transcriptionText = null; if (args.length > 1 && args[1] != null) { transcriptionId = (Long) args[1]; transcriptionText = (String) args[2]; } final ArrayList messages; if (chatAdapter.isFrozen) { messages = chatAdapter.frozenMessages; } else if (chatAdapter.isFiltered) { messages = chatAdapter.filteredMessages; } else { messages = ChatActivity.this.messages; } if (messages != null && !messages.contains(messageObject) && args.length > 1 && 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; } 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); if (args.length > 3 && args[3] != null || messageObject.messageOwner.voiceTranscriptionOpen) { 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; } } } } AndroidUtilities.runOnUIThread(() -> { updateMessagesVisiblePart(false); }); } } } else if (id == NotificationCenter.animatedEmojiDocumentLoaded) { if (chatAdapter != null) { MessageObject messageObject = (MessageObject) args[0]; if (messageObject != null) { final ArrayList messages; if (chatAdapter.isFrozen) { messages = chatAdapter.frozenMessages; } else if (chatAdapter.isFiltered) { messages = chatAdapter.filteredMessages; } else { messages = 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]; final ArrayList messageObjects = (ArrayList) args[1]; if (replyingMessageObject != null) { for (int i = 0; i < messageObjects.size(); ++i) { MessageObject messageObject = messageObjects.get(i); if (messageObject == null) continue; if (replyingMessageObject.getId() == messageObject.getId() && replyingMessageObject.getDialogId() == did) { replyingMessageObject = messageObject; if (replyingQuote != null) { replyingQuote.checkEdit(messageObject); } if (messagePreviewParams != null) { messagePreviewParams.updateReply(replyingMessageObject, replyingQuoteGroup != null ? replyingQuoteGroup : getGroup(replyingMessageObject.getGroupId()), dialog_id, replyingQuote); } fallbackFieldPanel(); break; } } } if (messagePreviewParams != null) { messagePreviewParams.checkEdits(messageObjects); } if (did != dialog_id && did != mergeDialogId) { return; } int loadIndex = did == dialog_id ? 0 : 1; doOnIdle(() -> { replaceMessageObjects(messageObjects, loadIndex, false); }); } else if (id == NotificationCenter.notificationsSettingsUpdated) { updateTitleIcons(); if (ChatObject.isChannel(currentChat) || UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.id == UserObject.VERIFY) { 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, 0, 0, null, classGuid, null); } for (int a = 0, N = ids.size(); a < N; a++) { Integer mid = ids.get(a); if (pin) { if (pinnedMessageObjects.containsKey(mid)) { continue; } 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); } if (object != null && (!isTopic || getTopicId() == MessageObject.getTopicId(currentAccount, object.messageOwner, ChatObject.isForum(currentChat)))) { pinnedMessageIds.add(mid); pinnedMessageObjects.put(mid, object); if (replaceObjects == null) { totalPinnedMessagesCount++; } updated = true; } } else { if (!pinnedMessageObjects.containsKey(mid)) { continue; } pinnedMessageObjects.remove(mid); pinnedMessageIds.remove(mid); if (replaceObjects == null) { totalPinnedMessagesCount--; } updated = true; } 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, 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); } updatePinnedListButton(true); } if (chatMode == MODE_PINNED) { if (pin) { if (arrayList != null) { processNewMessages(arrayList); } } else { processDeletedMessages(ids, ChatObject.isChannel(currentChat) ? dialog_id : 0, false); } } } 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, 0, 0, null, classGuid, null); updateMessagesVisiblePart(false); } else { pinnedMessageIds.clear(); pinnedMessageObjects.clear(); currentPinnedMessageId = 0; loadedPinnedMessagesCount = 0; totalPinnedMessagesCount = 0; hidePinnedMessageView(true); } } } updatePinnedTopicStarterMessage(); } 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) { if (webPage instanceof TLRPC.TL_webPageEmpty) { foundWebPage = null; if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(foundWebPage, false); } fallbackFieldPanel(); } else { foundWebPage = webPage; if (messagePreviewParams != null) { messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); } if (chatActivityEnterView != null) { chatActivityEnterView.setWebPage(foundWebPage, false); } showFieldPanelForWebPage(true, foundWebPage, 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 (sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); } } } if (chatAdapter != null) { chatAdapter.invalidateRowWithMessageObject(currentMessage); } } } } else if (id == NotificationCenter.botInfoDidLoad) { int guid = (Integer) args[1]; if (classGuid == guid || guid == 0) { TL_bots.BotInfo info = (TL_bots.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, hasQuickReplies, true); TLRPC.User bot = getMessagesController().getUser(info.user_id); hasBotWebView = bot != null && bot.bot_menu_webview; chatActivityEnterView.updateBotWebView(true); } } updateBotButtons(); } } else if (id == NotificationCenter.botKeyboardDidLoad) { MessagesStorage.TopicKey topicKey = (MessagesStorage.TopicKey) args[1]; if (dialog_id == topicKey.dialogId && getTopicId() == topicKey.topicId) { 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]) { updateSearchUpDownButtonVisibility(true); boolean jumpToMessage = (Boolean) args[6]; updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (jumpToMessage) { int messageId = (Integer) args[1]; long did = (Long) args[3]; if (searchingReaction != null && searchingFiltered) { if (chatAdapter.isFiltered) { updateFilteredMessages(true); } else { setFilterMessages(true); } } else if (messageId != 0) { final boolean wasFiltered = chatAdapter.isFiltered; setFilterMessages(false); if (!wasFiltered) { scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, true, 0); } else { updateVisibleRows(); } } else { setFilterMessages(false); updateVisibleRows(); } onSearchLoadingUpdate(false); } else if (searchingReaction != null) { if (chatAdapter.isFiltered) { updateFilteredMessages(true); } else { setFilterMessages(true); } } if (searchItem != null) { searchItem.setShowSearchProgress(false); } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } if (chatAdapter.isFiltered) { AndroidUtilities.runOnUIThread(() -> checkScrollForLoad(false)); } if (hashtagSearchEmptyView != null && searchingHashtag != null && chatMode != MODE_SEARCH) { hashtagSearchEmptyView.showProgress(false); } } } else if (id == NotificationCenter.chatSearchResultsLoading) { if (classGuid == (Integer) args[0]) { if (searchItem != null) { searchItem.setShowSearchProgress(!TextUtils.isEmpty(searchingQuery) || searchingReaction != null); } onSearchLoadingUpdate(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, false); } } } } } if (channelReplies != null) { SparseArray array = channelReplies.get(dialog_id); boolean hasChatInBack = false; if (threadMessageObject != null && !isTopic && parentLayout != null) { for (int a = 0, N = parentLayout.getFragmentStack().size() - 1; a < N; a++) { BaseFragment fragment = parentLayout.getFragmentStack().get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getTopicId() == getTopicId() && 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); if (!groupedMessages.messages.isEmpty()) { MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = messages.indexOf(messageObject); if (index >= 0 && !chatAdapter.isFiltered) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } } if (updatedRows != null && !chatAdapter.isFiltered) { 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); if (chatAdapter != null) { chatAdapter.updateRowsSafe(); } } } 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]; } maxPinnedMessageId = pinnedMessageIds.size() > 0 ? pinnedMessageIds.get(pinnedMessageIds.size() - 1) : 0; int fallbackId = pinnedMessageIds.isEmpty() ? 0 : pinnedMessageIds.get(0); if (isTopic) { int size = pinnedMessageIds.size(); for (int i = 0; i < pinnedMessageIds.size(); i++) { int messageId = pinnedMessages.get(i); MessageObject messageObject = pinnedMessageObjects.get(messageId); if (messageObject == null) { pinnedMessageIds.remove(i); i--; continue; } long messageTopicId = MessageObject.getTopicId(currentAccount, messageObject.messageOwner, true); if (getTopicId() != messageTopicId) { pinnedMessageObjects.remove(messageId); pinnedMessageIds.remove(i); i--; } } } loadedPinnedMessagesCount = pinnedMessageIds.size(); totalPinnedMessagesCount = (Integer) args[3]; pinnedEndReached = (Boolean) args[4]; getMediaDataController().loadReplyMessagesForMessages(new ArrayList<>(pinnedMessageObjects.values()), dialog_id, 0, 0, null, classGuid, null); if (!inMenuMode && !loadingPinnedMessagesList && totalPinnedMessagesCount == 0 && !pinnedEndReached) { getMediaDataController().loadPinnedMessages(dialog_id, 0, fallbackId); loadingPinnedMessagesList = true; } } } else if (id == NotificationCenter.userInfoDidLoad) { Long uid = (Long) args[0]; if (currentUser != null && currentUser.id == uid) { userInfo = (TLRPC.UserFull) args[1]; updateGreetingLock(); updateGreetInfo(); updateBottomOverlay(); checkThemeEmoticonOrWallpaper(); if (chatActivityEnterView != null) { chatActivityEnterView.checkChannelRights(); chatActivityEnterView.updateGiftButton(true); } if (getMessagesController().getSendPaidMessagesStars(getDialogId()) > 0) { if (!StarsController.getInstance(currentAccount).balanceAvailable()) { StarsController.getInstance(currentAccount).getBalance(); } } if (headerItem != null) { showAudioCallAsIcon = userInfo.phone_calls_available && !inPreviewMode; if (avatarContainer != null) { avatarContainer.setTitleExpand(showAudioCallAsIcon); } if (userInfo.phone_calls_available) { if (showAudioCallAsIcon) { if (audioCallIconItem != null) { View item = audioCallIconItem.createView(); if (openAnimationStartTime != 0 && item.getVisibility() != View.VISIBLE) { item.setAlpha(0f); item.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; } updateVisibleWallpaperActions(); if (greetingsViewContainer != null && userInfo != null && userInfo.business_intro != null) { greetingsViewContainer.setPreview(userInfo.business_intro.title, userInfo.business_intro.description); greetingsViewContainer.setSticker(userInfo.business_intro.sticker); } updateGreetInfo(); if (profileChannelMessageFetcher == null) { profileChannelMessageFetcher = new ProfileChannelCell.ChannelMessageFetcher(currentAccount); profileChannelMessageFetcher.fetch(userInfo); } birthdayAssetsFetcher = ProfileBirthdayEffect.BirthdayEffectFetcher.of(currentAccount, userInfo, birthdayAssetsFetcher); updateTopPanel(true); } } else if (id == NotificationCenter.didSetNewWallpapper) { if (fragmentView != null) { updateBackground(); progressView2.invalidate(); if (emptyView != null) { emptyView.invalidate(); } if (bigEmptyView != null) { bigEmptyView.invalidate(); } if (floatingDateView != null) { floatingDateView.invalidate(); } if (floatingTopicSeparator != null) { floatingTopicSeparator.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]; createUndoView(); if (undoView == null) { return; } 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) { long dialogId = (Long) args[0]; long topicId = (Long) args[1]; if (dialog_id == dialogId && this.getTopicId() == topicId) { int count = (int) args[2]; if (newMentionsCount > count) { newMentionsCount = count; if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); } } } } 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]; boolean fromCache = (boolean) args[2]; if (dialog_id == did) { if (!isTopic) { scheduledMessagesCount = (Integer) args[1]; updateScheduledInterface(openAnimationEnded); } else if (chatMode == 0) { // waitingForLoad.add(lastLoadIndex); // getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } } 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]; long topicId = args[1] instanceof Long ? (Long) args[1]: 0; if (did == dialog_id && getTopicId() == topicId) { if (parentLayout != null && parentLayout.getLastFragment() == 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, themeDelegate.wallpaper, true, null); } } } else if (id == NotificationCenter.chatAvailableReactionsUpdated) { long chatId = (long) args[0]; long topicId = (long) args[1]; if (chatId == -dialog_id && (!isTopic || getTopicId() == topicId)) { chatInfo = getMessagesController().getChatFull(chatId); gotChatInfo(); } } else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) { long dialogId = (long) args[0]; long topicId = (long) args[1]; if (dialogId == dialog_id && ((!isTopic && (!ChatObject.isMonoForum(currentChat) || getTopicId() == 0)) || topicId == getTopicId())) { reactionsMentionCount = (int) args[2]; ArrayList messages = null; if (args[2] != null) { messages = (ArrayList) args[3]; } if (messages != null) { for (int i = 0; i < messages.size(); i++) { int messageId = messages.get(i); BaseCell cell = findMessageCell(messageId, true); if (cell != null && reactionsMentionCount > 0) { reactionsMentionCount--; getMessagesStorage().markMessageReactionsAsRead(getDialogId(), getTopicId(), messageId, true); AndroidUtilities.runOnUIThread(() -> { playReactionAnimation(messageId); }, 200); } } } if (reactionsMentionCount <= 0) { reactionsMentionCount = 0; getMessagesController().markReactionsAsRead(dialogId, getTopicId()); } updateReactionsMentionButton(true); } } else if (id == NotificationCenter.chatWasBoostedByUser) { if (dialog_id == (long) args[2]) { boostsStatus = (TL_stories.TL_premium_boostsStatus) args[0]; canApplyBoosts = (ChannelBoostsController.CanApplyBoost) args[1]; } } else if (id == NotificationCenter.topicsDidLoaded) { if (getMessagesController().isMonoForumWithManageRights(dialog_id)) { if (avatarContainer != null) { avatarContainer.updateSubtitle(); } } else if (isTopic) { if (getParentActivity() == null) { return; } updateTopicTitleIcon(); if (UserObject.isBotForum(currentUser)) { updateTitle(true); } else { updateTopicHeader(); } updateBottomOverlay(); updateTopPanel(true); if (avatarContainer != null) { avatarContainer.updateSubtitle(); } } } else if (id == NotificationCenter.dialogTranslate) { final long dialogId = (long) args[0]; if (getDialogId() != dialogId) { return; } updateTopPanel(true); if (chatListView != null && chatAdapter != null) { boolean updatedPinned = false; saveGeneralScroll(); ArrayList groupChecked = new ArrayList<>(); 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(); boolean update = false; if (messageObject != null && messageObject.updateTranslation(false)) { update = true; MessageObject pinnedMessageObject = pinnedMessageObjects.get(messageObject.getId()); if (pinnedMessageObject != null) { pinnedMessageObject.messageOwner.translatedText = messageObject.messageOwner.translatedText; pinnedMessageObject.messageOwner.translatedToLanguage = messageObject.messageOwner.translatedToLanguage; if (pinnedMessageObject.updateTranslation(currentPinnedMessageId == messageObject.getId())) { updatedPinned = true; } } } MessageObject.GroupedMessages group = groupedMessagesMap.get(messageObject.getGroupId()); if (group != null && !groupChecked.contains(group.groupId)) { for (int j = 0; j < group.messages.size(); ++j) { MessageObject groupMessageObject = group.messages.get(j); if (groupMessageObject != null && groupMessageObject.updateTranslation(false)) { update = true; } } groupChecked.add(group.groupId); } if (messageObject != null && messageObject.replyMessageObject != null) { MessageObject translatedReplyMessageObject = getMessagesController().getTranslateController().findReplyMessageObject(dialogId, messageObject.replyMessageObject.getId()); if (translatedReplyMessageObject != null) { messageObject.replyMessageObject.messageOwner.translatedText = translatedReplyMessageObject.messageOwner.translatedText; messageObject.replyMessageObject.messageOwner.translatedToLanguage = translatedReplyMessageObject.messageOwner.translatedToLanguage; if (messageObject.replyMessageObject.updateTranslation(true)) { update = true; } } } if (update) { messageObject.forceUpdate = true; cell.setMessageObject(messageObject, cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop(), cell.isFirstInChat(), cell.isLastInChatList()); if (group != null) { if (chatListItemAnimator != null) { chatListItemAnimator.groupWillChanged(group); } for (int j = 0; j < group.messages.size(); j++) { group.messages.get(j).forceUpdate = true; } if (chatAdapter != null) { chatAdapter.notifyDataSetChanged(true); } } else if (chatAdapter != null) { chatAdapter.updateRowAtPosition(chatListView.getChildAdapterPosition(child)); } } else { cell.invalidate(); } } } if (!updatedPinned) { for (MessageObject pinnedMessageObject : pinnedMessageObjects.values()) { if (pinnedMessageObject != null && pinnedMessageObject.updateTranslation(currentPinnedMessageId == pinnedMessageObject.getId())) { updatedPinned = true; } } } if (updatedPinned) { updatePinnedMessageView(true, 1); } } checkTranslation(true); updateTranslateItemVisibility(); } else if (id == NotificationCenter.messageTranslated) { final MessageObject messageObject = (MessageObject) args[0]; final boolean summary = args.length > 1 && (boolean) args[1]; if (getDialogId() != messageObject.getDialogId()) { return; } updateMessageTranslation(messageObject, summary); if (args.length > 2 && (boolean) args[2]) { checkTranslation(true); } } else if (id == NotificationCenter.messageTranslating) { MessageObject messageObject = (MessageObject) args[0]; if (getDialogId() != messageObject.getDialogId()) { return; } if (chatListView == null || chatAdapter == null) { return; } for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { child.invalidate(); } } } else if (id == NotificationCenter.dialogIsTranslatable) { final long dialogId = (long) args[0]; if (getDialogId() != dialogId) { return; } updateTopPanel(true); updateTranslateItemVisibility(); } else if (id == NotificationCenter.onReceivedChannelDifference) { final long channelId = (long) args[0]; if (-channelId == dialog_id) { waitingForGetDifference = false; firstLoadMessages(); } } else if (id == NotificationCenter.storiesUpdated) { if (avatarContainer != null) { avatarContainer.avatarImageView.invalidate(); } } else if (id == NotificationCenter.channelRecommendationsLoaded) { final long dialogId = (long) args[0]; if (chatListView != null) { for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell){ ChatMessageCell cell = (ChatMessageCell) child; if (cell.channelRecommendationsCell != null && cell.channelRecommendationsCell.chatId == -dialogId) { boolean wasExpanded = cell.channelRecommendationsCell.isExpanded(); cell.channelRecommendationsCell.update(); if (cell.channelRecommendationsCell.isExpanded() != wasExpanded) { cell.getMessageObject().forceUpdate = true; cell.forceResetMessageObject(); cell.requestLayout(); final int position = chatListView.getChildAdapterPosition(child); if (position >= 0) { chatAdapter.notifyItemChanged(position); } } } } } } } else if (id == NotificationCenter.updateTranscriptionLock) { if (chatListView != null) { for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell){ ChatMessageCell cell = (ChatMessageCell) child; if (cell.transcribeButton != null) { cell.transcribeButton.setLock(TranscribeButton.showTranscribeLock(cell.getMessageObject()), true); } } } } } else if (id == NotificationCenter.savedMessagesDialogsUpdate) { checkSavedMessagesHint(); if (avatarContainer != null) { avatarContainer.updateSubtitle(true); } if (savedChatsItem != null && savedChatsGap != null) { savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE); } if (chatMode == MODE_SAVED && !isInsideContainer && getUserConfig().getClientUserId() != getSavedDialogId() && !getMessagesController().getSavedMessagesController().containsDialog(getSavedDialogId())) { finishFragment(); } } else if (id == NotificationCenter.quickRepliesUpdated) { // hasQuickReplies = currentUser != null && chatMode == 0 && !currentUser.bot && QuickRepliesController.getInstance(currentAccount).hasReplies(); // if (chatActivityEnterView != null) { // chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands, hasQuickReplies, true); // } } else if (id == NotificationCenter.businessLinksUpdated) { String businessLinkArgument = arguments.getString("business_link"); if (businessLinkArgument != null) { TL_account.TL_businessChatLink link = BusinessLinksController.getInstance(currentAccount).findLink(businessLinkArgument); if (link != null) { businessLink = link; updateTitle(true); } } } else if (id == NotificationCenter.premiumFloodWaitReceived) { invalidateMessagesVisiblePart(); } else if (id == NotificationCenter.hashtagSearchUpdated) { int guid = (Integer) args[0]; if (guid != classGuid) { return; } int count = (Integer) args[1]; endReached[0] = (Boolean) args[2]; int mask = (Integer) args[3]; hashtagSearchSelectedIndex = (Integer) args[4]; int jumpToMessageId = (Integer) args[5]; updateSearchButtons(mask, hashtagSearchSelectedIndex, count); if (jumpToMessageId != 0) { scrollToMessageId(jumpToMessageId, 0, true, 0, true, 0); } else { if (messagesSearchAdapter.loadedCount <= 0 && messagesSearchListView.getLayoutManager() != null) { messagesSearchListView.getLayoutManager().scrollToPosition(0); } messagesSearchAdapter.notifyDataSetChanged(); } if (hashtagSearchEmptyView != null) { hashtagSearchEmptyView.showProgress(false); } } else if (id == NotificationCenter.factCheckLoaded) { updateVisibleRows(msg -> msg != null && msg.getFactCheck() != null); } else if (id == NotificationCenter.availableEffectsUpdate) { updateVisibleRows(msg -> msg != null && msg.getEffect() != null); } else if (id == NotificationCenter.starReactionAnonymousUpdate) { final long did = (long) args[0]; final int mid = (int) args[1]; final long peer = (long) args[2]; if (dialog_id != did) return; MessageObject messageObject = messagesDict[0].get(mid); if (messageObject != null) { messageObject.setMyPaidReactionDialogId(peer); } } else if (id == NotificationCenter.messagesFeeUpdated) { final long did = (long) args[0]; if (dialog_id != did && getSendMonoForumPeerId() != did) return; updateTopPanel(true); updateBottomOverlay(true); } else if (id == NotificationCenter.starBalanceUpdated) { updateTopPanel(true); updateBottomOverlay(true); updateGreetingLock(); updateGreetInfo(); } else if (id == NotificationCenter.botForumTopicDidCreate) { final BotForumHelper.BotForumTopicCreateNotification arg = (BotForumHelper.BotForumTopicCreateNotification) args[0]; if (dialog_id != arg.dialogId) return; if (getTopicId() != 0) return; if (topicsTabs != null) { topicsTabs.selectTopic(arg.topicId, false); } clearOnLoadButIsNewTopic = true; // This is a newly created topic. } else if (id == NotificationCenter.botForumDraftUpdate) { final BotForumHelper.BotForumTextDraftUpdateNotification arg = (BotForumHelper.BotForumTextDraftUpdateNotification) args[0]; if (dialog_id != arg.botUserId) return; if (getTopicId() != arg.botTopicId) return; final ArrayList arr = new ArrayList<>(1); arr.add(arg.messageObject); if (arg.isNew) { processNewMessages(arr); } else { replaceMessageObjects(arr, 0, false); } } else if (id == NotificationCenter.botForumDraftDelete) { final BotForumHelper.BotForumTextDraftDeleteNotification arg = (BotForumHelper.BotForumTextDraftDeleteNotification) args[0]; final ArrayList arr = new ArrayList<>(1); if (dialog_id != arg.botUserId) return; if (getTopicId() != arg.botTopicId) return; arr.add(arg.messageId); processDeletedMessages(arr, -dialog_id, false); if (avatarContainer != null) { avatarContainer.updateSubtitle(true); } } } private AlertDialog quoteMessageUpdateAlert; public void showQuoteMessageUpdate() { if (quoteMessageUpdateAlert != null) { return; } String sender = replyingMessageObject != null ? getMessagesController().getFullName(replyingMessageObject.getSenderId()) : ""; quoteMessageUpdateAlert = new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(LocaleController.getString(R.string.UpdatedQuoteTitle)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.UpdatedQuoteMessage, sender))) .setPositiveButton(LocaleController.getString(R.string.Edit), (d, w) -> { if (messagePreviewParams != null && messagePreviewParams.quote != null) { openForwardingPreview(MessagePreviewView.TAB_REPLY); } }) .setNegativeButton(LocaleController.getString(R.string.Cancel), (d, w) -> { hideFieldPanel(true); }) .setOnDismissListener(d -> { quoteMessageUpdateAlert = null; }) .show(); } private void saveGeneralScroll() { int scrollByCellHeight = 0; ChatMessageCell scrollByCell = null; for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; int visibleHeight = Math.min(cell.getBottom(), chatListView.getHeight()) - Math.max(0, cell.getTop()); if (visibleHeight > scrollByCellHeight) { scrollByCell = cell; scrollByCellHeight = visibleHeight; } } } if (scrollByCell != null) { chatLayoutManager.scrollToPositionWithOffset(chatListView.getChildAdapterPosition(scrollByCell), scrollByCell.getTop() - (int) chatListViewPaddingTop, false); } } private int getScrollingOffsetForView(View v) { FileLog.d("getScrollingOffsetForView view=" + v + " results in {"+(chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom())+"} chatHeight=" + chatListView.getMeasuredHeight() + " bottom=" + v.getBottom() + " paddingBottom=" + chatListView.getPaddingBottom()); return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); } private boolean updateMessageTranslation(MessageObject messageObject, boolean scroll) { if (messageObject == null || messageObject.messageOwner == null) { return false; } boolean updated = false; for (MessageObject pinnedMessageObject : pinnedMessageObjects.values()) { if (pinnedMessageObject != null && pinnedMessageObject.getId() == messageObject.getId()) { pinnedMessageObject.messageOwner.translatedText = messageObject.messageOwner.translatedText; pinnedMessageObject.messageOwner.translatedToLanguage = messageObject.messageOwner.translatedToLanguage; if (pinnedMessageObject.updateTranslation(true)) { updatePinnedMessageView(true, 1); updated = true; } } } if (chatListView == null) { return updated; } ArrayList groupChecked = new ArrayList<>(); for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; MessageObject cellMessageObject = cell.getMessageObject(); if (cellMessageObject == null) { continue; } boolean update = false; if (cellMessageObject.getId() == messageObject.getId()) { cellMessageObject.messageOwner.translatedText = messageObject.messageOwner.translatedText; cellMessageObject.messageOwner.translatedToLanguage = messageObject.messageOwner.translatedToLanguage; cellMessageObject.messageOwner.summaryText = messageObject.messageOwner.summaryText; cellMessageObject.messageOwner.translatedSummaryText = messageObject.messageOwner.translatedSummaryText; cellMessageObject.messageOwner.translatedSummaryLanguage = messageObject.messageOwner.translatedSummaryLanguage; if (cellMessageObject.updateTranslation(false)) { update = true; ArrayList dependentMessages = replyMessageOwners.get(cellMessageObject.getId()); if (dependentMessages != null) { updateMessagesReplyTranslation(dependentMessages, messageObject); } } } MessageObject.GroupedMessages group = groupedMessagesMap.get(messageObject.getGroupId()); if (group != null && !groupChecked.contains(group.groupId)) { for (int j = 0; j < group.messages.size(); ++j) { MessageObject groupMessageObject = group.messages.get(j); if (groupMessageObject != null && groupMessageObject.updateTranslation(false)) { update = true; } } groupChecked.add(group.groupId); } if (cellMessageObject.replyMessageObject != null && cellMessageObject.replyMessageObject.getId() == messageObject.getId() && cellMessageObject.replyMessageObject.getDialogId() == messageObject.getDialogId()) { cellMessageObject.replyMessageObject.messageOwner.translatedText = messageObject.messageOwner.translatedText; cellMessageObject.replyMessageObject.messageOwner.translatedToLanguage = messageObject.messageOwner.translatedToLanguage; cellMessageObject.replyMessageObject.messageOwner.translatedSummaryText = messageObject.messageOwner.translatedSummaryText; cellMessageObject.replyMessageObject.messageOwner.translatedSummaryLanguage = messageObject.messageOwner.translatedSummaryLanguage; if (cellMessageObject.replyMessageObject.updateTranslation(false)) { update = true; } } if (update) { if (scroll) { chatLayoutManager.scrollToPositionWithOffset(chatListView.getChildAdapterPosition(child), cell.getTop() - (int) chatListViewPaddingTop, false); } else { saveGeneralScroll(); } cellMessageObject.forceUpdate = true; cell.setMessageObject(cellMessageObject, cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop(), cell.isFirstInChat(), cell.isLastInChatList()); if (group != null) { if (chatListItemAnimator != null) { chatListItemAnimator.groupWillChanged(group); } for (int j = 0; j < group.messages.size(); j++) { group.messages.get(j).forceUpdate = true; } chatAdapter.notifyDataSetChanged(true); } else { chatAdapter.updateRowAtPosition(chatListView.getChildAdapterPosition(child)); } updated = true; } } } return updated; } private boolean updateMessagesReplyTranslation(ArrayList messageIds, MessageObject translatedReplyMessageObject) { boolean updated = false; for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; MessageObject cellMessageObject = cell.getMessageObject(); boolean update = false; if (cellMessageObject != null && messageIds.contains(cellMessageObject.getId()) && cellMessageObject.replyMessageObject != null && cellMessageObject.replyMessageObject.getId() == translatedReplyMessageObject.getId()) { cellMessageObject.replyMessageObject.messageOwner.translatedText = translatedReplyMessageObject.messageOwner.translatedText; cellMessageObject.replyMessageObject.messageOwner.translatedToLanguage = translatedReplyMessageObject.messageOwner.translatedToLanguage; if (cellMessageObject.replyMessageObject.updateTranslation(false)) { update = true; } } if (update) { cellMessageObject.forceUpdate = true; cell.setMessageObject(cellMessageObject, cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop(), cell.isFirstInChat(), cell.isLastInChatList()); chatAdapter.updateRowAtPosition(chatListView.getChildAdapterPosition(child)); updated = true; } } } return updated; } private long lastTranslationCheck; private void checkTranslation(boolean force) { if (System.currentTimeMillis() - lastTranslationCheck > 1000) { force = true; } AndroidUtilities.cancelRunOnUIThread(checkTranslationRunnable); AndroidUtilities.runOnUIThread(checkTranslationRunnable, force ? 0 : 150); } private Runnable checkTranslationRunnable = () -> { lastTranslationCheck = System.currentTimeMillis(); if (chatListView != null && chatAdapter != null) { int minId = Integer.MAX_VALUE, maxId = Integer.MIN_VALUE; for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; if (cell.getCurrentMessagesGroup() != null) { for (int j = 0; j < cell.getCurrentMessagesGroup().messages.size(); ++j) { final int mid = cell.getCurrentMessagesGroup().messages.get(j).getId(); minId = Math.min(minId, mid); maxId = Math.max(maxId, mid); } } else if (cell.getMessageObject() != null) { final int mid = cell.getMessageObject().getId(); minId = Math.min(minId, mid); maxId = Math.max(maxId, mid); } } } if (minId <= maxId) { ArrayList groupsChecked = new ArrayList<>(); for (int i = 0; i < messages.size(); ++i) { MessageObject messageObject = messages.get(i); MessageObject.GroupedMessages group = groupedMessagesMap.get(messageObject.getGroupId()); if (group != null) { if (!groupsChecked.contains(group.groupId)) { for (int j = 0; j < group.messages.size(); ++j) { MessageObject messageObject1 = group.messages.get(j); if (messageObject1 != null) { final int mid = messageObject1.getId(); getMessagesController().getTranslateController().checkTranslation( messageObject1, mid >= minId - 7 && mid <= maxId + 7 ); } } groupsChecked.add(group.groupId); } } else { final int mid = messageObject.getId(); getMessagesController().getTranslateController().checkTranslation( messageObject, mid >= minId - 7 && mid <= maxId + 7 ); } } } } if (currentPinnedMessageId > 0 && pinnedMessageObjects != null) { getMessagesController().getTranslateController().checkTranslation(pinnedMessageObjects.get(currentPinnedMessageId), true); } updateTranslateItemVisibility(); }; private void checkSecretMessageForLocation(MessageObject messageObject) { if (messageObject.type != MessageObject.TYPE_GEO || 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 == MessageObject.TYPE_GEO) { cell.forceResetMessageObject(); } } } }, true, themeDelegate); } private void loadSendAsPeers(boolean animatedUpdate) { if (sendAsPeersObj != null || currentChat == null || !ChatObject.canSendAsPeers(currentChat) || chatActivityEnterView == null || ChatObject.isMonoForum(currentChat)) { return; } sendAsPeersObj = getMessagesController().getSendAsPeers(dialog_id); if (sendAsPeersObj != null) { chatActivityEnterView.updateSendAsButton(animatedUpdate); } } private int sponsoredMessagesPostsBetween; private boolean sponsoredMessagesAdded; private Pattern sponsoredUrlPattern; private MessageObject botSponsoredMessage; private void addSponsoredMessages(boolean animated) { if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) && !UserObject.isBot(currentUser) || !forwardEndReached[0] || getUserConfig().isPremium() && getMessagesController().isSponsoredDisabled() || isReport()) { return; } MessagesController.SponsoredMessagesInfo res = getMessagesController().getSponsoredMessages(dialog_id); if (res == null || res.messages == null) { return; } for (int i = 0; i < res.messages.size(); i++) { MessageObject messageObject = res.messages.get(i); messageObject.resetLayout(); if (messageObject.sponsoredUrl != null) { try { if (sponsoredUrlPattern == null) { sponsoredUrlPattern = Pattern.compile("https://t\\.me/(\\w+)(?:/(\\d+))?"); } Matcher matcher = sponsoredUrlPattern.matcher(messageObject.sponsoredUrl); if (matcher.matches()) { String username = matcher.group(1); int postId = 0; try { postId = matcher.groupCount() >= 2 ? Integer.parseInt(matcher.group(2)) : 0; } catch (Exception e2) {} TLObject obj = getMessagesController().getUserOrChat(username); long did; if (obj instanceof TLRPC.User) { did = ((TLRPC.User) obj).id; } else if (obj instanceof TLRPC.Chat) { did = -((TLRPC.Chat) obj).id; } else { continue; } if (postId < 0) continue; getMessagesController().ensureMessagesLoaded(did, postId, null); } } catch (Exception e) { FileLog.e(e, false); } } } sponsoredMessagesAdded = true; if (UserObject.isBot(currentUser)) { botSponsoredMessage = res == null || res.messages == null || res.messages.isEmpty() ? null : res.messages.get(0); updateTopPanel(true); } else { sponsoredMessagesPostsBetween = res.posts_between != null ? res.posts_between : 0; if (notPushedSponsoredMessages != null) { notPushedSponsoredMessages.clear(); } processNewMessages(res.messages, false); } } public void removeFromSponsored(MessageObject message) { if (message == botSponsoredMessage) { botSponsoredMessage = null; updateTopPanel(true); return; } MessagesController.SponsoredMessagesInfo sponsoredMessagesInfo = getMessagesController().getSponsoredMessages(dialog_id); if (sponsoredMessagesInfo != null) { sponsoredMessagesInfo.messages.remove(message); } } private void checkGroupCallJoin(boolean fromServer) { if (groupCall == null || voiceChatHash == null && !openVideoChat || !openAnimationEnded) { if (voiceChatHash != null && fromServer && chatInfo != null && chatInfo.call == null && fragmentView != null && getParentActivity() != null) { BulletinFactory.of(this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString(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; openVideoChat = false; } 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.isFiltered) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); } } } if (updatedRows != null && !chatAdapter.isFiltered) { 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 (sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, 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 (sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonCount( ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); } showMentionDownButton(true, true); } } checkScrollForLoad(false); return; } messages.clear(); waitingForLoad.clear(); messagesByDays.clear(); messagesByDaysSorted.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); createEmptyView(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, 0); if (parentLayout.getFragmentStack().size() > 1) { BaseFragment prevFragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().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) { createUndoView(); if (undoView == null) { return; } undoView.showWithAction(0, UndoView.ACTION_GIGAGROUP_SUCCESS, null); } }); } @Override protected void onCancel() { createUndoView(); if (undoView == null) { return; } undoView.showWithAction(0, UndoView.ACTION_GIGAGROUP_CANCEL, null); getMessagesController().removeSuggestion(dialog_id, "CONVERT_GIGAGROUP"); } }), (dialog, which) -> { createUndoView(); if (undoView == null) { return; } 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, false); } } } if (update == null) { replyMessageOwners.remove(id); } } private void rotateMotionBackgroundDrawable() { if (themeDelegate == null) { return; } Drawable wallpaper = themeDelegate.getWallpaperDrawable(); if (fragmentView != null) { wallpaper = (contentView).getBackgroundImage(); } if (wallpaper instanceof ChatBackgroundDrawable) { wallpaper = ((ChatBackgroundDrawable) wallpaper).getDrawable(true); } 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 ArrayList notPushedSponsoredMessages; private void processNewMessages(ArrayList arr) { processNewMessages(arr, true); } private void processNewMessages(ArrayList arr, final boolean animatedFromBottom) { FileLog.d("processNewMessages " + arr.size() + " messages"); long currentUserId = getUserConfig().getClientUserId(); boolean updateChat = false; boolean hasFromMe = false; boolean isAd = false; if (chatListItemAnimator != null) { chatListItemAnimator.setShouldAnimateEnterFromBottom(animatedFromBottom); } boolean switchToPendingTopic = false; if (UserObject.isBotForum(currentUser)) { FileLog.d("[BotForum] onDraft check " + getDialogId() + " " + getTopicId()); if (avatarContainer != null) { avatarContainer.updateSubtitle(true); } if (getTopicId() == 0) { for (MessageObject messageObject : arr) { final long topicId = messageObject.getTopicId(); if (messageObject.isSending() && messageObject.isOutOwner() && (topicId == 0 || topicId == 1)) { switchToPendingTopic = true; break; } } } } if (switchToPendingTopic && topicsTabs != null) { topicsTabs.selectTopic(1, false); return; } boolean notifiedSearch = false; LongSparseArray scheduledGroupReplacement = null; for (int a = 0, N = arr.size(); a < N; a++) { FileLog.d("processNewMessages " + a + " our of " + N); MessageObject messageObject = arr.get(a); if (!isAd) { isAd = messageObject.isSponsored(); } if (messageObject.getId() > 0 && (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || messageObject.type == MessageObject.TYPE_ACTION_WALLPAPER)) { for (int i = 0; i < messages.size(); i++) { int type = messageObject.type; if (messages.get(i).type == type && messages.get(i).getId() < 0) { messagesDict[0].remove(messages.get(i).getId()); messagesDict[0].put(messageObject.getId(), messageObject); messageObject.copyStableParams(messages.get(i)); if (type == MessageObject.TYPE_ACTION_WALLPAPER) { final TLRPC.WallPaper oldWallpaper = messages.get(i).messageOwner.action.wallpaper; final long newId = messageObject.messageOwner.action.wallpaper != null ? messageObject.messageOwner.action.wallpaper.id : (oldWallpaper != null ? oldWallpaper.id : 0); messageObject.messageOwner.action.wallpaper = oldWallpaper; if (messageObject.messageOwner.action.wallpaper != null) { messageObject.messageOwner.action.wallpaper.id = newId; } } else if (type == MessageObject.TYPE_SUGGEST_PHOTO) { PhotoUtilities.replacePhotoImagesInCache(currentAccount, messages.get(i).messageOwner.action.photo, messageObject.messageOwner.action.photo); } messages.set(i, messageObject); if (type != MessageObject.TYPE_ACTION_WALLPAPER && chatAdapter.messagesStartRow >= 0) { chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + i); } break; } } } int messageId = messageObject.getId(); if (chatMode != MODE_SAVED && 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()) || TlUtils.isInstance(messageObject.messageOwner.action, TLRPC.TL_messageActionGiftPremium.class, TLRPC.TL_messageActionGiftCode.class, TLRPC.TL_messageActionGiftTon.class)) { 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 && !ChatObject.isIgnoredChatRestrictionsForBoosters(chatInfo)) { 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.getEffect() != null) && !(SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW || !LiteMode.isEnabled(messageObject.isAnimatedAnimatedEmoji() ? LiteMode.FLAG_ANIMATED_EMOJI_CHAT : LiteMode.FLAG_ANIMATED_STICKERS_CHAT))) { 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) || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaidMessagesPrice ) { 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()); } messageObject.applyTimestampsHighlightForReplyMsg(); 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, false); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) { messageObject.generatePaymentSentMessageText(null, true); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionSuggestedPostApproval) { messageObject.generateSuggestionApprovalMessageText(); } } if (messageObject.replyMessageObject != null) { repliesMessagesDict.put(messageObject.replyMessageObject.getId(), messageObject.replyMessageObject); addReplyMessageOwner(messageObject, 0); } } if ((chatMode == MODE_SCHEDULED || chatMode == MODE_QUICK_REPLIES || UserObject.isBotForum(currentUser)) && !arr.isEmpty()) { replaceMessageObjects(arr, 0, true); } boolean needMoveScrollToLastMessage = false; boolean reloadMegagroup = false; if (justCreatedTopic) { forwardEndReached[0] = true; } if (!forwardEndReached[0]) { int currentMaxDate = Integer.MIN_VALUE; for (int a = 0; a < arr.size(); a++) { FileLog.d("processNewMessages " + a + " our of " + arr.size()); MessageObject obj = arr.get(a); if (obj.isOut()) { rotateMotionBackgroundDrawable(); } if (chatMode == MODE_QUICK_REPLIES) { if (!(obj.getQuickReplyId() == getQuickReplyId() || TextUtils.equals(obj.getQuickReplyName(), quickReplyShortcut) || obj.messageOwner != null && obj.messageOwner.quick_reply_shortcut_id == threadMessageId)) { continue; } } else if (chatMode == MODE_SAVED) { if (MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), obj.messageOwner) != threadMessageId) { continue; } } else { 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, false); 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 (obj.messageOwner instanceof TLRPC.TL_messageEmpty) { continue; } if (!isTopic && 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 || isTopic) { if (obj.messageOwner.mentioned && obj.isContentUnread()) { newMentionsCount++; } } if (!isAd) { newUnreadMessageCount++; } if (obj.type == 10 || obj.type == MessageObject.TYPE_ACTION_PHOTO) { updateChat = true; } } if (newUnreadMessageCount != 0 && sideControlsButtonsLayout != null) { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, newUnreadMessageCount, true); } } if (newMentionsCount != 0 && sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); 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; boolean addedAdUnder = false; for (int a = 0; a < arr.size(); a++) { MessageObject obj = arr.get(a); if (obj.scheduled != (chatMode == MODE_SCHEDULED)) { continue; } if (chatMode == MODE_QUICK_REPLIES) { if (!(obj.getQuickReplyId() == getQuickReplyId() || TextUtils.equals(obj.getQuickReplyName(), quickReplyShortcut) || obj.messageOwner != null && obj.messageOwner.quick_reply_shortcut_id == threadMessageId)) { continue; } } else if (chatMode == MODE_SAVED) { if (MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), obj.messageOwner) != threadMessageId) { continue; } } else { if (threadMessageId != 0 && ChatObject.isMonoForum(currentChat) && MessageObject.getMonoForumTopicId(obj.messageOwner) != getThreadId()) { continue; } if (threadMessageId != 0 && !ChatObject.isMonoForum(currentChat) && (!ChatObject.isForum(currentChat) || (!isTopic || getTopicId() != MessageObject.getTopicId(currentAccount, obj.messageOwner, ChatObject.isForum(currentChat)))) && threadMessageId != obj.getReplyTopMsgId() && threadMessageId != obj.getReplyMsgId()) { continue; } } if (obj.isOut() && messagesDict[0].indexOfKey(obj.getId()) < 0) { 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); // MessageObject conversionMsg = conversionMessages.get(removed.getId()); // if (conversionMsg != null) { // conversionMessages.remove(removed.getId()); // if (index >= 0 && index < messages.size()) { // messages.remove(index); // } // } ArrayList dayArr = messagesByDays.get(removed.dateKey); dayArr.remove(removed); if (dayArr.isEmpty()) { messagesByDays.remove(removed.dateKey); messagesByDaysSorted.remove(removed.dateKeyInt); 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 (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 && (chatMode != MODE_QUICK_REPLIES || messages.size() + 1 < getMessagesController().quickReplyMessagesLimit)) { animatingMessageObjects.add(obj); } MessageObject.GroupedMessages groupedMessages; if (obj.hasValidGroupId()) { groupedMessages = groupedMessagesMap.get(obj.getGroupId()); if (groupedMessages == null) { groupedMessages = new MessageObject.GroupedMessages(); groupedMessages.reversed = reversed; 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 || obj.isQuickReply() || messages.isEmpty()) { placeToPaste = 0; } else { final int size = messages.size(); for (int b = 0; b < size; b++) { final 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 || 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 (isAd && sponsoredMessagesPostsBetween > 0) { placeToPaste = findAdPlace(); if (placeToPaste < 0 || placeToPaste > messages.size()) { if (notPushedSponsoredMessages == null) { notPushedSponsoredMessages = new ArrayList<>(); } notPushedSponsoredMessages.add(obj); continue; } } if (isAd && placeToPaste == 0) { addedAdUnder = true; } 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.action instanceof TLRPC.TL_messageActionTodoCompletions || obj.messageOwner.action instanceof TLRPC.TL_messageActionTodoAppendTasks) && !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 (obj.messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL && messages.size() == 2) { placeToPaste = 1; } if (dayArray == null) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); messagesByDaysSorted.put(obj.dateKeyInt, dayArray); if (chatMode != MODE_QUICK_REPLIES) { TLRPC.Message dateMsg = new TLRPC.TL_message(); if (chatMode == MODE_SCHEDULED) { if (obj.messageOwner.date == 0x7ffffffe) { dateMsg.message = LocaleController.getString(R.string.MessageScheduledUntilOnline); } else { dateMsg.message = LocaleController.formatString(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); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false, false); dateObj.type = MessageObject.TYPE_DATE; dateObj.contentType = 1; dateObj.isDateObject = true; dateObj.stableId = getStableIdForDateObject(obj.dateKeyInt); messages.add(placeToPaste, dateObj); if (chatAdapter != null && chatAdapter.messagesStartRow >= 0) { chatAdapter.notifyItemInserted(chatAdapter.messagesStartRow + placeToPaste); } } } if (chatMode != MODE_QUICK_REPLIES && !(obj.messageOwner.action instanceof TLRPC.TL_messageActionGeoProximityReached) && (!obj.isOut() || obj.messageOwner.from_scheduled) && chatMode != MODE_SAVED) { 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.messagesStartRow >= 0) { chatAdapter.notifyItemInserted(chatAdapter.messagesStartRow + 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(chatAdapter.messagesStartRow + 1, size - 1); } } } obj.stableId = lastStableId++; getMessagesController().getTranslateController().checkTranslation(obj, false); messages.add(placeToPaste, obj); if (placeToPaste == 0 && !obj.isSponsored()) { needMoveScrollToLastMessage = true; } if (notPushedSponsoredMessages != null && notPushedSponsoredMessages.contains(obj)) { notPushedSponsoredMessages.remove(obj); } if (chatAdapter != null) { chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + placeToPaste); chatAdapter.notifyItemInserted(chatAdapter.messagesStartRow + placeToPaste); } if (obj.isOut() && waitingForSendingMessageLoad) { waitingForSendingMessageLoad = false; if (!animatingMessageObjects.contains(obj)) { chatActivityEnterView.hideTopView(true); } if (changeBoundAnimator != null) { changeBoundAnimator.start(); } } if (threadMessageId == 0 || isTopic) { if (!obj.isOut() && obj.messageOwner.mentioned && obj.isContentUnread()) { newMentionsCount++; } } if (!isAd) { newUnreadMessageCount++; } if (obj.type == 10 || obj.type == MessageObject.TYPE_ACTION_PHOTO) { 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.theme); } if (webpagesToReload != null) { getMessagesController().reloadWebPages(dialog_id, webpagesToReload, chatMode); } 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 && sideControlsButtonsLayout != null) { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN, newUnreadMessageCount, true); } } canShowPagedownButton = true; updatePagedownButtonVisibility(true); } } else { MessageObject scrollToMessage = null; if (child instanceof ChatMessageCell) { scrollToMessage = ((ChatMessageCell) child).getMessageObject(); } else if (child instanceof ChatActionCell) { scrollToMessage = ((ChatActionCell) child).getMessageObject(); } int scrollToIndex = messages.indexOf(scrollToMessage); if (child != null && scrollToIndex >= 0) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, getScrollingOffsetForView(child)); } } if (newMentionsCount != 0 && sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); 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 (chatMode == MODE_QUICK_REPLIES) { updateBottomOverlay(); } if (!messages.isEmpty() && botUser != null && botUser.length() == 0) { botUser = null; updateBottomOverlay(); } if (updateChat) { updateTitle(false); checkAndUpdateAvatar(); } if (reloadMegagroup) { getMessagesController().loadFullChat(currentChat.id, 0, true); } checkWaitingForReplies(); updateReplyMessageHeader(true); if (!isAd && notPushedSponsoredMessages != null && !notPushedSponsoredMessages.isEmpty() && arr != notPushedSponsoredMessages) { processNewMessages(notPushedSponsoredMessages, false); } invalidatePremiumBlocked(); if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); } if (videoConversionTimeHint != null && videoConversionTimeHint.shown()) { videoConversionTimeHint.hide(); } if (botMessageHint != null && botMessageHint.shown()) { botMessageHint.hide(); } if (factCheckHint != null) { factCheckHint.hide(); } if (currentUser != null && currentUser.bot) { updateTopPanel(true); } } private int getStableIdForDateObject(int date) { int id = dateObjectsStableIds.get(date, -1); if (id == -1) { id = lastStableId++; dateObjectsStableIds.put(date, id); } return id; } private int getStableIdForConversionObject(int mid) { int id = conversionObjectsStableIds.get(mid, -1); if (id == -1) { id = lastStableId++; conversionObjectsStableIds.put(mid, id); } return id; } private void saveScrollPosition() { if (chatListView == null || chatLayoutManager == null || chatLayoutManager.hasPendingScrollPosition()) { return; } int top = 0; int position = RecyclerListView.NO_POSITION; for (int i = 0; i < chatListView.getChildCount(); i++) { View v = chatListView.getChildAt(i); final int vposition = chatListView.getChildAdapterPosition(v); if (vposition < 0) continue; if (v instanceof ChatMessageCell) { position = vposition; top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { position = vposition; top = getScrollingOffsetForView(v); break; } } if (position >= 0) { chatLayoutManager.scrollToPositionWithOffset(position, top); } } 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, boolean sent) { processDeletedMessages(markAsDeletedMessages, channelId, sent, true); } private void processDeletedMessages(ArrayList markAsDeletedMessages, long channelId, boolean sent, boolean thanos) { ArrayList removedIndexes = new ArrayList<>(); ArrayList thanosMessagesIndexes = new ArrayList<>(); final int currentTime = getConnectionsManager().getCurrentTime(); 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; } if (replyingMessageObject != null && markAsDeletedMessages.contains(replyingMessageObject.getId())) { replyingMessageObject = null; replyingQuote = null; fallbackFieldPanel(); } 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 && !isTopic && parentLayout != null) { for (int a = 0, N = parentLayout.getFragmentStack().size() - 1; a < N; a++) { BaseFragment fragment = parentLayout.getFragmentStack().get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && getTopicId() == getTopicId() && chatActivity.getChatMode() == getChatMode()) { hasChatInBack = true; break; } } } } int commentsDeleted = 0; for (int a = 0; a < size; a++) { Integer mid = markAsDeletedMessages.get(a); MessageObject obj = chatAdapter != null && chatAdapter.isFiltered ? filteredMessagesDict.get(mid) : messagesDict[loadIndex].get(mid); if (selectedObject != null && obj == selectedObject || obj != null && selectedObjectGroup != null && selectedObjectGroup == groupedMessagesMap.get(obj.getGroupId())) { closeMenu(); } if (PhotoViewer.isPlayingMessage(obj)) { PhotoViewer.getInstance().closePhoto(false, false); } else if (PhotoViewer.isPlayingMessageInPip(obj)) { PhotoViewer.getPipInstance().destroyPhotoViewer(); } 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 (obj.scheduled && sent) { obj.scheduledSent = true; } if (editingMessageObject == obj) { hideFieldPanel(true); } int index = chatAdapter != null && chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : 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 = chatAdapter != null && chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.remove(index) : messages.remove(index); if (chatAdapter != null) { if (chatAdapter.isFiltered) { int mindex = -1; for (int i = 0; i < messages.size(); ++i) { if (messages.get(i).getId() == obj.getId()) { mindex = i; break; } } if (mindex >= 0) { messages.remove(mindex); } getMediaDataController().removeMessageFromResults(removed.getId()); } else if (filteredMessagesDict != null) { MessageObject msg = filteredMessagesDict.get(mid); if (msg != null) { filteredMessagesDict.remove(mid); chatAdapter.filteredMessages.remove(msg); getMediaDataController().removeMessageFromResults(msg.getId()); } } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } removedIndexes.add(chatAdapter.messagesStartRow + index); if (thanos && !sent && !obj.scheduledSent && removed != null && removed.messageOwner != null && removed.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT && currentTime - removed.messageOwner.date >= (currentChat != null || currentUser != null && currentUser.bot ? 2 : 0)) { thanosMessagesIndexes.add(chatAdapter.messagesStartRow + index); removed.deletedByThanos = LiteMode.isEnabled(LiteMode.FLAG_CHAT_THANOS); } } 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); MessageObject conversionMsg = conversionMessages.get(mid); if (conversionMsg != null) { conversionMessages.remove(mid); int dindex = index; if (chatAdapter != null && chatAdapter.isFiltered) { dindex = messages.indexOf(obj); } if (dindex >= 0 && dindex < messages.size()) { messages.remove(dindex); if (chatAdapter != null && !chatAdapter.isFiltered) { removedIndexes.add(chatAdapter.messagesStartRow + dindex); } } } ArrayList dayArr = messagesByDays.get(obj.dateKey); if (dayArr != null) { dayArr.remove(obj); if (dayArr.isEmpty()) { messagesByDays.remove(obj.dateKey); messagesByDaysSorted.remove(obj.dateKeyInt); int dindex = index; if (chatAdapter != null && chatAdapter.isFiltered) { dindex = messages.indexOf(obj); } if (dindex >= 0 && dindex < messages.size()) { messages.remove(dindex); if (chatAdapter != null && !chatAdapter.isFiltered) { removedIndexes.add(chatAdapter.messagesStartRow + dindex); } } } } if (filteredMessagesByDays != null) { dayArr = filteredMessagesByDays.get(obj.dateKeyInt); if (dayArr != null) { MessageObject mobj = chatAdapter != null && chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; dayArr.remove(mobj); if (dayArr.isEmpty()) { filteredMessagesByDays.remove(obj.dateKeyInt); int dindex = index; if (chatAdapter != null && !chatAdapter.isFiltered) { dindex = chatAdapter.filteredMessages.indexOf(mobj); } if (chatAdapter != null && dindex >= 0 && dindex < chatAdapter.filteredMessages.size()) { chatAdapter.filteredMessages.remove(dindex); if (chatAdapter.isFiltered) { removedIndexes.add(chatAdapter.messagesStartRow + dindex); } } } } } updated = true; } } } if (updatedReplies) { updateReplyMessageHeader(true); } if (commentsDeleted != 0 && replyOriginalChat != null) { 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 = chatAdapter.getMessages().indexOf(messageObject); if (index >= 0) { if (chatAdapter != null && !chatAdapter.isFrozen) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); } } } } } if (messages.isEmpty()) { if (!endReached[0] && !loading) { if (!chatAdapter.isFiltered) { 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++, isTopic); 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 && !chatAdapter.isFrozen) { int prevHintRow = chatAdapter.hintRow; int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; int prevUserNameTimeRow = chatAdapter.userNameTimeRow; int prevUserPhotoTimeRow = chatAdapter.userPhotoTimeRow; for (int a = 0, N = removedIndexes.size(); a < N; a++) { final int pos = removedIndexes.get(a); chatAdapter.notifyItemRemoved(pos, thanosMessagesIndexes.contains(pos)); } if (!isThreadChat() || messages.size() <= 3) { removeUnreadPlane(false); } if (chatAdapter.getMessages().isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevLoadingDownRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevHintRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevUserNameTimeRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevUserPhotoTimeRow >= 0) { chatAdapter.notifyItemRemoved(0); } } else { chatAdapter.notifyItemRangeChanged(chatAdapter.messagesStartRow, chatAdapter.getMessages().size()); } } updateVisibleRows(); if (chatMode == MODE_QUICK_REPLIES) { updateBottomOverlay(); } } else if (threadMessageId == 0) { first_unread_id = 0; last_message_id = 0; createUnreadMessageAfterId = 0; removeMessageObject(unreadMessageObject); unreadMessageObject = null; } if (updateScheduled) { updateScheduledInterface(true); } invalidatePremiumBlocked(); if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); } if (videoConversionTimeHint != null && videoConversionTimeHint.shown()) { videoConversionTimeHint.hide(); } if (chatMode == MODE_QUICK_REPLIES && messages != null && messages.isEmpty()) { threadMessageId = 0; } } private final BotForumHelper.BotDraftAnimationsPool botDraftAnimationsPool = new BotForumHelper.BotDraftAnimationsPool(); 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 (messageObject.getId() > 0 && old == null && UserObject.isBotForum(currentUser)) { old = BotForumHelper.getInstance(currentAccount).onBotForumDraftCheckNewMessages(currentUser.id, (int) getTopicId(), messageObject.getId(), messageObject.messageText.toString()); if (old != null) { botDraftAnimationsPool.bind(old.messageOwner.id, messageObject.getId()); old.messageOwner.id = old.messageOwner.local_id = messageObject.getId(); old.messageOwner.date = messageObject.messageOwner.date; } } 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 || messageObject.scheduled && chatMode != MODE_SCHEDULED) { 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, false); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) { messageObject.generatePaymentSentMessageText(null, true); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionSuggestedPostApproval) { messageObject.generateSuggestionApprovalMessageText(); } } if (old.isWebpage() && messageObject.isWebpage()) { TLRPC.TL_messageMediaWebPage media = (TLRPC.TL_messageMediaWebPage) MessageObject.getMedia(old.messageOwner); if (media.webpage != null && "telegram_story".equals(media.webpage.type)) { TL_stories.StoryItem storyItem = null; for (int i = 0; i < media.webpage.attributes.size(); ++i) { TLRPC.WebPageAttribute attr = media.webpage.attributes.get(i); if (attr instanceof TLRPC.TL_webPageAttributeStory) { storyItem = ((TLRPC.TL_webPageAttributeStory) attr).storyItem; break; } } if (storyItem != null) { TLRPC.TL_messageMediaWebPage newMedia = (TLRPC.TL_messageMediaWebPage) MessageObject.getMedia(messageObject.messageOwner); for (int i = 0; i < newMedia.webpage.attributes.size(); ++i) { TLRPC.WebPageAttribute attr = newMedia.webpage.attributes.get(i); if (attr instanceof TLRPC.TL_webPageAttributeStory) { TLRPC.TL_webPageAttributeStory storyAttr = (TLRPC.TL_webPageAttributeStory) attr; if (!(storyAttr.storyItem instanceof TL_stories.TL_storyItem)) { storyAttr.storyItem = storyItem; } break; } } } } } 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.reversed = reversed; 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); groupedMessages.positionsArray.remove(old.getId()); if (oldPosition != null) { groupedMessages.positions.put(messageObject, oldPosition); groupedMessages.positionsArray.put(messageObject.getId(), oldPosition); } if (newGroups == null) { newGroups = new LongSparseArray<>(); } newGroups.put(groupedMessages.groupId, groupedMessages); } } } } if (chatMode == MODE_SAVED) { messageObject.isSaved = true; } if (messageObject.type >= 0) { messageObject.reactionsChanged |= old.isBotPendingDraft && !messageObject.isBotPendingDraft; messageObject.copyStableParams(old); messages.set(index, messageObject); if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); } if (index2 >= 0) { dayArr.set(index2, messageObject); } } else { messages.remove(index); if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } MessageObject conversionMsg = conversionMessages.get(old.getId()); if (conversionMsg != null) { conversionMessages.remove(old.getId()); messages.remove(index); int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; int prevUserNameTimeRow = chatAdapter.userNameTimeRow; int prevUserPhotoTimeRow = chatAdapter.userPhotoTimeRow; if (!chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); if (messages.isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevLoadingDownRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevUserNameTimeRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevUserPhotoTimeRow >= 0) { chatAdapter.notifyItemRemoved(0); } } } } if (index2 >= 0) { dayArr.remove(index2); if (dayArr.isEmpty()) { messagesByDays.remove(old.dateKey); messagesByDaysSorted.remove(old.dateKeyInt); messages.remove(index); int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; int prevUserNameTimeRow = chatAdapter.userNameTimeRow; int prevUserPhotoTimeRow = chatAdapter.userPhotoTimeRow; if (!chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); if (messages.isEmpty()) { if (prevLoadingUpRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevLoadingDownRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevUserNameTimeRow >= 0) { chatAdapter.notifyItemRemoved(0); } if (prevUserPhotoTimeRow >= 0) { chatAdapter.notifyItemRemoved(0); } } } } } } } updateReplyMessageOwners(old.getId(), messageObject); } if (newGroups != null) { for (int b = 0; b < newGroups.size(); b++) { final MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); if (groupedMessages.messages.isEmpty()) { groupedMessagesMap.remove(groupedMessages.groupId); } else { groupedMessages.calculate(); final MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); final 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); } } } } } } updatePinnedTopicStarterMessage(); } private void migrateToNewChat(MessageObject obj) { if (parentLayout == null) { return; } final long channelId = obj.messageOwner.action.channel_id; final BaseFragment lastFragment = parentLayout.getFragmentStack().size() > 0 ? parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 1) : null; int index = parentLayout.getFragmentStack().indexOf(ChatActivity.this); INavigationLayout actionBarLayout = parentLayout; if (index > 0 && !(lastFragment instanceof ChatActivity) && !(lastFragment instanceof ProfileActivity) && currentChat.creator) { for (int a = index, N = actionBarLayout.getFragmentStack().size() - 1; a < N; a++) { BaseFragment fragment = actionBarLayout.getFragmentStack().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.getFragmentStack().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) { int duration = Math.max(4000, Math.min((text == null ? 0 : text.length()) / 50 * 1600, 10000)); BulletinFactory.of(this).createSimpleBulletin(R.raw.chats_infotip, text, 9999).setDuration(duration).setOnHideListener(() -> { 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; }).show(true); hintMessageObject = messageObject; hintMessageType = type; } private void showPollSolution(MessageObject messageObject, TLRPC.PollResults results) { if (results == null || TextUtils.isEmpty(results.solution)) { return; } String string = results.solution; ArrayList entities = results.solution_entities; if (messageObject != null && messageObject.translated && messageObject.messageOwner != null && messageObject.messageOwner.translatedPoll != null && messageObject.messageOwner.translatedPoll.solution != null) { string = messageObject.messageOwner.translatedPoll.solution.text; entities = messageObject.messageOwner.translatedPoll.solution.entities; } CharSequence text; if (!entities.isEmpty()) { text = new SpannableStringBuilder(string); text = Emoji.replaceEmoji(text, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), false); text = MessageObject.replaceAnimatedEmoji(text, entities, Theme.chat_msgBotButtonPaint.getFontMetricsInt()); MessageObject.addEntitiesToText(text, entities, false, true, true, false); } else { text = string; text = Emoji.replaceEmoji(text, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), false); } showInfoHint(messageObject, text, 0); } private void updateSearchButtons(int mask, int num, int count) { if (sideControlsButtonsLayout != null) { sideControlsButtonsLayout.setButtonEnabled(ChatActivitySideControlsButtonsLayout.BUTTON_SEARCH_UP, (mask & (reversed ? 2 : 1)) != 0, true); sideControlsButtonsLayout.setButtonEnabled(ChatActivitySideControlsButtonsLayout.BUTTON_SEARCH_DOWN, (mask & (reversed ? 1 : 2)) != 0, true); } searchLastCount = count; searchLastIndex = num; updateSearchCountText(); if (searchExpandList != null) { searchExpandList.setClickable(count > 0); searchExpandList.animate().alpha(count > 0 ? 1f : 0.5f).start(); } } private void updateSearchCountText() { if (searchCountText != null) { boolean animated = !LocaleController.isRTL; if (searchLastCount < 0) { searchCountText.setText("", animated); } else if (searchLastCount == 0) { searchCountText.setText(LocaleController.getString(R.string.NoResult), animated); } else if (searchingFiltered) { searchCountText.setText(LocaleController.formatPluralString("TaggedMessages", searchLastCount), animated); } else if (chatMode == MODE_SEARCH || messagesSearchListContainer.getTag() != null) { searchCountText.setText(LocaleController.formatPluralString("SearchMessagesResultCount", searchLastCount, LocaleController.formatNumber(searchLastCount, ' ')), animated); } else { searchCountText.setText(LocaleController.formatString(R.string.Of, searchLastIndex + 1, searchLastCount), animated); } } } @Override public boolean needDelayOpenAnimation() { if (chatMode != MODE_SCHEDULED && getParentLayout() != null && getParentLayout().getFragmentStack().size() > 1) { BaseFragment previousFragment = getParentLayout().getFragmentStack().get(getParentLayout().getFragmentStack().size() - 2); if (previousFragment instanceof ChatActivity && ((ChatActivity) previousFragment).isKeyboardVisible()) { return false; } } return firstLoading; } @Override public void onBecomeFullyVisible() { isFullyVisible = true; super.onBecomeFullyVisible(); if (showCloseChatDialogLater) { showDialog(closeChatDialog); } if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); } if (keyboardWasVisible) { if (chatActivityEnterView != null) { chatActivityEnterView.openKeyboardInternal(); chatActivityEnterView.freezeEmojiView(false); } keyboardWasVisible = false; } if (savedMessagesHint != null) { AndroidUtilities.runOnUIThread(this::checkSavedMessagesHint, 600); } if (convertingToast && !convertingToastShown) { convertingToastShown = true; BulletinFactory.of(this) .createSimpleBulletin(R.raw.convert_video, getString(R.string.VideoConversionTitle), getString(R.string.VideoConversionText)) .setDuration(Bulletin.DURATION_PROLONG) .setOnHideListener(this::checkConversionDateTimeToast) .show(true); } } private boolean shownConversionDateTimeToast; private void checkConversionDateTimeToast() { if (shownConversionDateTimeToast || !isFullyVisible || !chatListView.isAttachedToWindow() || getContext() == null) return; final int[] loc = new int[2]; ChatMessageCell foundCell = null; for (int i = chatListView.getChildCount() - 1; i >= 0; --i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; if ( cell.getMessageObject() != null && cell.getMessageObject().messageOwner != null && cell.getMessageObject().messageOwner.video_processing_pending && (cell.getCurrentPosition() == null || cell.getMessageObject() != null && (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (cell.getCurrentPosition().flags & (cell.getMessageObject().isOutOwner() ? MessageObject.POSITION_FLAG_LEFT : MessageObject.POSITION_FLAG_RIGHT)) != 0) ) { cell.getLocationInWindow(loc); final float y = loc[1] + cell.getTimeY(); if (y >= dp(240) && y <= AndroidUtilities.displaySize.y - dp(25) - AndroidUtilities.navigationBarHeight) { foundCell = cell; break; } } } } if (foundCell != null) { shownConversionDateTimeToast = true; videoConversionTimeHint = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); setTranslationY(-getTop() - dp(120) + videoConversionTimeHintY); } } .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_CENTER) .setDuration(3500) .setHideByTouch(true) .useScale(true) .setMaxWidth(150) .setRounding(8); videoConversionTimeHint.setText(LocaleController.getString(R.string.VideoConversionTimeInfo)); contentView.addView(videoConversionTimeHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); foundCell.getLocationInWindow(loc); videoConversionTimeHintY = loc[1] + foundCell.getTimeY(); videoConversionTimeHint.setTranslationY(- videoConversionTimeHint.getTop() - dp(120) + videoConversionTimeHintY); videoConversionTimeHint.setJointPx(0, -dp(16) + loc[0] + foundCell.timeX + foundCell.timeWidth / 2f); videoConversionTimeHint.show(); } else { AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkConversionDateTimeToast); AndroidUtilities.runOnUIThread(ChatActivity.this::checkConversionDateTimeToast, 2000); } } private boolean checkedSavedMessagesHint; private boolean savedMessagesHintShown; private void checkSavedMessagesHint() { if (checkedSavedMessagesHint) return; checkedSavedMessagesHint = true; if (!savedMessagesHintShown && chatMode == 0 && !getMessagesController().getSavedMessagesController().unsupported && getMessagesController().getSavedMessagesController().getAllCount() > 2) { if (savedMessagesHint != null && MessagesController.getGlobalMainSettings().getInt("savedhint", 0) < 1) { savedMessagesHint.show(); savedMessagesHintShown = true; MessagesController.getGlobalMainSettings().edit() .putInt("savedhint", MessagesController.getGlobalMainSettings().getInt("savedhint", 0) + 1) .putInt("savedsearchhint", MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) + 1) .apply(); } else if (savedMessagesSearchHint != null && MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) < 1) { savedMessagesSearchHint.show(); savedMessagesHintShown = true; MessagesController.getGlobalMainSettings().edit().putInt("savedsearchhint", MessagesController.getGlobalMainSettings().getInt("savedsearchhint", 0) + 1).apply(); } else { checkSavedMessagesTagHint(); } } } private long lastScrollTime; private boolean savedMessagesTagHintShown; private void checkSavedMessagesTagHint() { if (savedMessagesTagHint == null || savedMessagesTagHint.shown() || savedMessagesTagHintShown || !checkedSavedMessagesHint) { return; } if (savedMessagesTagHint != null && (messagesSearchListContainer == null || messagesSearchListContainer.getTag() == null) && System.currentTimeMillis() - lastScrollTime > 1800 && MessagesController.getGlobalMainSettings().getInt("savedsearchtaghint", 0) < 1) { final int[] loc = new int[2]; ChatMessageCell foundCell = null; for (int i = chatListView.getChildCount() - 1; i >= 0; --i) { View child = chatListView.getChildAt(i); if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; if (cell.areTags() && !cell.reactionsLayoutInBubble.reactionButtons.isEmpty()) { cell.getLocationInWindow(loc); final float y = loc[1] + cell.reactionsLayoutInBubble.y; if (y >= dp(240) && y <= AndroidUtilities.displaySize.y - dp(25) - AndroidUtilities.navigationBarHeight) { foundCell = cell; break; } } } } if (foundCell != null) { savedMessagesTagHintShown = true; ReactionsLayoutInBubble.ReactionButton btn = foundCell.reactionsLayoutInBubble.reactionButtons.get(0); foundCell.getLocationInWindow(loc); savedMessagesTagHint.setTranslationY(loc[1] - savedMessagesTagHint.getTop() - dp(120) + foundCell.reactionsLayoutInBubble.y); savedMessagesTagHint.setJointPx(0, -dp(16) + loc[0] + foundCell.reactionsLayoutInBubble.x + btn.width / 2f); savedMessagesTagHint.show(); MessagesController.getGlobalMainSettings().edit().putInt("savedsearchtaghint", 1).apply(); } else { AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkSavedMessagesTagHint); AndroidUtilities.runOnUIThread(ChatActivity.this::checkSavedMessagesTagHint, 2000); } } } @Override public void onBecomeFullyHidden() { hideTagSelector(); if (!getMessagesController().premiumFeaturesBlocked() && getMessagesController().transcribeAudioTrialWeeklyNumber <= 0 && !getMessagesController().didPressTranscribeButtonEnough() && !getUserConfig().isPremium() && messages != null) { for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); if (msg != null && !msg.isOutOwner() && (msg.isVoice() || msg.isRoundVideo()) && !msg.isUnread() && (msg.isContentUnread() || ChatObject.isChannelAndNotMegaGroup(currentChat))) { TranscribeButton.showOffTranscribe(msg, false); } } } isFullyVisible = false; hideUndoViews(); if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(Theme.getColor(Theme.key_windowBackgroundWhite)); } TranscribeButton.resetVideoTranscriptionsOpen(); if (progressDialogCurrent != null) { progressDialogCurrent.cancel(); progressDialogCurrent = null; } flagSecure.detach(); super.onBecomeFullyHidden(); } 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); } } long startMs; @Override public void onTransitionAnimationStart(boolean isOpen, boolean backward) { super.onTransitionAnimationStart(isOpen, backward); startMs = System.currentTimeMillis(); 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); NotificationCenter.getGlobalInstance().onAnimationFinish(transitionAnimationGlobalIndex); // if (Build.VERSION.SDK_INT >= 21) { // createChatAttachView(); // } checkGroupCallJoin(lastCallCheckFromServer); boolean hintShown = false; if (ChatObject.isMonoForum(currentChat) && !ChatObject.canManageMonoForum(currentAccount, currentChat)) { hintShown = chatActivityEnterView.showSendSuggestionHint(); } if (!hintShown && 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(); hintShown = true; } } } if (!backward && parentLayout != null && needRemovePreviousSameChatActivity) { for (int a = 0, N = parentLayout.getFragmentStack().size() - 1; a < N; a++) { BaseFragment fragment = parentLayout.getFragmentStack().get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; if (chatActivity.needRemovePreviousSameChatActivity && chatActivity.dialog_id == dialog_id && chatActivity.getTopicId() == getTopicId() && chatActivity.getChatMode() == getChatMode() && chatActivity.threadMessageId == threadMessageId && chatActivity.isReport() == isReport()) { fragment.removeSelfFromStack(); break; } } } } showScheduledOrNoSoundHint(); if (!backward && firstOpen) { if (chatActivityEnterView != null && (threadMessageObject != null && threadMessageObject.getRepliesCount() == 0 && ChatObject.canSendMessages(currentChat) && !isTopic || chatMode == MODE_EDIT_BUSINESS_LINK)) { 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(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(R.string.PsaInfoDefault); } } else { message = null; } } else { message = null; } if (!TextUtils.isEmpty(message)) { checkTopUndoView(); 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 (PULL_DOWN_BACK_FRAGMENT) { if (!backward && fromPullingDownTransition && parentLayout != null && parentLayout.getFragmentStack().size() >= 2) { BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2); if (fragment instanceof ChatActivity) { backToPreviousFragment = (ChatActivity) fragment; parentLayout.removeFragmentFromStack(backToPreviousFragment); } } } if (pendingRequestsDelegate != null && backward) { pendingRequestsDelegate.onBackToScreen(); } updateMessagesVisiblePart(false); } else { getNotificationCenter().onAnimationFinish(transitionAnimationIndex); NotificationCenter.getGlobalInstance().onAnimationFinish(transitionAnimationGlobalIndex); } contentView.invalidate(); if (!TextUtils.isEmpty(attachMenuBotToOpen)) { openAttachBotLayout(attachMenuBotToOpen); attachMenuBotToOpen = null; } checkGroupEmojiPackHint(); } private void checkGroupEmojiPackHint() { if (groupEmojiPackHint == null && ChatObject.isMegagroup(currentChat)) { final TLRPC.ChatFull chatFull = getMessagesController().getChatFull(currentChat.id); if (chatFull == null || chatFull.emojiset == null || chatActivityEnterView == null || getContext() == null) { return; } if (bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE) { return; } if (MessagesController.getGlobalMainSettings().getBoolean("groupEmojiPackHintShown", false)) { return; } TLRPC.StickerSet emojiSet = chatFull.emojiset; long thumbDocumentId = emojiSet.thumb_document_id; if (thumbDocumentId == 0) { TLRPC.TL_messages_stickerSet stickerSet = getMediaDataController().getGroupStickerSetById(emojiSet); if (stickerSet != null && !stickerSet.documents.isEmpty()) { thumbDocumentId = stickerSet.documents.get(0).id; } } if (thumbDocumentId == 0 || getContext() == null) { return; } MessagesController.getGlobalMainSettings().edit().putBoolean("groupEmojiPackHintShown", true).apply(); groupEmojiPackHint = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM); groupEmojiPackHint.setCloseButton(true); groupEmojiPackHint.setMultilineText(true); groupEmojiPackHint.setTextAlign(Layout.Alignment.ALIGN_CENTER); groupEmojiPackHint.setRounding(12); SpannableStringBuilder packFullName = new SpannableStringBuilder("d"); packFullName.setSpan(new AnimatedEmojiSpan(thumbDocumentId, groupEmojiPackHint.getTextPaint().getFontMetricsInt()), 0, packFullName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); SpannableStringBuilder titleBuilder = new SpannableStringBuilder(chatFull.emojiset.title); titleBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, titleBuilder.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE); packFullName.append(" "); packFullName.append(titleBuilder); groupEmojiPackHint.setText(AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.GroupEmojiPackHint), packFullName)); groupEmojiPackHint.setMaxWidthPx(HintView2.cutInFancyHalf(groupEmojiPackHint.getText(), groupEmojiPackHint.getTextPaint())); groupEmojiPackHint.setDuration(-1); groupEmojiPackHint.setPadding(dp(6), 0, dp(6), 0); AndroidUtilities.runOnUIThread(() -> { FrameLayout.LayoutParams lp = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 0, 0); lp.bottomMargin = chatActivityEnterView.getMeasuredHeight(); contentView.addView(groupEmojiPackHint, lp); groupEmojiPackHint.setJointPx(0, chatActivityEnterView.getEmojiButton().getX() + dp(18)); groupEmojiPackHint.show(); }, 300); } } public boolean groupEmojiPackHintWasVisible() { boolean result = false; if (groupEmojiPackHint != null) { result = true; if (groupEmojiPackHint.shown()) { groupEmojiPackHint.hide(); } } groupEmojiPackHint = null; return result; } public void openAttachBotLayout(String botUsername) { TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); req.username = botUsername; 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, false); } else if (attachMenuBot.show_in_attach_menu || attachMenuBot.show_in_side_menu) { WebAppDisclaimerAlert.show(getContext(), ignore -> { TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); botRequest.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); botRequest.enabled = true; botRequest.write_allowed = true; ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { attachMenuBot.inactive = attachMenuBot.side_menu_disclaimer_needed = false; if (error2 == null) { MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); openAttachBotLayout(user.id, attachMenuBotStartCommand, false); } }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); }, null, null); } else { AttachBotIntroTopView introTopView = new AttachBotIntroTopView(getParentActivity()); introTopView.setColor(Theme.getColor(Theme.key_chat_attachIcon)); introTopView.setBackgroundColor(Theme.getColor(Theme.key_dialogTopBackground)); introTopView.setAttachBot(attachMenuBot); AtomicBoolean allowWrite = new AtomicBoolean(); AlertDialog.Builder builder = 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; botRequest.write_allowed = allowWrite.get(); ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { if (error2 == null) { attachMenuBot.inactive = attachMenuBot.side_menu_disclaimer_needed = false; MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); openAttachBotLayout(user.id, attachMenuBotStartCommand, false); } }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); }) .setNegativeButton(LocaleController.getString(R.string.Cancel), null); if (attachMenuBot.request_write_access) { allowWrite.set(true); CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 5, getResourceProvider()); cell.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); cell.setBackground(Theme.getSelectorDrawable(false)); cell.setMultiline(true); cell.setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.OpenUrlOption2, UserObject.getUserName(user))), "", true, false); cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); cell.setOnClickListener(v -> { boolean allow = !cell.isChecked(); cell.setChecked(allow, true); allowWrite.set(allow); }); builder.setCustomViewOffset(6); builder.setView(cell); } builder.show(); } } })); } } } })); } public void openAttachBotLayout(long botId, String startCommand, boolean justAdded) { openAttachMenu(); createChatAttachView(); if (chatAttachAlert != null) { chatAttachAlert.showBotLayout(botId, startCommand, justAdded, false); } } @Override protected void onDialogDismiss(Dialog dialog) { if (closeChatDialog != null && dialog == closeChatDialog) { getMessagesController().deleteDialog(dialog_id, 0); if (parentLayout != null && !parentLayout.getFragmentStack().isEmpty() && parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 1) != this) { BaseFragment fragment = parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 1); removeSelfFromStack(); fragment.finishFragment(); } else { finishFragment(); } } } @Override public boolean extendActionMode(Menu menu) { if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { if (PhotoViewer.getInstance().getSelectionLength() == 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, currentEncryptedChat, true, true); return true; } public static void fillActionModeMenu(Menu menu, TLRPC.EncryptedChat encryptedChat, boolean chat, boolean includeLinks) { if (menu.findItem(R.id.menu_bold) != null) { return; } if (Build.VERSION.SDK_INT >= 23) { menu.removeItem(android.R.id.shareText); } int order = 6; if (chat) { menu.add(R.id.menu_groupbolditalic, R.id.menu_quote, order++, LocaleController.getString(R.string.Quote)); } menu.add(R.id.menu_groupbolditalic, R.id.menu_spoiler, order++, LocaleController.getString(R.string.Spoiler)); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString(R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, order++, stringBuilder); stringBuilder = new SpannableStringBuilder(LocaleController.getString(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(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 (encryptedChat == null || AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 101) { stringBuilder = new SpannableStringBuilder(LocaleController.getString(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(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); } if (includeLinks) menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, LocaleController.getString(R.string.CreateLink)); menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, LocaleController.getString(R.string.Regular)); } private void updateScheduledInterface(boolean animated) { if (chatActivityEnterView != null) { chatActivityEnterView.updateScheduleButton(animated); } } public void updateBottomOverlay() { updateBottomOverlay(false); } public void updateBottomOverlay(boolean animated) { if (bottomOverlayChatText == null || chatMode == MODE_SCHEDULED || getContext() == null) { return; } bottomOverlayChatWaitsReply = false; bottomOverlayLinks = false; boolean accentTextButton = false; boolean forceVisible = false; boolean forceNoBottom = false; boolean showGiftButton = false; boolean showSuggestButton = false; boolean showSearchButton = chatMode == MODE_DEFAULT && ChatObject.isChannelOrGiga(currentChat); boolean showGigaGroupButton = false; if (chatMode == MODE_DEFAULT && getMessagesController().isFrozen() && !AccountFrozenAlert.isSpamBot(currentAccount, currentUser)) { if (bottomOverlayStartButton != null) { bottomOverlayStartButton.setVisibility(View.GONE); } forceVisible = true; bottomOverlayLinks = true; bottomOverlayChatText.setVisibility(View.GONE); bottomOverlayLinksText.setVisibility(View.VISIBLE); bottomOverlayLinksText.setTextColor(getThemedColor(Theme.key_graySectionText)); bottomOverlayLinksText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); final SpannableStringBuilder sb = new SpannableStringBuilder(); sb.append(getString(R.string.AccountFrozenBottomTitle)); sb.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_text_RedBold)), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sb.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sb.append("\n"); sb.append(getString(R.string.AccountFrozenBottomSubtitle)); bottomOverlayLinksText.setText(sb); bottomOverlayLinksText.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(getThemedColor(Theme.key_featuredStickers_addButton), .05f), Theme.RIPPLE_MASK_ALL)); bottomOverlayLinksText.setClickable(true); showBottomOverlayProgress(false, false); } else if (chatMode == MODE_DEFAULT && getDialogId() != getUserConfig().getClientUserId() && userInfo != null && userInfo.contact_require_premium && !getUserConfig().isPremium()) { bottomOverlayLinks = true; bottomOverlayChatText.setVisibility(View.GONE); bottomOverlayLinksText.setVisibility(View.VISIBLE); bottomOverlayLinksText.setTextColor(getThemedColor(Theme.key_graySectionText)); bottomOverlayLinksText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); bottomOverlayLinksText.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.OnlyPremiumCanMessage, UserObject.getFirstName(currentUser)), Theme.key_chat_messageLinkIn, 0, () -> { ChatGreetingsView.showPremiumSheet(getContext(), currentAccount, dialog_id, themeDelegate); })); bottomOverlayLinksText.setClickable(false); showBottomOverlayProgress(false, false); } else if (chatMode == MODE_QUICK_REPLIES && messages.size() >= getMessagesController().quickReplyMessagesLimit) { bottomOverlayLinks = true; bottomOverlayChatText.setVisibility(View.GONE); bottomOverlayLinksText.setVisibility(View.VISIBLE); bottomOverlayLinksText.setTextColor(getThemedColor(Theme.key_graySectionText)); bottomOverlayLinksText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); bottomOverlayLinksText.setText(AndroidUtilities.replaceTags(LocaleController.formatPluralString("BusinessRepliesLimit", getMessagesController().quickReplyMessagesLimit))); bottomOverlayLinksText.setClickable(false); showBottomOverlayProgress(false, false); if (chatActivityEnterView != null) { chatActivityEnterView.hidePopup(false); } } else if (chatMode == MODE_SAVED && getSavedDialogId() != getUserConfig().getClientUserId()) { if (getSavedDialogId() == UserObject.ANONYMOUS) { forceNoBottom = true; } else { bottomOverlayChatText.setTag(null); bottomOverlayChatText.setText(LocaleController.getString(currentUser != null ? R.string.SavedOpenChatNoCaps : (ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.SavedOpenChannelNoCaps : R.string.SavedOpenGroupNoCaps))); showBottomOverlayProgress(false, false); } } else if (isReport()) { updateActionModeTitle(); } else if (chatMode == MODE_PINNED) { boolean allowPin; if (currentChat != null) { allowPin = ChatObject.canPinMessages(currentChat) && (!currentChat.monoforum /*|| ChatObject.canManageMonoForum(currentAccount, currentChat)*/); } else { if (userInfo != null) { allowPin = userInfo.can_pin_message; } else { allowPin = false; } } if (allowPin) { bottomOverlayChatText.setTag(1); bottomOverlayChatText.setText(LocaleController.getString(R.string.UnpinAllMessagesNoCaps)); } else { bottomOverlayChatText.setTag(null); bottomOverlayChatText.setText(LocaleController.getString(R.string.HidePinnedMessagesNoCaps)); } showBottomOverlayProgress(false, false); } else if (currentUser != null && currentUser.id == UserObject.VERIFY) { if (!getMessagesController().isDialogMuted(dialog_id, getTopicId())) { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelMuteNoCaps), false); bottomOverlayChatText.setEnabled(true); } else { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelUnmuteNoCaps), true); bottomOverlayChatText.setEnabled(true); } showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); } 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) && !UserObject.isBotForum(currentUser) && (ChatObject.isForum(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(ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.ChannelJoinRequestSentNoCaps : R.string.GroupJoinRequestSentNoCaps), true); bottomOverlayChatText.setEnabled(false); } else { bottomOverlayChatText.setText(LocaleController.getString(ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.ChannelJoinRequestNoCaps : R.string.GroupJoinRequestNoCaps)); bottomOverlayChatText.setEnabled(true); accentTextButton = true; } } else { bottomOverlayChatText.setText(LocaleController.getString(ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.ChannelJoinNoCaps : R.string.GroupJoinNoCaps)); bottomOverlayChatText.setEnabled(true); showGiftButton = chatInfo != null && chatInfo.stargifts_available; showSuggestButton = currentChat.broadcast_messages_allowed && currentChat.linked_monoforum_id != 0; accentTextButton = true; } showBottomOverlayProgress(false, false); } } else if (shouldDisplaySwipeToLeftToReplyInForum()) { bottomOverlayChatWaitsReply = true; showBottomOverlayProgress(false, false); bottomOverlayChatText.setTextInfo(LocaleController.getString(R.string.ForumReplyToMessagesInTopic)); bottomOverlayChatText.setEnabled(false); } else if (!isThreadChat()) { if (!getMessagesController().isDialogMuted(dialog_id, getTopicId())) { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelMuteNoCaps), false); bottomOverlayChatText.setEnabled(true); } else { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelUnmuteNoCaps), true); bottomOverlayChatText.setEnabled(true); } showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); showGiftButton = chatInfo != null && chatInfo.stargifts_available; showSuggestButton = currentChat.broadcast_messages_allowed && currentChat.linked_monoforum_id != 0; } else if (forumTopic != null && forumTopic.closed) { if (!ChatObject.canManageTopic(currentAccount, currentChat, forumTopic)) { Drawable lock = getContext().getResources().getDrawable(R.drawable.msg_mini_lock2).mutate(); lock.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteGrayText), PorterDuff.Mode.MULTIPLY)); bottomOverlayChatText.setTextInfo(lock, LocaleController.getString(R.string.TopicClosedByAdmin)); bottomOverlayChatText.setEnabled(false); } showBottomOverlayProgress(false, false); } } else if (shouldDisplaySwipeToLeftToReplyInForum()) { bottomOverlayChatWaitsReply = true; showBottomOverlayProgress(false, false); bottomOverlayChatText.setTextInfo(LocaleController.getString(R.string.ForumReplyToMessagesInTopic)); bottomOverlayChatText.setEnabled(false); } else if (!isThreadChat()) { bottomOverlayChatText.setText(LocaleController.getString(R.string.DeleteThisGroup)); bottomOverlayChatText.setEnabled(true); } if (bottomOverlayStartButton != null) { bottomOverlayStartButton.setVisibility(View.GONE); } if (!shouldApply && requestedTime > 0) { MessagesController.getNotificationsSettings(currentAccount).edit().putLong("dialog_join_requested_time_" + dialog_id, -1).commit(); } } else { showBottomOverlayProgress(false, true); if (userBlocked) { if (bottomOverlayStartButton != null) { bottomOverlayStartButton.setVisibility(View.GONE); } if (currentUser.bot) { bottomOverlayChatText.setText(LocaleController.getString(R.string.BotUnblockNoCaps)); } else { bottomOverlayChatText.setText(LocaleController.getString(R.string.Unblock)); } bottomOverlayChatText.setVisibility(View.VISIBLE); 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, getTopicId())) { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelMuteNoCaps), false); } else { bottomOverlayChatText.setText(LocaleController.getString(R.string.ChannelUnmuteNoCaps), true); } showBottomOverlayProgress(false, true); } else if (botUser != null && currentUser.bot && !UserObject.isDeleted(currentUser) && !UserObject.isBotForum(currentUser)) { // bottomOverlayStartButton.setText(LocaleController.getString(R.string.BotStart)); if (bottomOverlayStartButton != null) { bottomOverlayStartButton.setVisibility(View.VISIBLE); } bottomOverlayChatText.setVisibility(View.GONE); chatActivityEnterView.hidePopup(false); if (getParentActivity() != null) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } if (!messages.isEmpty() && currentUser != null && botUser.length() != 0) { sentBotStart = true; } } else { bottomOverlayChatText.setText(LocaleController.getString(R.string.DeleteThisChat)); } } if (currentChat != null && currentChat.gigagroup && !isReport() && chatMode == 0) { showGigaGroupButton = true; showGiftButton = false; showSuggestButton = false; } if (inPreviewMode) { bottomViewsVisibilityController.setViewVisible(MESSAGE_SEARCH_CONTAINER, false, false); bottomChannelButtonsLayout.setVisibility(View.INVISIBLE); chatActivityEnterView.setFieldFocused(false); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (bottomOverlayLinks || forceVisible) { bottomChannelButtonsLayout.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (searchItem != null && searchItemVisible) { createSearchContainer(); if (searchContainer == null) { return; } bottomViewsVisibilityController.setViewVisible(MESSAGE_SEARCH_CONTAINER, true, true); if (searchCountText != null) { searchCountText.setText("", false); } if (searchExpandAnimator != null) { searchExpandAnimator.removeAllListeners(); searchExpandAnimator.cancel(); } if (searchExpandProgress != 1f) { searchExpandAnimator = ValueAnimator.ofFloat(searchExpandProgress, 1f); searchExpandAnimator.addUpdateListener(animation -> { searchExpandProgress = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); }); searchExpandAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { searchExpandProgress = 1f; chatActivityEnterView.setVisibility(View.INVISIBLE); bottomChannelButtonsLayout.setVisibility(View.INVISIBLE); invalidateChatListViewTopPadding(); } }); searchExpandAnimator.setDuration(250); searchExpandAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); searchExpandAnimator.start(); } else { chatActivityEnterView.setVisibility(View.INVISIBLE); bottomChannelButtonsLayout.setVisibility(View.INVISIBLE); invalidateChatListViewTopPadding(); } chatActivityEnterView.setFieldFocused(false); if (chatActivityEnterView.isTopViewVisible()) { topViewWasVisible = 1; chatActivityEnterView.hideTopView(false); } else { topViewWasVisible = 2; } } else if (chatMode == MODE_SEARCH) { createSearchContainer(); if (searchContainer == null) { return; } bottomViewsVisibilityController.setViewVisible(MESSAGE_SEARCH_CONTAINER, true, false); invalidateChatListViewTopPadding(); } else { bottomViewsVisibilityController.setViewVisible(MESSAGE_SEARCH_CONTAINER, false, true); 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(); 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 (isInsideContainer || forceNoBottom) { bottomChannelButtonsLayout.setVisibility(View.GONE); chatActivityEnterView.setVisibility(View.GONE); } else if (isReport()) { bottomChannelButtonsLayout.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (chatMode == MODE_PINNED || currentChat != null && (!ChatObject.isMonoForum(currentChat) || !isSubscriberSuggestions) && ((ChatObject.isNotInChat(currentChat) && !UserObject.isBotForum(currentUser) || !ChatObject.canWriteToChat(currentChat)) && (currentChat.join_to_send || !isThreadChat() || ChatObject.isForum(currentChat)) || forumTopic != null && forumTopic.closed && !ChatObject.canManageTopic(currentAccount, currentChat, forumTopic) || shouldDisplaySwipeToLeftToReplyInForum()) || currentUser != null && (UserObject.isDeleted(currentUser) || userBlocked || UserObject.isReplyUser(currentUser))) { if (chatActivityEnterView.isEditingMessage()) { chatActivityEnterView.setVisibility(View.VISIBLE); // AndroidUtilities.updateViewShow(bottomChannelButtonsLayout, false, false, true); bottomChannelButtonsLayout.setVisibility(View.INVISIBLE); chatActivityEnterView.setFieldFocused(); AndroidUtilities.runOnUIThread(() -> chatActivityEnterView.openKeyboard(), 100); } else { bottomChannelButtonsLayout.setVisibility(View.VISIBLE); // AndroidUtilities.updateViewShow(bottomChannelButtonsLayout, true, false, true); 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 != null && !UserObject.isBotForum(currentUser) && currentUser.bot || currentUser != null && currentUser.id == UserObject.VERIFY || chatMode == MODE_SAVED && getSavedDialogId() != getUserConfig().getClientUserId()) { bottomChannelButtonsLayout.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else { bottomChannelButtonsLayout.setVisibility(View.INVISIBLE); chatActivityEnterView.setVisibility(View.VISIBLE); } } if (topViewWasVisible == 1) { chatActivityEnterView.showTopView(false, false); topViewWasVisible = 0; } } if (sentBotStart) { bottomChannelButtonsLayout.setVisibility(View.GONE); chatActivityEnterView.setVisibility(View.VISIBLE); chatActivityEnterView.setBotInfo(botInfo); } bottomOverlayChatText.setTextColorKey(accentTextButton ? Theme.key_featuredStickers_buttonText : Theme.key_glass_defaultText); bottomChannelButtonsLayout.setCenterAccentBackground(accentTextButton, animated); bottomChannelButtonsLayout.showButton(ChatActivityChannelButtonsLayout.BUTTON_SEARCH, showSearchButton && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE, animated); bottomChannelButtonsLayout.showButton(ChatActivityChannelButtonsLayout.BUTTON_DIRECT, showSuggestButton && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE, animated); bottomChannelButtonsLayout.showButton(ChatActivityChannelButtonsLayout.BUTTON_GIFT, showGiftButton && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE, animated); bottomChannelButtonsLayout.showButton(ChatActivityChannelButtonsLayout.BUTTON_GIGA_GROUP_INFO, showGigaGroupButton && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE, animated); checkRaiseSensors(); } private boolean shouldDisplaySwipeToLeftToReplyInForum() { return ( isForumInViewAsMessagesMode() && replyingMessageObject == null && editingMessageObject == null && !canSendMessageToGeneralTopic() ); } private boolean canSendMessageToTopic(MessageObject message) { if (chatMode == MODE_SUGGESTIONS) { return true; } if (message != null && ChatObject.isForum(currentChat)) { TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, MessageObject.getTopicId(currentAccount, message.messageOwner, true)); return canSendMessageToTopic(topic); } return false; } private boolean canSendMessageToGeneralTopic() { if (chatMode == MODE_SUGGESTIONS) { return false; } if (isForumInViewAsMessagesMode() && currentChat != null) { TLRPC.TL_forumTopic generalTopic = getMessagesController().getTopicsController().findTopic(currentChat.id, 1); return canSendMessageToTopic(generalTopic); } return false; } private boolean canSendMessageToTopic(TLRPC.TL_forumTopic topic) { if (chatMode == MODE_SUGGESTIONS) { return true; } return topic != null && (!topic.closed || ChatObject.canManageTopic(currentAccount, currentChat, topic)); } public void updateReplyMessageHeader(boolean notify) { if (chatMode == MODE_SAVED || UserObject.isBotForum(currentUser)) { return; } if (avatarContainer != null && threadMessageId != 0) { if (isTopic) { updateTopicHeader(); } else if (isComments) { if (threadMessageObject != null && threadMessageObject.hasReplies()) { avatarContainer.setTitle(LocaleController.formatPluralString("Comments", threadMessageObject.getRepliesCount())); } else { avatarContainer.setTitle(LocaleController.getString(R.string.CommentsTitle)); } } else if (threadMessageObject != null) { avatarContainer.setTitle(LocaleController.formatPluralString("Replies", threadMessageObject.getRepliesCount())); } } if (replyMessageHeaderObject == null) { return; } String text; if (threadMessageObject.getRepliesCount() == 0) { if (isComments) { text = LocaleController.getString(R.string.NoComments); } else { text = LocaleController.getString(R.string.NoReplies); } } else { text = LocaleController.getString(R.string.DiscussionStarted); } replyMessageHeaderObject.messageText = replyMessageHeaderObject.messageOwner.message = text; if (notify) { chatAdapter.updateRowWithMessageObject(replyMessageHeaderObject, true, false); } } private void updateTopicHeader() { if (avatarContainer != null && forumTopic != null) { avatarContainer.setTitle(forumTopic.title); } updateTopicTitleIcon(); } private void createAlertView() { if (alertView != null || getContext() == null) { return; } alertView = new FrameLayout(getContext()); 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)); int index = 9; if (topChatPanelView != null && topChatPanelView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(topChatPanelView) + 1); } if (pinnedMessageView != null && pinnedMessageView.getParent() == contentView) { index = Math.max(index, contentView.indexOfChild(pinnedMessageView) + 1); } contentView.addView(alertView, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.TOP | Gravity.LEFT)); alertNameTextView = new TextView(getContext()); alertNameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); alertNameTextView.setTextColor(getThemedColor(Theme.key_chat_topPanelTitle)); alertNameTextView.setTypeface(AndroidUtilities.bold()); 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(getContext()); 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)); } public void showAlert(String name, String message) { createAlertView(); 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(), 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)) { if (pinnedMessageView != null) { 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() && !isTopic) || pinnedListButton == null) { return; } if (!fragmentOpened) { animated = false; } 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() && !isTopic) { 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 String callLink(MessageObject message) { if ( message != null && message.messageOwner != null && message.messageOwner.media != null && message.messageOwner.media.webpage != null && "telegram_call".equalsIgnoreCase(message.messageOwner.media.webpage.type) ) { return message.messageOwner.media.webpage.display_url; } return null; } private void updatePinnedMessageView(boolean animated, int animateToNext) { if (currentEncryptedChat != null || chatMode != 0) { return; } int pinned_msg_id; boolean changed = false; MessageObject pinnedMessageObject; if (isThreadChat() && threadMessageVisible) { pinnedMessageObject = null; pinned_msg_id = 0; } else if (isThreadChat() && !isTopic) { if (!threadMessageVisible) { pinnedMessageObject = threadMessageObject; pinned_msg_id = (int) 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); String callLink = callLink(pinnedMessageObject); pinnedMessageButtonShown = botButton != null || !TextUtils.isEmpty(callLink); SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if ((threadMessageObject == null || isTopic) && (chatInfo == null && userInfo == null || pinned_msg_id == 0 || !pinnedMessageIds.isEmpty() && pinnedMessageIds.get(0) == preferences.getInt("pin_" + dialog_id, 0)) || isReport() || actionBar != null && (actionBar.isActionModeShowed() || actionBar.isSearchFieldVisible())) { changed = hidePinnedMessageView(animated); } else { if (pinnedMessageView == null) { createPinnedMessageView(); } else { updatePinnedListButton(animated); } if (pinnedMessageView == null) { return; } if (pinnedMessageObject != null) { if (pinnedMessageView != null && 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 || !TextUtils.isEmpty(callLink) ? View.VISIBLE : View.GONE); pinnedMessageButton[animateToNext != 0 ? 0 : 1].setOnClickListener(null); pinnedMessageButton[animateToNext != 0 ? 0 : 1].setOnLongClickListener(null); if (botButton != null) { CharSequence string = new SpannableString(botButton.text); if (botButton instanceof TLRPC.TL_keyboardButtonBuy && pinnedMessageObject != null && MessageObject.getMedia(pinnedMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice) { string = StarsIntroActivity.replaceStars(string); } string = Emoji.replaceEmoji(string, buttonTextView.getPaint().getFontMetricsInt(), false); buttonTextView.setText(string); final MessageObject buttonMessage = pinnedMessageObject; buttonTextView.setOnClickListener(e -> { if (getParentActivity() == null || bottomChannelButtonsLayout.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 || bottomChannelButtonsLayout.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, false); try { buttonTextView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} return true; } return false; }); } else if (!TextUtils.isEmpty(callLink)) { buttonTextView.setText(getString(R.string.VoipChatJoin)); buttonTextView.setOnClickListener(e -> { final Uri uri = Uri.parse(callLink); final String slug = uri.getPathSegments().get(uri.getPathSegments().size() - 1); final TLRPC.TL_inputGroupCallSlug inputGroupCallSlug = new TLRPC.TL_inputGroupCallSlug(); inputGroupCallSlug.slug = slug; VoIPHelper.joinConference(getParentActivity(), currentAccount, inputGroupCallSlug, false, null); }); } else { buttonTextView.setText(null); buttonTextView.setOnClickListener(null); } buttonTextView.measure(View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(dp(28), View.MeasureSpec.EXACTLY)); if (messageTextView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ((ViewGroup.MarginLayoutParams) messageTextView.getLayoutParams()).rightMargin = ( (botButton == null && TextUtils.isEmpty(callLink) ? dp(44) : buttonTextView.getMeasuredWidth() + dp(14 + 8)) + 0 /*(isSideMenued() ? dp(SIDE_MENU_WIDTH) : 0)*/ ); } if (nameTextView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ((ViewGroup.MarginLayoutParams) nameTextView.getLayoutParams()).rightMargin = ( (botButton == null && TextUtils.isEmpty(callLink) ? dp(44) : buttonTextView.getMeasuredWidth() + dp(14 + 8)) + 0 /*(isSideMenued() ? dp(SIDE_MENU_WIDTH) : 0) */ ); } 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; } } 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; pinnedImageHasBlur = false; if (animateToNext == 0) { pinnedMessageImageView[0].setImageBitmap(null); pinnedMessageImageView[0].setVisibility(View.INVISIBLE); } layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = layoutParams4.leftMargin = layoutParams5.leftMargin = dp(18); } else { if (pinnedMessageObject.isRoundVideo()) { pinnedMessageImageView[1].setRoundRadius(AndroidUtilities.dp(16)); } else { pinnedMessageImageView[1].setRoundRadius(AndroidUtilities.dp(2)); } pinnedImageHasBlur = pinnedMessageObject.hasMediaSpoilers(); 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); pinnedMessageImageView[1].setHasBlur(pinnedImageHasBlur); if (animateToNext != 0) { pinnedMessageImageView[1].setAlpha(0.0f); } layoutParams1.leftMargin = layoutParams2.leftMargin = layoutParams3.leftMargin = layoutParams4.leftMargin = layoutParams5.leftMargin = 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 && !isTopic) { 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 ( pinnedMessageObject.messageOwner != null && pinnedMessageObject.messageOwner.media != null && pinnedMessageObject.messageOwner.media.webpage != null && "telegram_call".equalsIgnoreCase(pinnedMessageObject.messageOwner.media.webpage.type) ) { final SpannableStringBuilder sb = new SpannableStringBuilder("x ").append(getString(R.string.PinnedCall)); final ColoredImageSpan span = new ColoredImageSpan(R.drawable.ic_call); span.setSize(dp(16)); sb.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); nameTextView.setText(sb, true); if (currentPinnedMessageIndex[0] != 0) { if (isTopic) { pinnedCounterTextView.setNumber(Math.max(1, currentPinnedMessageIndex[0]), animated && pinnedCounterTextView.getTag() == null); } else { int total = getPinnedMessagesCount(); pinnedCounterTextView.setNumber(Math.min(total - 1, Math.max(1, total - currentPinnedMessageIndex[0])), animated && pinnedCounterTextView.getTag() == null); } showCounter = true; } showCounter = true; } else { if (currentPinnedMessageIndex[0] == 0 || loadedPinnedMessagesCount != 2) { nameTextView.setText(LocaleController.getString(R.string.PinnedMessage), true); } else { nameTextView.setText(LocaleController.getString(R.string.PreviousPinnedMessage), true); } if (currentPinnedMessageIndex[0] != 0) { if (isTopic) { pinnedCounterTextView.setNumber(Math.max(1, currentPinnedMessageIndex[0]), animated && pinnedCounterTextView.getTag() == null); } else { int total = getPinnedMessagesCount(); pinnedCounterTextView.setNumber(Math.min(total - 1, Math.max(1, total - currentPinnedMessageIndex[0])), animated && pinnedCounterTextView.getTag() == null); } showCounter = true; } } } CharSequence pinnedText = null; pinnedMessageObject.updateTranslation(false); if (pinnedMessageObject.type == MessageObject.TYPE_MUSIC) { pinnedText = String.format("%s - %s", pinnedMessageObject.getMusicAuthor(), pinnedMessageObject.getMusicTitle()); } else if (pinnedMessageObject.type == MessageObject.TYPE_POLL) { if (pinnedMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll poll = (TLRPC.TL_messageMediaPoll) pinnedMessageObject.messageOwner.media; String mess = poll.poll.question.text; if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); pinnedText = mess; } else if (pinnedMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaToDo) { TLRPC.TL_messageMediaToDo poll = (TLRPC.TL_messageMediaToDo) pinnedMessageObject.messageOwner.media; String mess = poll.todo.title.text; 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(), 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', ' '); pinnedText = mess; pinnedText = Emoji.replaceEmoji(pinnedText, messageTextView.getPaint().getFontMetricsInt(), false); if (pinnedMessageObject != null && pinnedMessageObject.messageOwner != null) { pinnedText = pinnedMessageObject.replaceAnimatedEmoji(pinnedText, messageTextView.getPaint().getFontMetricsInt()); } } else if (pinnedMessageObject.messageText != null) { String mess = pinnedMessageObject.messageText.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); pinnedText = mess; pinnedText = Emoji.replaceEmoji(pinnedText, messageTextView.getPaint().getFontMetricsInt(), false); if (pinnedMessageObject != null && pinnedMessageObject.messageOwner != null) { pinnedText = pinnedMessageObject.replaceAnimatedEmoji(pinnedText, messageTextView.getPaint().getFontMetricsInt()); } } 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 || !TextUtils.isEmpty(callLink)) { 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; final float tx = 0; // getSideMenuWidth(); if (layoutParams1.leftMargin != prevMargin) { animateImage = null; setPinnedTextTranslationX = true; int diff = prevMargin - layoutParams1.leftMargin; if (!isSideMenuAnimating()) { //animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[0], View.TRANSLATION_X, tx + diff, tx)); //animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[1], View.TRANSLATION_X, tx + diff, tx)); //animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.TRANSLATION_X, tx + diff, tx)); //animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[1], View.TRANSLATION_X, tx + diff, tx)); } //animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_X, tx + pinnedCounterTextViewX + diff, tx + 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(tx); pinnedMessageTextView[0].setTranslationX(tx); nameTextView.setTranslationX(tx); pinnedNameTextView[0].setTranslationX(tx); buttonTextView.setTranslationX(tx); pinnedMessageButton[0].setTranslationX(tx); pinnedCounterTextView.setTranslationX(tx + 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); } final float tx2 = 0; // getSideMenuWidth(); pinnedCounterTextView.setTranslationY(0.0f); pinnedMessageTextView[0].setTranslationX(tx2); pinnedMessageTextView[1].setTranslationX(tx2); pinnedCounterTextView.setTranslationX(tx2 + 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(tx2); pinnedNameTextView[1].setTranslationX(tx2); 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 (pinnedCounterTextView != null) { 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(getSideMenuWidth() + pinnedCounterTextViewX); pinnedCounterTextView.setAlpha(shouldAnimateName || currentPinnedMessageIndex[0] == 0 ? 0.0f : 1.0f); } messageTextView.setVisibility(View.VISIBLE); messageTextView.setAlpha(1.0f); // messageTextView.setTranslationX(getSideMenuWidth()); messageTextView.setTranslationY(0); nameTextView.setVisibility(View.VISIBLE); nameTextView.setAlpha(1.0f); // nameTextView.setTranslationX(getSideMenuWidth()); nameTextView.setTranslationY(0); pinnedMessageTextView[1].setVisibility(View.INVISIBLE); //pinnedMessageTextView[1].setTranslationX(getSideMenuWidth()); 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(getSideMenuWidth()); pinnedNameTextView[1].setTranslationY(0); pinnedMessageImageView[0].setVisibility(View.INVISIBLE); BackupImageView backupImageView = pinnedMessageImageView[1]; pinnedMessageImageView[1] = pinnedMessageImageView[0]; pinnedMessageImageView[0] = backupImageView; if (pinnedMessageImageView[0] != null) { pinnedMessageImageView[0].setAlpha(1.0f); pinnedMessageImageView[0].setScaleX(1f); pinnedMessageImageView[0].setScaleY(1f); pinnedMessageImageView[0].setTranslationY(0); } if (pinnedMessageImageView[1] != null) { pinnedMessageImageView[1].setAlpha(1.0f); pinnedMessageImageView[1].setScaleX(1f); pinnedMessageImageView[1].setScaleY(1f); pinnedMessageImageView[1].setTranslationY(0); } } if (isThreadChat() && !isTopic) { pinnedLineView.set(0, 1, false); } else { int position = Collections.binarySearch(pinnedMessageIds, currentPinnedMessageId, Comparator.reverseOrder()); pinnedLineView.set(pinnedMessageIds.size() - 1 - position, pinnedMessageIds.size(), animated); } } else { if (pinnedCounterTextView != null) { 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() + dp(4); if (pinnedCounterTextView != null) { pinnedCounterTextView.setTranslationX(/*getSideMenuWidth() +*/ pinnedCounterTextViewX); } } return result; } } private boolean shownRestartTopic, shownTranslateTopic; private boolean shownBotVerification; public static final boolean DEBUG_TOP_PANELS = false; public void updateTopPanel(boolean animated) { if (chatMode != 0 && chatMode != MODE_SUGGESTIONS) { 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 || DEBUG_TOP_PANELS; } boolean showShare = preferences.getBoolean("dialog_bar_share" + did, false) || DEBUG_TOP_PANELS; boolean showReport = preferences.getBoolean("dialog_bar_report" + did, false) || DEBUG_TOP_PANELS; boolean showBlock = preferences.getBoolean("dialog_bar_block" + did, false) || DEBUG_TOP_PANELS; boolean showAdd = preferences.getBoolean("dialog_bar_add" + did, false) || DEBUG_TOP_PANELS; boolean showArchive = preferences.getBoolean("dialog_bar_archived" + dialog_id, false) || DEBUG_TOP_PANELS; 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); TLRPC.EmojiStatus showEmojiStatusReport = currentUser != null && (showReport || showBlock) ? DialogObject.filterEmojiStatus(currentUser.emoji_status) : null; TL_bots.botVerification showBotVerificationReport = (show && (showReport || showBlock) || shownBotVerification || preferences.getBoolean("dialog_bar_botver" + did, true)) ? (userInfo != null && !UserObject.isUserSelf(currentUser) && userInfo.bot_verification != null ? userInfo.bot_verification : chatInfo != null && chatInfo.bot_verification != null ? chatInfo.bot_verification : null) : null; long showCost = 0; if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(-dialog_id, getThreadId()); // if (topic != null && !topic.nopaid_messages_exception) { // showCost = currentChat.send_paid_messages_stars; // } if (headerItem != null) { headerItem.setSubItemShown(remove_fee, getThreadId() != 0 && topic != null && !topic.nopaid_messages_exception && currentChat.send_paid_messages_stars > 0); headerItem.setSubItemShown(charge_fee, getThreadId() != 0 && topic != null && topic.nopaid_messages_exception && currentChat.send_paid_messages_stars > 0); } if (feeItemGap != null) { feeItemGap.setVisibility(getThreadId() != 0 && currentChat.send_paid_messages_stars > 0 ? View.VISIBLE : View.GONE); } if (feeItemText != null) { if (topic != null && !topic.nopaid_messages_exception && currentChat.send_paid_messages_stars > 0) { feeItemText.setText(AndroidUtilities.replaceTags(StarsIntroActivity.replaceStarsWithPlain(LocaleController.formatString(R.string.DirectFee, (int) currentChat.send_paid_messages_stars, DialogObject.getShortName(getThreadId())), 0.6f))); } else { feeItemText.setText(LocaleController.formatString(R.string.DirectFeeNone, DialogObject.getShortName(getThreadId()))); } feeItemText.setVisibility(getThreadId() != 0 && currentChat.send_paid_messages_stars > 0 ? View.VISIBLE : View.GONE); } } else { showCost = preferences.getLong("dialog_bar_paying_" + did, 0L); if (showCost <= 0 && userInfo != null && userInfo.settings != null && userInfo.settings.charge_paid_message_stars > 0) { showCost = userInfo.settings.charge_paid_message_stars; } } if (showCost > 0) { if (!show) { showReport = showGeo = showShare = showBlock = showAdd = showArchive = showAddMembersToGroup = false; } show = true; } else if (showBotVerificationReport != null) { if (!shownBotVerification) { preferences.edit().putBoolean("dialog_bar_botver" + did, false).apply(); } shownBotVerification = true; if (!show) { showReport = showGeo = showShare = showBlock = showAdd = showArchive = showAddMembersToGroup = false; } show = true; } if (UserObject.isBotForum(currentUser)) { show = showReport = showGeo = showShare = showBlock = showAdd = showArchive = showAddMembersToGroup = false; } boolean showRestartTopic = !isInPreviewMode() && forumTopic != null && forumTopic.closed && !forumTopic.hidden && ChatObject.canManageTopic(currentAccount, currentChat, forumTopic); boolean showTranslate = ( getUserConfig().isPremium() || currentChat != null && currentChat.autotranslation ? getMessagesController().getTranslateController().isDialogTranslatable(getDialogId()) && !getMessagesController().getTranslateController().isTranslateDialogHidden(getDialogId()) : !getMessagesController().premiumFeaturesBlocked() && preferences.getInt("dialog_show_translate_count" + did, 5) <= 0 ) || DEBUG_TOP_PANELS; boolean showBizBot = currentEncryptedChat == null && getUserConfig().isPremium() && preferences.getLong("dialog_botid" + did, 0) != 0 || DEBUG_TOP_PANELS; boolean showBotAd = currentUser != null && currentUser.bot && messages.size() >= 2 && botSponsoredMessage != null; if (showRestartTopic) { shownRestartTopic = true; } if (showTranslate || showBizBot || showEmojiStatusReport != null) { shownTranslateTopic = true; } boolean showRestartTopic1 = (showRestartTopic || shownRestartTopic) && !(showReport || showBlock || showGeo); if (show || showReport || showBlock || showGeo || showTranslate || showBizBot || showRestartTopic1) { createTopPanel(); if (topChatPanelView == null) { return; } } boolean show2 = showBotAd; if (showBizBot) { createBizBotButton(); if (bizBotButton != null) { bizBotButton.set( did, preferences.getLong("dialog_botid" + did, 0), preferences.getString("dialog_boturl" + did, null), preferences.getInt("dialog_botflags" + did, 0) ); } } if (showTranslate) { createTranslateButton(); if (translateButton != null) { translateButton.updateText(); } } if (showBotAd) { createBotAdView(); if (botAdView != null) { markSponsoredAsRead(botSponsoredMessage); botAdView.set(this, botSponsoredMessage, () -> { if (botSponsoredMessage == null) return; RevenueSharingAdsInfoBottomSheet[] sheet = new RevenueSharingAdsInfoBottomSheet[1]; sheet[0] = RevenueSharingAdsInfoBottomSheet.showAlert(getContext(), ChatActivity.this, true, resourceProvider, o -> { if (botSponsoredMessage == null) return; if (botSponsoredMessage.sponsoredInfo != null || botSponsoredMessage.sponsoredAdditionalInfo != null || botSponsoredMessage.sponsoredUrl != null && !botSponsoredMessage.sponsoredUrl.startsWith("https://" + MessagesController.getInstance(currentAccount).linkPrefix)) { ItemOptions info = o.makeSwipeback(); ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getContext(), true, false, resourceProvider); backCell.setItemHeight(44); backCell.setTextAndIcon(getString(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 -> o.closeSwipeback()); info.addView(backCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); info.addView(new ActionBarPopupWindow.GapView(getContext(), resourceProvider), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); ArrayList sections = new ArrayList<>(); if (botSponsoredMessage.sponsoredUrl != null && !TextUtils.equals(AndroidUtilities.getHostAuthority(botSponsoredMessage.sponsoredUrl), MessagesController.getInstance(currentAccount).linkPrefix)) { TextView textView = new TextView(getContext()); textView.setTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourceProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); Uri uri = Uri.parse(botSponsoredMessage.sponsoredUrl); textView.setText(Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null)); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, botSponsoredMessage.sponsoredAdditionalInfo == null ? 6 : 0)); textView.setOnClickListener(e -> { if (botSponsoredMessage == null) return; o.dismiss(); logSponsoredClicked(botSponsoredMessage, false, true); Browser.openUrl(getContext(), Uri.parse(botSponsoredMessage.sponsoredUrl), true, false, false, null, null, false, MessagesController.getInstance(currentAccount).sponsoredLinksInappAllow, false); }); textView.setOnLongClickListener(e -> { if (botSponsoredMessage == null) return false; if (AndroidUtilities.addToClipboard(botSponsoredMessage.sponsoredUrl)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourceProvider).createCopyLinkBulletin().show(); } return true; }); sections.add(textView); } if (botSponsoredMessage.sponsoredInfo != null) { TextView textView = new TextView(getContext()); textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourceProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); textView.setText(botSponsoredMessage.sponsoredInfo); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, botSponsoredMessage.sponsoredAdditionalInfo == null ? 6 : 0)); textView.setOnClickListener(e -> { if (AndroidUtilities.addToClipboard(botSponsoredMessage.sponsoredInfo)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourceProvider).createCopyBulletin(LocaleController.getString(R.string.TextCopied)).show(); } }); sections.add(textView); } if (botSponsoredMessage.sponsoredAdditionalInfo != null) { TextView textView = new TextView(getContext()); textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourceProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); textView.setText(botSponsoredMessage.sponsoredAdditionalInfo); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, 6)); textView.setOnClickListener(e -> { if (AndroidUtilities.addToClipboard(botSponsoredMessage.sponsoredAdditionalInfo)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourceProvider).createCopyBulletin(LocaleController.getString(R.string.TextCopied)).show(); } }); sections.add(textView); } for (int i = 0; i < sections.size(); ++i) { View section = sections.get(i); if (i > 0) { FrameLayout separator = new FrameLayout(getContext()); separator.setBackgroundColor(Theme.getColor(Theme.key_divider, resourceProvider)); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 1); params.height = 1; info.addView(separator, params); } info.addView(section, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } o.add(R.drawable.msg_channel, getString(R.string.SponsoredMessageSponsorReportable), () -> o.openSwipeback(info)); o.addGap(); } o.add(R.drawable.msg_block2, getString(R.string.ReportAd), () -> { o.dismiss(); if (sheet[0] != null) sheet[0].dismiss(); ReportBottomSheet.openSponsored(ChatActivity.this, botSponsoredMessage, themeDelegate); }); o.add(R.drawable.msg_cancel, getString(R.string.HideAd), () -> { o.dismiss(); if (sheet[0] != null) sheet[0].dismiss(); if (getUserConfig().isPremium()) { botSponsoredMessage = null; updateTopPanel(true); BulletinFactory.of(this) .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) .show(); getMessagesController().disableAds(true); } else { showDialog(new PremiumFeatureBottomSheet(this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); } }); o.setGravity(Gravity.RIGHT).show(); }); }, () -> { if (getUserConfig().isPremium()) { botSponsoredMessage = null; updateTopPanel(true); BulletinFactory.of(this) .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) .show(); getMessagesController().disableAds(true); } else { showDialog(new PremiumFeatureBottomSheet(this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); } }); } } if ((shownTranslateTopic || shownRestartTopic) && !show) { showReport = showGeo = showShare = showBlock = showAdd = showArchive = showAddMembersToGroup = false; showEmojiStatusReport = null; showBotVerificationReport = null; show = true; } if (reportSpamButton != null) { reportSpamButton.setVisibility(showReport || showBlock || showGeo ? View.VISIBLE : View.GONE); } if (restartTopicButton != null) { restartTopicButton.setVisibility(showRestartTopic1 ? View.VISIBLE : View.GONE); } if (translateButton != null) { translateButton.setVisibility(showTranslate ? View.VISIBLE : View.GONE); } if (botAdView != null) { botAdView.setVisibility(showBotAd ? View.VISIBLE : View.GONE); } if (bizBotButton != null) { bizBotButton.setVisibility(showBizBot ? View.VISIBLE : View.GONE); } if (closeReportSpam != null) { closeReportSpam.setVisibility(showRestartTopic1 || (showTranslate || showBizBot) && !(showReport || showBlock || showGeo) ? View.GONE : View.VISIBLE); } if (!showRestartTopic) { shownRestartTopic = false; } if (!showTranslate && !showBizBot) { shownTranslateTopic = false; } addToContactsButtonArchive = false; TLRPC.User user = currentUser != null ? getMessagesController().getUser(currentUser.id) : null; boolean isChatWithAdmin = false; if (user != null && !TextUtils.isEmpty(chatWithAdmin)) { createTopPanel(); if (topChatPanelView == null) { return; } isChatWithAdmin = true; if (chatWithAdminTextView == null) { chatWithAdminTextView = new TextView(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, 48, 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) { createTopPanel(); if (topChatPanelView == null) { return; } addToContactsButton.setVisibility(View.VISIBLE); addToContactsButton.setText(LocaleController.getString(R.string.GroupAddMembers)); addToContactsButton.setTag(4); addToContactsButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); 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)) { if (addToContactsButton != null) { addToContactsButton.setVisibility(View.GONE); } } else if (!user.contact && !user.self && showAdd) { createTopPanel(); if (topChatPanelView == null) { return; } addContactItem.setVisibility(View.VISIBLE); addContactItem.setText(LocaleController.getString(R.string.AddToContacts)); addToContactsButton.setVisibility(View.VISIBLE); if (showArchive) { addToContactsButtonArchive = true; addToContactsButton.setText(LocaleController.getString(R.string.Unarchive).toUpperCase()); addToContactsButton.setTag(3); } else { if (reportSpamButton.getVisibility() == View.VISIBLE) { addToContactsButton.setText(LocaleController.getString(R.string.AddContactChat)); } else { // todo float baseWidth = addToContactsButton.getPaint().measureText(LocaleController.formatString(R.string.AddContactFullChat, "")); addToContactsButton.setText(LocaleController.formatString(R.string.AddContactFullChat, TextUtils.ellipsize(UserObject.getFirstName(user), addToContactsButton.getPaint(), AndroidUtilities.displaySize.x - baseWidth - AndroidUtilities.dp(64 * 2), TextUtils.TruncateAt.MIDDLE)).toUpperCase()); } } addToContactsButton.setTag(null); addToContactsButton.setVisibility(View.VISIBLE); } else if (showShare && !user.self) { createTopPanel(); if (topChatPanelView == null) { return; } addContactItem.setVisibility(View.VISIBLE); addToContactsButton.setVisibility(View.VISIBLE); addContactItem.setText(LocaleController.getString(R.string.ShareMyContactInfo)); addToContactsButton.setText(LocaleController.getString(R.string.ShareMyPhone).toUpperCase()); addToContactsButton.setTag(1); addToContactsButton.setVisibility(View.VISIBLE); } else { if (!user.contact && !UserObject.isService(user.id) && !user.self && !show && addContactItem != null) { createTopPanel(); if (topChatPanelView == null) { return; } addContactItem.setVisibility(View.VISIBLE); addContactItem.setText(LocaleController.getString(R.string.ShareMyContactInfo)); addToContactsButton.setTag(2); } else if (addContactItem != null) { addContactItem.setVisibility(View.GONE); } if (addToContactsButton != null) { addToContactsButton.setVisibility(View.GONE); } } if (reportSpamButton != null) { reportSpamButton.setText(LocaleController.getString(R.string.ReportSpamUser)); } } else { if (showGeo) { createTopPanel(); if (topChatPanelView == null) { return; } reportSpamButton.setText(LocaleController.getString(R.string.ReportSpamLocation)); reportSpamButton.setTag(R.id.object_tag, 1); reportSpamButton.setTextColor(getThemedColor(Theme.key_chat_addContact)); Theme.setSelectorDrawableColor(reportSpamButton.getBackground(), getThemedColor(Theme.key_chat_addContact) & 0x19ffffff, true); reportSpamButton.setTag(Theme.key_chat_addContact); } else { if (showArchive) { createTopPanel(); if (topChatPanelView == null) { return; } addToContactsButtonArchive = true; addToContactsButton.setText(LocaleController.getString(R.string.Unarchive).toUpperCase()); addToContactsButton.setTag(3); addToContactsButton.setVisibility(View.VISIBLE); reportSpamButton.setText(LocaleController.getString(R.string.ReportSpam)); } else { if (addToContactsButton != null) { addToContactsButton.setVisibility(View.GONE); } if (reportSpamButton != null) { reportSpamButton.setText(LocaleController.getString(R.string.ReportSpamAndLeave)); } } if (reportSpamButton != null) { reportSpamButton.setTag(R.id.object_tag, null); reportSpamButton.setTextColor(getThemedColor(Theme.key_text_RedBold)); Theme.setSelectorDrawableColor(reportSpamButton.getBackground(), getThemedColor(Theme.key_text_RedBold) & 0x19ffffff, true); reportSpamButton.setTag(Theme.key_text_RedBold); } } if (addContactItem != null) { addContactItem.setVisibility(View.GONE); } } if (chatWithAdminTextView != null) { chatWithAdminTextView.setVisibility(isChatWithAdmin ? View.VISIBLE : View.GONE); } if (userBlocked || (showBotVerificationReport == null && showCost <= 0 && (addToContactsButton == null || addToContactsButton.getVisibility() == View.GONE) && (reportSpamButton == null || reportSpamButton.getVisibility() == View.GONE) && (chatWithAdminTextView == null || chatWithAdminTextView.getVisibility() == View.GONE) && (restartTopicButton == null || restartTopicButton.getVisibility() == View.GONE) && (translateButton == null || translateButton.getVisibility() == View.GONE) && (bizBotButton == null || bizBotButton.getVisibility() == View.GONE))) { show = false; } int topChatPanelHeight = AndroidUtilities.dp(50); if (showCost > 0 || showEmojiStatusReport != null && show) { createTopPanel(); if (topChatPanelView == null) { return; } emojiStatusSpamHint.resetEmojiColor(); topViewSeparator2.setVisibility(View.VISIBLE); if ((restartTopicButton == null || restartTopicButton.getVisibility() != View.VISIBLE) && (reportSpamButton == null || reportSpamButton.getVisibility() != View.VISIBLE) && (addToContactsButton == null || addToContactsButton.getVisibility() != View.VISIBLE) && (user == null || TextUtils.isEmpty(chatWithAdmin)) ) { topChatPanelHeight -= AndroidUtilities.dp(48); topViewSeparator2.setVisibility(View.GONE); closeReportSpam.setVisibility(View.GONE); } emojiStatusSpamHint.setVisibility(View.VISIBLE); emojiStatusSpamHint.setTextColor(getThemedColor(Theme.key_chat_topPanelMessage)); emojiStatusSpamHint.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13.3f); topViewSeparator1.setVisibility(View.VISIBLE); SpannableStringBuilder totalText = new SpannableStringBuilder(); if (showEmojiStatusReport != null && show) { final TLRPC.EmojiStatus status = showEmojiStatusReport; final Runnable openStatus = () -> { PremiumPreviewBottomSheet sheet = new PremiumPreviewBottomSheet(this, currentAccount, user, getResourceProvider()); long document_id; if (status instanceof TLRPC.TL_emojiStatus) { TLRPC.TL_emojiStatus s = (TLRPC.TL_emojiStatus) status; document_id = s.document_id; } else if (status instanceof TLRPC.TL_emojiStatusCollectible) { TLRPC.TL_emojiStatusCollectible s = (TLRPC.TL_emojiStatusCollectible) status; document_id = s.document_id; sheet.emojiStatusCollectible = s; } else return; BackupImageView icon = new BackupImageView(getContext()); AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable drawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(icon, dp(160), AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_LARGE); icon.setImageDrawable(drawable); icon.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(@NonNull View v) { drawable.attach(); } @Override public void onViewDetachedFromWindow(@NonNull View v) { drawable.detach(); } }); drawable.set(document_id, false); sheet.isEmojiStatus = true; sheet.overrideTitleIcon = icon; showDialog(sheet); }; SpannableStringBuilder text = new SpannableStringBuilder(AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.ReportSpamUserEmojiStatusHint2), openStatus)); SpannableString emoji = new SpannableString("x"); Long docid = null; if (DialogObject.getEmojiStatusDocumentId(currentUser.emoji_status) != 0) { docid = DialogObject.getEmojiStatusDocumentId(currentUser.emoji_status); } if (docid != null) { AnimatedEmojiSpan span = new AnimatedEmojiSpan(docid, emojiStatusSpamHint.getPaint().getFontMetricsInt()); span.full = false; emoji.setSpan(span, 0, emoji.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } SpannableString link = new SpannableString(LocaleController.getString(R.string.TelegramPremium)); link.setSpan(new ClickableSpan() { @Override public void onClick(@NonNull View view) { openStatus.run(); } @Override public void updateDrawState(@NonNull TextPaint ds) { super.updateDrawState(ds); ds.setUnderlineText(false); } }, 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); int i = text.toString().indexOf("%1$s"); if (i >= 0) { text.replace(i, i + 4, emoji); } i = text.toString().indexOf("%2$s"); if (i >= 0) { text.replace(i, i + 4, link); } totalText.append(AndroidUtilities.replaceArrows(text, true, dp(8f / 3f), dp(1.66f), 1.0f)); } if (showCost > 0) { long _user_id = dialog_id; long _parent_id = 0; if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { _user_id = getThreadId(); _parent_id = dialog_id; } final long user_id = _user_id; final long parent_id = _parent_id; if (totalText.length() > 0) { totalText.append("\n\n"); } final ColoredImageSpan[] span = new ColoredImageSpan[1]; totalText.append(StarsIntroActivity.replaceStars(AndroidUtilities.replaceSingleTag(formatString(R.string.MessageLockedStarsRemoveFee, DialogObject.getShortName(user_id), LocaleController.formatNumber(showCost, ',')), () -> { StarsController.getInstance(currentAccount).getPaidRevenue(user_id, parent_id, revenue -> { if (getContext() == null) return; AlertsCreator.showAlertWithCheckbox( getContext(), getString(R.string.RemoveMessageFeeTitle), AndroidUtilities.replaceTags(formatString(ChatObject.isMonoForum(currentChat) ? R.string.RemoveMessageFeeMessageChannel : R.string.RemoveMessageFeeMessage, DialogObject.getShortName(user_id))), revenue > 0 ? formatPluralStringComma("RemoveMessageFeeRefund", (int) (long) revenue) : null, getString(R.string.Confirm), refund -> StarsController.getInstance(currentAccount).stopPaidMessages(user_id, parent_id, revenue > 0 && refund, true), resourceProvider ); }); }), .9f, span)); span[0].setTranslateY(-dp(1)); span[0].setTranslateX(+dp(1)); } ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) emojiStatusSpamHint.getLayoutParams(); lp.leftMargin = dp(25 + (isSideMenued() ? 32 : 0)); lp.rightMargin = dp(25 + (isSideMenued() ? 32 : 0)); emojiStatusSpamHint.setTranslationX(getSideMenuWidth() / 2.0f); emojiStatusSpamHint.setText(totalText); emojiStatusSpamHint.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - dp(50 + (isSideMenued() ? SIDE_MENU_WIDTH : 0)), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(99999, View.MeasureSpec.AT_MOST)); topChatPanelHeight += AndroidUtilities.dp(4); emojiStatusSpamHint.setTranslationY(topChatPanelHeight); topChatPanelHeight += AndroidUtilities.dp(10) + emojiStatusSpamHint.getMeasuredHeight(); } else if (showBotVerificationReport != null) { createTopPanel(); if (topChatPanelView == null) { return; } topViewSeparator2.setVisibility(View.VISIBLE); if ((restartTopicButton == null || restartTopicButton.getVisibility() != View.VISIBLE) && (reportSpamButton == null || reportSpamButton.getVisibility() != View.VISIBLE) && (addToContactsButton == null || addToContactsButton.getVisibility() != View.VISIBLE) && (user == null || TextUtils.isEmpty(chatWithAdmin)) ) { topChatPanelHeight -= AndroidUtilities.dp(48); topViewSeparator2.setVisibility(View.GONE); closeReportSpam.setVisibility(View.GONE); } emojiStatusSpamHint.setVisibility(View.VISIBLE); emojiStatusSpamHint.setTextColor(getThemedColor(Theme.key_chat_topPanelMessage)); emojiStatusSpamHint.setEmojiColor(getThemedColor(Theme.key_chat_topPanelMessage)); emojiStatusSpamHint.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13.3f); topViewSeparator1.setVisibility(View.VISIBLE); SpannableStringBuilder text = new SpannableStringBuilder("x"); text.setSpan(new AnimatedEmojiSpan(showBotVerificationReport.icon, emojiStatusSpamHint.getPaint().getFontMetricsInt()), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); text.append(" "); text.append(showBotVerificationReport.description); ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) emojiStatusSpamHint.getLayoutParams(); lp.leftMargin = dp(25 + (isSideMenued() ? 32 : 0)); lp.rightMargin = dp(25 + (isSideMenued() ? 32 : 0)); emojiStatusSpamHint.setTranslationX(getSideMenuWidth() / 2.0f); emojiStatusSpamHint.setText(text); emojiStatusSpamHint.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - dp(50 + (isSideMenued() ? SIDE_MENU_WIDTH : 0)), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(99999, View.MeasureSpec.AT_MOST)); topChatPanelHeight += AndroidUtilities.dp(4); emojiStatusSpamHint.setTranslationY(topChatPanelHeight); topChatPanelHeight += AndroidUtilities.dp(10) + emojiStatusSpamHint.getMeasuredHeight(); } else { if (emojiStatusSpamHint != null) { emojiStatusSpamHint.setVisibility(View.GONE); } if (topViewSeparator1 != null) { topViewSeparator1.setVisibility(View.GONE); } if (topViewSeparator2 != null) { topViewSeparator2.setVisibility(View.GONE); } } if (showTranslate || showBizBot) { createTopPanel(); if (topChatPanelView == null) { return; } if (restartTopicButton.getVisibility() == View.VISIBLE || reportSpamButton.getVisibility() == View.VISIBLE || addToContactsButton.getVisibility() == View.VISIBLE || user != null && !TextUtils.isEmpty(chatWithAdmin) ) { topViewSeparator3.setVisibility(View.VISIBLE); topViewSeparator3.setTranslationY(showTranslate ? 0 : -dp(48 - 36)); } else { if (showBotVerificationReport == null && showCost <= 0) { topChatPanelHeight -= AndroidUtilities.dp(48); } topViewSeparator3.setVisibility(View.GONE); } if (showTranslate) { topChatPanelHeight += AndroidUtilities.dp(36); } if (showBizBot) { topChatPanelHeight += AndroidUtilities.dp(48); } if (bizBotButton != null) { bizBotButton.setTranslationY(AndroidUtilities.dp(showBizBot && showTranslate ? -36 : 0)); } } else if (topViewSeparator3 != null) { topViewSeparator3.setVisibility(View.GONE); } if (topViewSeparator1 != null) { topViewSeparator1.setVisibility((topViewSeparator3 != null && topViewSeparator3.getVisibility() == View.VISIBLE || topViewSeparator2 != null && topViewSeparator2.getVisibility() == View.VISIBLE) ? View.VISIBLE : View.GONE); } if (topChatPanelView != null) { topChatPanelView.getLayoutParams().height = topChatPanelHeight; } int topChatPanel2Height = 0; if (show2) { topChatPanel2Height += dp(2); if (showBotAd) { topChatPanel2Height += botAdView.height(); } } if (topChatPanelView2 != null) { topChatPanelView2.getLayoutParams().height = topChatPanel2Height; } if (show) { createTopPanel(); if (topChatPanelView == null) { return; } 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 != null) { 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, -topChatPanelHeight); 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; } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } @Override public void onAnimationCancel(Animator animation) { if (reportSpamViewAnimator != null && reportSpamViewAnimator.equals(animation)) { reportSpamViewAnimator = null; } } }); reportSpamViewAnimator.start(); } else { topChatPanelViewOffset = -topChatPanelHeight; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } } } if (show2) { createTopPanel2(); if (topChatPanelView2 == null) { return; } if (topChatPanelView2.getTag() != null) { topChatPanelView2.setTag(null); topChatPanelView2.setVisibility(View.VISIBLE); if (topChatPanelView2Animator != null) { topChatPanelView2Animator.cancel(); topChatPanelView2Animator = null; } if (animated) { topChatPanelView2Animator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(topChatPanelView2Offset, 0); animator.addUpdateListener(animation -> { topChatPanelView2Offset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); }); topChatPanelView2Animator.playTogether(animator); topChatPanelView2Animator.setDuration(200); topChatPanelView2Animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (topChatPanelView2Animator != null && topChatPanelView2Animator.equals(animation)) { topChatPanelView2Animator = null; } } @Override public void onAnimationCancel(Animator animation) { if (topChatPanelView2Animator != null && topChatPanelView2Animator.equals(animation)) { topChatPanelView2Animator = null; } } }); topChatPanelView2Animator.start(); } else { topChatPanelView2Offset = 0; invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } } } else if (topChatPanelView2 != null) { if (topChatPanelView2.getTag() == null) { topChatPanelView.setTag(1); if (topChatPanelView2Animator != null) { topChatPanelView2Animator.cancel(); topChatPanelView2Animator = null; } if (animated) { topChatPanelView2Animator = new AnimatorSet(); ValueAnimator animator = ValueAnimator.ofFloat(topChatPanelView2Offset, -topChatPanel2Height); animator.addUpdateListener(animation -> { topChatPanelView2Offset = (float) animation.getAnimatedValue(); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); }); topChatPanelView2Animator.playTogether(animator); topChatPanelView2Animator.setDuration(200); topChatPanelView2Animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (topChatPanelView2Animator != null && topChatPanelView2Animator.equals(animation)) { topChatPanelView2.setVisibility(View.GONE); topChatPanelView2Animator = null; } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } @Override public void onAnimationCancel(Animator animation) { if (topChatPanelView2Animator != null && topChatPanelView2Animator.equals(animation)) { topChatPanelView2Animator = null; } } }); topChatPanelView2Animator.start(); } else { topChatPanelView2Offset = -topChatPanel2Height; 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.canSendVoice(currentChat)) { MediaController.getInstance().setAllowStartRecord(false); } else if (!ApplicationLoader.mainInterfacePaused && (bottomChannelButtonsLayout == null || bottomChannelButtonsLayout.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 public 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.setTitleExpand(showAudioCallAsIcon); 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 (suggestEmojiPanel != null) { suggestEmojiPanel.setVisibility(allowStickersPanel && !value && (chatActivityEnterView == null || !chatActivityEnterView.isStickersExpanded()) ? View.VISIBLE : View.GONE); } if (mentionContainer != null) { mentionContainer.animate().alpha(chatActivityEnterView.isStickersExpanded() || isInPreviewMode() ? 0 : 1f).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); } 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 { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); } 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 && !isInsideContainer); } if (fragmentLocationContextView != null) { fragmentLocationContextView.setEnabled(!value && !isInsideContainer); } if (pinnedMessageView != null) { pinnedMessageView.setEnabled(!isInPreviewMode()); } if (contentView != null) { contentView.setOccupyStatusBar(!inBubbleMode && !isInsideContainer && !inPreviewMode); } } 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; } return Math.round(windowInsetsStateHolder.getAnimatedMaxBottomInset() + (chatInputViewsContainer.getInputBubbleHeight() + dp(9 + 7))); } @Override public int getTopOffset(int tag) { return Math.max(AndroidUtilities.statusBarHeight + ActionBar.getCurrentActionBarHeight(), actionBar != null ? actionBar.getMeasuredHeight() + actionBar.getTop() : 0) + (int) Math.max(0, paddingTopHeight); } @Override public boolean allowLayoutChanges() { return false; } }); 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); pinnedMessageImageView[0].setHasBlur(pinnedImageHasBlur); } if (chatMode == 0) { getNotificationsController().setOpenedDialogId(dialog_id, getTopicId()); } 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); applyChatLinkMessageMaybe(); if (bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() != View.VISIBLE && !actionBar.isSearchFieldVisible() && chatMode != MODE_SEARCH && !BaseFragment.hasSheets(this)) { 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(false); showGigagroupConvertAlert(); if (pullingDownOffset != 0) { pullingDownOffset = 0; chatListView.invalidate(); } flagSecure.attach(); if (starReactionsOverlay != null) { starReactionsOverlay.bringToFront(); } } public float getPullingDownOffset() { return pullingDownOffset; } public void checkAdjustResize() { if (isInsideContainer) return; if (isReport()) { AndroidUtilities.requestAdjustNothing(getParentActivity(), classGuid); } else { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } } @Override public void finishFragment() { super.finishFragment(); if (scrimPopupWindow != null) { scrimPopupWindow.setPauseNotifications(false); closeMenu(); } } public void saveDraft() { CharSequence draftMessage = null; MessageObject replyMessage = null; boolean searchWebpage = true; if (!ignoreAttachOnPause && chatActivityEnterView != null && bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() != View.VISIBLE) { replyMessage = replyingMessageObject; draftMessage = AndroidUtilities.getTrimmedString(chatActivityEnterView.getDraftMessage()); searchWebpage = chatActivityEnterView.isMessageWebPageSearchEnabled(); } CharSequence[] message = new CharSequence[]{ignoreDraft ? null : draftMessage}; ArrayList entities = getMediaDataController().getEntities(message, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101); long draftThreadId; if (chatMode == MODE_SAVED) { draftThreadId = 0; } else if (ChatObject.isForum(currentChat) && !isTopic && replyMessage != null) { if (replyMessage.replyToForumTopic != null) { draftThreadId = replyMessage.replyToForumTopic.id; } else { draftThreadId = MessageObject.getTopicId(currentAccount, replyMessage.messageOwner, ChatObject.isForum(currentChat)); } } else { draftThreadId = threadMessageId; } getMediaDataController().saveDraft(dialog_id, draftThreadId, message[0], entities, (replyMessage != null && !replyMessage.isTopicMainMessage && replyMessage.replyToForumTopic == null && !ignoreDraft) ? replyMessage.messageOwner : null, replyingQuote, messageSuggestionParams != null ? messageSuggestionParams.toTl() : null, chatActivityEnterView != null ? chatActivityEnterView.getEffectId() : 0, !searchWebpage, false); } @Override public void onPause() { super.onPause(); scrolling = false; if (scrimPopupWindow != null) { scrimPopupWindow.setPauseNotifications(false); closeMenu(); } long replyId = threadMessageId; getMessagesController().markDialogAsReadNow(dialog_id, replyId); MediaController.getInstance().stopRaiseToEarSensors(this, true, true); paused = true; wasPaused = true; if (chatMode == 0) { getNotificationsController().setOpenedDialogId(0, 0); } Bulletin.removeDelegate(this); getMessagesController().setLastVisibleDialogId(dialog_id, chatMode == MODE_SCHEDULED, false); if (!ignoreAttachOnPause && chatActivityEnterView != null && bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() != View.VISIBLE) { chatActivityEnterView.onPause(); chatActivityEnterView.setFieldFocused(false); } if (chatAttachAlert != null) { if (!ignoreAttachOnPause) { chatAttachAlert.onPause(); } else { ignoreAttachOnPause = false; } } if (contentView != null) { contentView.onPause(); } if (chatMode == 0 || chatMode == MODE_SAVED && getUserConfig().getClientUserId() == getSavedDialogId() || chatMode == MODE_SUGGESTIONS && ChatObject.isMonoForum(currentChat)) { saveDraft(); getMessagesController().cancelTyping(0, dialog_id, threadMessageId); } if (chatMode == 0 || chatMode == MODE_SAVED) { if (!pausedOnLastMessage && !firstLoading && (!isThreadChat() || isTopic)) { 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; MessageObject messageObject = null; if (holder.itemView instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) holder.itemView).getMessageObject(); } else if (holder.itemView instanceof ChatActionCell) { messageObject = ((ChatActionCell) holder.itemView).getMessageObject(); } if (messageObject != null) { mid = messageObject.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 messageObject2 = messages.get(num); if (messageObject2 == null || messageObject2.getId() == 0) { continue; } if ((!messageObject2.isOut() || messageObject2.messageOwner.from_scheduled) && messageObject != null && messageObject.isUnread()) { ignore = true; messageId = 0; } if (count > 2) { break; } count++; } if (holder != null && !ignore) { if (messageObject != null) { messageId = messageObject.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" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), messageId); editor.putInt("diditemo" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), offset); } else { pausedOnLastMessage = true; editor.remove("diditem" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId())); editor.remove("diditemo" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId())); } 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(); } } public void setResolvedChatLink(TL_account.resolvedBusinessChatLinks resolvedChatLink) { this.resolvedChatLink = resolvedChatLink; } public void applyChatLinkMessageMaybe() { if (chatActivityEnterView == null || chatMode != 0 || resolvedChatLink == null) { return; } ArrayList entities; final boolean isPremium = UserConfig.getInstance(currentAccount).isPremium(); if (!isPremium && UserConfig.getInstance(currentAccount).getClientUserId() != dialog_id && resolvedChatLink.entities != null) { entities = resolvedChatLink.entities.stream().filter(entity -> { if (entity instanceof TLRPC.TL_messageEntityCustomEmoji) { TLRPC.TL_messageEntityCustomEmoji emojiEntity = (TLRPC.TL_messageEntityCustomEmoji) entity; long documentId = emojiEntity.document_id; TLRPC.Document emoji = emojiEntity.document; if (emoji == null) { emoji = AnimatedEmojiDrawable.findDocument(currentAccount, documentId); } if (emoji == null) { ArrayList sets1 = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_EMOJIPACKS); for (TLRPC.TL_messages_stickerSet set : sets1) { if (set != null && set.documents != null && !set.documents.isEmpty()) { for (TLRPC.Document document : set.documents) { if (document.id == documentId) { emoji = document; break; } } } if (emoji != null) { break; } } } if (emoji == null) { ArrayList sets2 = MediaDataController.getInstance(currentAccount).getFeaturedEmojiSets(); for (TLRPC.StickerSetCovered set : sets2) { if (set != null && set.covers != null && !set.covers.isEmpty()) { for (TLRPC.Document document : set.covers) { if (document.id == documentId) { emoji = document; break; } } } if (emoji != null) { break; } ArrayList documents = null; if (set instanceof TLRPC.TL_stickerSetFullCovered) { documents = ((TLRPC.TL_stickerSetFullCovered) set).documents; } else if (set instanceof TLRPC.TL_stickerSetNoCovered && set.set != null) { TLRPC.TL_inputStickerSetID inputStickerSetID = new TLRPC.TL_inputStickerSetID(); inputStickerSetID.id = set.set.id; TLRPC.TL_messages_stickerSet fullSet = MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSetID, true); if (fullSet != null && fullSet.documents != null) { documents = fullSet.documents; } } if (documents != null && !documents.isEmpty()) { for (TLRPC.Document document : documents) { if (document.id == documentId) { emoji = document; break; } } } if (emoji != null) { break; } } } if (emoji != null) { TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialog_id); if (chatFull != null && chatFull.emojiset != null) { TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getGroupStickerSetById(chatFull.emojiset); if (stickerSet != null) { for (TLRPC.Document document : stickerSet.documents) { if (document.id == documentId) { return true; } } } } } return !(emoji == null || !MessageObject.isFreeEmoji(emoji)); } else { return true; } }).collect(Collectors.toCollection(ArrayList::new)); } else { entities = resolvedChatLink.entities; } CharSequence message = ChatActivityEnterView.applyMessageEntities(entities, resolvedChatLink.message, chatActivityEnterView.getEditField().getPaint().getFontMetricsInt()); if (message != null && message.length() > 0 && message.charAt(0) == '@') { message = TextUtils.concat(" ", message); } chatActivityEnterView.setFieldText(message, true, true); resolvedChatLink = null; } public void applyDraftMaybe(boolean canClear) { applyDraftMaybe(canClear, false); } private int appliedDraftDate; public void applyDraftMaybe(boolean canClear, boolean forceSet) { if (chatActivityEnterView == null || chatMode != 0 && chatMode != MODE_SUGGESTIONS && (chatMode != MODE_SAVED || getUserConfig().getClientUserId() != getSavedDialogId())) { return; } if (chatMode == MODE_SUGGESTIONS && (!ChatObject.isMonoForum(currentChat) || threadMessageId == 0 && ChatObject.canManageMonoForum(currentAccount, currentChat))) { return; } TLRPC.DraftMessage draftMessage = null; Long topicId = null; if (isForumInViewAsMessagesMode()) { Pair pair = getMediaDataController().getOneThreadDraft(dialog_id); if (pair != null) { topicId = pair.first; draftMessage = pair.second; } } else { draftMessage = getMediaDataController().getDraft(dialog_id, chatMode == MODE_SAVED ? 0 : threadMessageId); } MediaDataController.DraftVoice voiceDraft = MediaDataController.getInstance(currentAccount).getDraftVoice(dialog_id, getTopicId()); TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to != null && draftMessage.reply_to.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, topicId != null ? topicId : threadMessageId) : null; if ((forceSet && draftMessage != null) || chatActivityEnterView.getFieldText() == null || chatMode == 0 && getUserConfig().getClientUserId() == getDialogId() && draftMessage != null && appliedDraftDate < draftMessage.date) { if (voiceDraft != null) { chatActivityEnterView.setVoiceDraft(voiceDraft); } else if (draftMessage != null) { appliedDraftDate = draftMessage.date; 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_messageEntityBlockquote) { QuoteSpan.putQuoteToEditable(stringBuilder, entity.offset, entity.offset + entity.length, entity.collapsed); } else if (entity instanceof TLRPC.TL_messageEntityCustomEmoji) { Paint.FontMetricsInt fontMetrics = null; try { fontMetrics = chatActivityEnterView.getEditField().getPaint().getFontMetricsInt(); } catch (Exception e) { FileLog.e(e, false); } 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, true, true); if (getArguments().getBoolean("hasUrl", false)) { chatActivityEnterView.setSelection(draftMessage.message.indexOf('\n') + 1); AndroidUtilities.runOnUIThread(() -> { if (!BaseFragment.hasSheets(ChatActivity.this)) { if (chatActivityEnterView != null) { chatActivityEnterView.setFieldFocused(true); chatActivityEnterView.openKeyboard(); } } }, 700); } chatActivityEnterView.setEffectId(draftMessage.effect); } } else if (canClear && draftMessage == null) { chatActivityEnterView.setFieldText(""); chatActivityEnterView.setEffectId(0); hideFieldPanel(true); } if (/*messageSuggestionParams == null &&*/ draftMessage != null && draftMessage.suggested_post != null) { messageSuggestionParams = MessageSuggestionParams.of(draftMessage.suggested_post); showFieldPanelForSuggestionParams(messageSuggestionParams); } if (replyingMessageObject == null || threadMessageObject == replyingMessageObject) { if (draftReplyMessage != null && !(threadMessageObject != null && threadMessageObject.getId() == draftReplyMessage.id)) { replyingMessageObject = new MessageObject(currentAccount, draftReplyMessage, getMessagesController().getUsers(), false, false); if (draftMessage.reply_to != null && (draftMessage.reply_to.flags & 4) != 0) { replyingQuote = ReplyQuote.from(replyingMessageObject, draftMessage.reply_to.quote_text, (draftMessage.reply_to.flags & 16) != 0 ? draftMessage.reply_to.quote_offset : -1); } checkNewMessagesOnQuoteEdit(false); if (replyingQuote != null) { showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); } else { showFieldPanelForReply(replyingMessageObject); } updateBottomOverlay(); } else if (topicId != null && topicId != 0 && currentChat != null) { // user created a draft in topic TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, topicId); if (topic != null && topic.topicStartMessage != null) { replyingMessageObject = new MessageObject(currentAccount, topic.topicStartMessage, getMessagesController().getUsers(), false, false); replyingMessageObject.replyToForumTopic = topic; showFieldPanelForReply(replyingMessageObject); updateBottomOverlay(); } } } } private void checkNewMessagesOnQuoteEdit(boolean update) { if (replyingMessageObject == null) return; for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); if (msg == null) continue; if (msg.getId() == replyingMessageObject.getId() && msg.getDialogId() == replyingMessageObject.getDialogId()) { replyingMessageObject = msg; if (replyingQuote != null) { replyingQuote.checkEdit(msg); } if (update) { if (messagePreviewParams != null) { messagePreviewParams.updateReply(replyingMessageObject, replyingQuoteGroup != null ? replyingQuoteGroup : getGroup(replyingMessageObject.getGroupId()), dialog_id, replyingQuote); } fallbackFieldPanel(); } break; } } } 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 (selectedMessagesCountTextView != null) { selectedMessagesCountTextView.setTextSize(!AndroidUtilities.isTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 18 : 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.getFragmentStack().isEmpty() || parentLayout.getFragmentStack().get(0) == ChatActivity.this || parentLayout.getFragmentStack().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.isRoundOnce() || messageObject.isVoiceOnce()) { continue; } 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(ChatActivity.this, 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, message.type != 0 ? getTopicId() : 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 finalSelectedGroup) { createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, false); } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, boolean hideDimAfter) { if (finalSelectedObject == null && (selectedMessagesIds[0].size() + selectedMessagesIds[1].size()) == 0) { return; } AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, (int) getTopicId(), chatMode, null, () -> { hideActionMode(); updatePinnedMessageView(true); }, hideDimAfter ? () -> dimBehindView(false) : null, themeDelegate); } private void hideActionMode() { if (actionBar != null) { if (!actionBar.isActionModeShowed()) { return; } bottomViewsVisibilityController.setViewVisible(MESSAGE_ACTION_CONTAINER, false, true); actionBar.hideActionMode(); } cantDeleteMessagesCount = 0; canEditMessagesCount = 0; cantForwardMessagesCount = 0; canSaveMusicCount = 0; canSaveDocumentsCount = 0; cantSaveMessagesCount = 0; if (chatActivityEnterView != null) { EditTextCaption editTextCaption = chatActivityEnterView.getEditField(); if (editTextCaption != null) { 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; if (tagSelector != null) { hideTagSelector(); } } private boolean createMenu(View v, boolean single, boolean listView, float x, float y, boolean longpress) { return createMenu(v, single, listView, x, y, true, longpress); } private CharSequence getMessageCaption(MessageObject messageObject, MessageObject.GroupedMessages group) { return getMessageCaption(messageObject, group, null); } public static CharSequence getMessageCaption(MessageObject messageObject, MessageObject.GroupedMessages group, int[] msgId) { if (messageObject == null) { return null; } String restrictionReason = MessagesController.getInstance(messageObject.currentAccount).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; if (msgId != null) { msgId[0] = message.getId(); } } } return caption; } private boolean createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup, boolean longpress) { return createMenu(v, single, listView, x, y, searchGroup, longpress, false); } @SuppressLint("ClickableViewAccessibility") private boolean createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup, boolean longpress, boolean suggestEdit) { if (actionBar.isActionModeShowed() || isReport()) { return false; } if (chatActivityEnterView != null) { chatActivityEnterView.hideHints(); } 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 && TlUtils.isInstance(message.messageOwner.action, TLRPC.TL_messageActionGiftPremium.class, TLRPC.TL_messageActionGiftCode.class, TLRPC.TL_messageActionGiftStars.class)) { return false; } if (factCheckHint != null) { factCheckHint.hide(false); } FileLog.d("open menu msg_id=" + message.getId() + (message.getDocument() != null ? " doc_id=" + message.getDocument().id : "")); final int type = getMessageType(message); if (single) { boolean isGiveawayResultsMessage = false; if (message.messageOwner.action instanceof TLRPC.TL_messageActionGiveawayResults) { isGiveawayResultsMessage = true; } if (message.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage || isGiveawayResultsMessage) { if (message.getReplyMsgId() != 0) { AndroidUtilities.runOnUIThread(() -> scrollToMessageId(message.getReplyMsgId(), message.messageOwner.id, true, message.getDialogId() == mergeDialogId ? 1 : 0, false, 0)); } else { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.MessageNotFound), themeDelegate).show(); } return true; } else if (!longpress && message.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { 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_paymentReceiptStars) { StarsIntroActivity.showTransactionSheet(getContext(), false, currentAccount, (TLRPC.TL_payments_paymentReceiptStars) response, resourceProvider); } else if (response instanceof TLRPC.PaymentReceipt) { presentFragment(new PaymentFormActivity((TLRPC.PaymentReceipt) response)); } }), ConnectionsManager.RequestFlagFailOnServerErrors); return true; } else if (!longpress && message.messageOwner.action instanceof TLRPC.TL_messageActionPaymentRefunded) { TLRPC.TL_messageActionPaymentRefunded action = (TLRPC.TL_messageActionPaymentRefunded) message.messageOwner.action; StarsIntroActivity.showTransactionSheet(getContext(), currentAccount, message.messageOwner.date, action, resourceProvider); 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) && !isThreadChat()) { 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_SAVED || chatMode == MODE_QUICK_REPLIES) { allowPin = false; } else if (chatMode == MODE_SCHEDULED || (isThreadChat() && !isTopic)) { allowPin = false; } else if (currentChat != null) { allowPin = message.getDialogId() != mergeDialogId && ChatObject.canPinMessages(currentChat) && (!currentChat.monoforum /*|| ChatObject.canManageMonoForum(currentAccount, 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; } if (UserObject.isReplyUser(dialog_id) || dialog_id == UserObject.VERIFY) { allowPin = false; } allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION; boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards || getDialogId() == UserObject.VERIFY; boolean noforwardsOrPaidMedia = noforwards || message.type == MessageObject.TYPE_PAID_MEDIA; boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())) && !message.isExpiredStory(); boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId && message.type != MessageObject.TYPE_STORY && message.type != MessageObject.TYPE_POLL; 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 (message.isExpiredStory() || 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 || bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE && !(bottomOverlayChatWaitsReply && selectedObject != null && (MessageObject.getTopicId(currentAccount, selectedObject.messageOwner, ChatObject.isForum(currentChat)) != 0 || selectedObject.wasJustSent))) { allowChatActions = false; } if (currentChat != null && (ChatObject.isNotInChat(currentChat) && !ChatObject.isMonoForum(currentChat) && !isThreadChat())) { allowChatActions = false; } if (currentChat != null && (ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup)) { allowChatActions = false; } if (currentChat != null && (!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; if (AndroidUtilities.isAccessibilityScreenReaderEnabled() && message.messageOwner != null && message.messageOwner.from_id != null && message.messageOwner.from_id.user_id != getUserConfig().clientUserId && chatMode != MODE_SAVED) { items.add(LocaleController.getString(R.string.OpenProfile)); options.add(OPTION_OPEN_PROFILE); icons.add(R.drawable.msg_user_search); } if (!getUserConfig().isPremium() && !getMessagesController().premiumFeaturesBlocked() && message.getDocument() != null && message.getDocument().size >= 150 * 1024 * 1024 && FileLoader.getInstance(currentAccount).isLoadingFile(FileLoader.getAttachFileName(message.getDocument())) && chatMode != MODE_SAVED) { items.add(LocaleController.getString(R.string.PremiumSpeedPromo)); options.add(OPTION_SPEED_PROMO); icons.add(R.drawable.msg_speed); if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW) { TLRPC.TL_help_premiumPromo premiumPromo = MediaDataController.getInstance(currentAccount).getPremiumPromo(); String typeString = PremiumPreviewFragment.featureTypeToServerString(PremiumPreviewFragment.PREMIUM_FEATURE_DOWNLOAD_SPEED); if (premiumPromo != null) { int index = -1; for (int i = 0; i < premiumPromo.video_sections.size(); i++) { if (premiumPromo.video_sections.get(i).equals(typeString)) { index = i; break; } } if (index != -1) { FileLoader.getInstance(currentAccount).loadFile(premiumPromo.videos.get(index), premiumPromo, FileLoader.PRIORITY_HIGH, 0); } } } } 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) { createUndoView(); if (undoView == null) { return; } undoView.showWithAction(dialog_id, action, currentUser, userInfo != null ? userInfo.ttl_period : chatInfo.ttl_period, null, null); } } }, true, 0, 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; fillMessageMenu(primaryMessage, icons, items, options); } if (selectedObject != null && selectedObject.isHiddenSensitive() && !selectedObject.isMediaSpoilersRevealed) { for (int i = 0; i < options.size(); ++i) { final int option = options.get(i); switch (option) { case OPTION_SAVE_TO_GALLERY: case OPTION_SAVE_TO_GALLERY2: case OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC: case OPTION_SHARE: case OPTION_FORWARD: case OPTION_REPLY: options.remove(i); items.remove(i); icons.remove(i); i--; break; } } } if (suggestEdit) { items.clear(); options.clear(); icons.clear(); if (selectedObject != null && (selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.type == MessageObject.TYPE_PHOTO || selectedObject.type == MessageObject.TYPE_VIDEO)) { items.add(LocaleController.getString(R.string.EditOfferMessage)); options.add(OPTION_SUGGESTION_EDIT_MESSAGE); icons.add(R.drawable.msg_edit); } items.add(LocaleController.getString(R.string.EditOfferPrice)); options.add(OPTION_SUGGESTION_EDIT_PRICE); icons.add(R.drawable.menu_edit_price); items.add(LocaleController.getString(R.string.EditOfferTime)); options.add(OPTION_SUGGESTION_EDIT_TIME); icons.add(R.drawable.msg_calendar2); } 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(); final boolean isReactionsViewAvailable = !suggestEdit && !isSecretChat() && !isInScheduleMode() && currentUser == null && primaryMessage.hasReactions() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) && !ChatObject.isMonoForum(currentChat) && !availableReacts.isEmpty() && primaryMessage.messageOwner.reactions.can_see_list && !primaryMessage.isSecretMedia(); final boolean isReactionsAvailable; if (suggestEdit) { isReactionsAvailable = false; } else if (message.isForwardedChannelPost()) { TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(-message.getFromChatId()); if (chatInfo == null) { isReactionsAvailable = true; } else { isReactionsAvailable = !isSecretChat() && chatMode != MODE_QUICK_REPLIES && !isInScheduleMode() && primaryMessage.isReactionsAvailable() && (chatInfo != null && (!(chatInfo.available_reactions instanceof TLRPC.TL_chatReactionsNone) || chatInfo.paid_reactions_available)) && !availableReacts.isEmpty(); } } else { isReactionsAvailable = !message.isSecretMedia() && chatMode != MODE_QUICK_REPLIES && !isSecretChat() && !isInScheduleMode() && primaryMessage.isReactionsAvailable() && (chatInfo != null && (!(chatInfo.available_reactions instanceof TLRPC.TL_chatReactionsNone) || chatInfo.paid_reactions_available) || (chatInfo == null && !ChatObject.isChannel(currentChat)) || currentUser != null || ChatObject.isMonoForum(currentChat)) && !availableReacts.isEmpty(); } final boolean showMessageSeen = !suggestEdit && !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) && chatMode != MODE_SAVED && message.canSetReaction() && !ChatObject.isMonoForum(currentChat); final boolean showMessageAuthor = !suggestEdit && currentChat != null && !message.isOut() && ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat) && -currentChat.linked_monoforum_id == message.getFromChatId(); final boolean showPrivateMessageSeen = !suggestEdit && !isReactionsViewAvailable && currentChat == null && currentEncryptedChat == null && (currentUser != null && !UserObject.isUserSelf(currentUser) && !UserObject.isReplyUser(currentUser) && !UserObject.isAnonymous(currentUser) && !currentUser.bot && !UserObject.isService(currentUser.id)) && (userInfo == null || !userInfo.read_dates_private) && !isInScheduleMode() && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().pmReadDateExpirePeriod) && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); final boolean showPrivateMessageEdit = !suggestEdit && (currentUser == null || !UserObject.isReplyUser(currentUser) && !UserObject.isAnonymous(currentUser)) && !isInScheduleMode() && message.isEdited() && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); final boolean showPrivateMessageFwdOriginal = !suggestEdit && false && (currentUser == null || !UserObject.isReplyUser(currentUser) && !UserObject.isAnonymous(currentUser)) && !isInScheduleMode() && message.isForwarded() && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); final boolean showSponsorInfo = !suggestEdit && selectedObject != null && selectedObject.isSponsored() && (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith("https://" + getMessagesController().linkPrefix)); final boolean isReactionsAvailableFinal = !suggestEdit && isReactionsAvailable; int flags = 0; if (isReactionsViewAvailable || showMessageSeen || showSponsorInfo) { 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, primaryMessage, dialog_id); int count = 0; if (primaryMessage.messageOwner.reactions != null) { for (TLRPC.ReactionCount r : primaryMessage.messageOwner.reactions.results) { count += r.count; } } boolean hasHeader = count > 10 && primaryMessage.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 * ReactedUsersListView.ITEM_HEIGHT_DP + (hasHeader ? 44 * 2 + 8 : 44)) + (!hasHeader ? 1 : 0))); ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); backCell.setItemHeight(44); backCell.setTextAndIcon(LocaleController.getString(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 = primaryMessage.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.ReactionCount reactionCount = null; if (index >= 0) { reactionCount = counters.get(index); } ReactedUsersListView v = new ReactedUsersListView(container.getContext(), themeDelegate, currentAccount, message, reactionCount, false, true) .setSeenUsers(reactedView.getSeenUsers()) .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { if (getParentActivity() == null || getContext() == null) return; final EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { @Override public void dismiss() { super.dismiss(); dimBehindView(false); } }; alert.setCalcMandatoryInsets(isKeyboardVisible()); alert.setDimBehind(false); closeMenu(false); showDialog(alert); }) .setOnProfileSelectedListener((view, userId, messagePeerReaction) -> { Bundle args = new Bundle(); if (userId > 0) { args.putLong("user_id", userId); } else { args.putLong("chat_id", -userId); } args.putInt("report_reaction_message_id", primaryMessage.getId()); args.putLong("report_reaction_from_dialog_id", dialog_id); 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 { linearLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); reactedUsersListView = new ReactedUsersListView(contentView.getContext(), themeDelegate, currentAccount, primaryMessage, null, false, true) .setSeenUsers(reactedView.getSeenUsers()) .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { if (getParentActivity() == null || getContext() == null) return; final EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { @Override public void dismiss() { super.dismiss(); dimBehindView(false); } }; alert.setCalcMandatoryInsets(isKeyboardVisible()); alert.setDimBehind(false); closeMenu(false); showDialog(alert); }) .setOnProfileSelectedListener((view, userId, messagePeerReaction) -> { Bundle args = new Bundle(); if (userId > 0) { args.putLong("user_id", userId); } else { args.putLong("chat_id", -userId); } args.putInt("report_reaction_message_id", primaryMessage.getId()); args.putLong("report_reaction_from_dialog_id", dialog_id); 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(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); linearLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); backContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Bulletin.hideVisible(); 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 && (finalMessageSeenView.dates.size() <= 0 || finalMessageSeenView.dates.get(0) <= 0)) { TLObject object = finalMessageSeenView.users.get(0); if (object == null) { return; } Bundle args = new Bundle(); if (object instanceof TLRPC.User) { args.putLong("user_id", ((TLRPC.User) object).id); } else if (object instanceof TLRPC.Chat) { args.putLong("chat_id", ((TLRPC.Chat) object).id); } ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); return; } if (SharedConfig.messageSeenHintCount > 0 && contentView.getKeyboardHeight() < AndroidUtilities.dp(20)) { messageSeenPrivacyBulletin = BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), themeDelegate).createErrorBulletin(AndroidUtilities.replaceTags(LocaleController.getString(R.string.MessageSeenTooltipMessage))); messageSeenPrivacyBulletin.setDuration(4000); messageSeenPrivacyBulletin.show(); SharedConfig.updateMessageSeenHintCount(SharedConfig.messageSeenHintCount - 1); } 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) -> { TLObject object = finalMessageSeenView.users.get(position); if (object == null) { return; } closeMenu(true); Bundle args = new Bundle(); if (object instanceof TLRPC.User) { args.putLong("user_id", ((TLRPC.User) object).id); } else if (object instanceof TLRPC.Chat) { args.putLong("chat_id", ((TLRPC.Chat) object).id); } ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); }); foregroundIndex[0] = popupLayout.addViewToSwipeBack(linearLayout); popupLayout.addView(messageSeenLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44)); addGap = true; } else if (showPrivateMessageSeen) { MessagePrivateSeenView messagePrivateSeenView = new MessagePrivateSeenView(getContext(), MessagePrivateSeenView.TYPE_SEEN, message, () -> { closeMenu(true); }, themeDelegate); popupLayout.addView(messagePrivateSeenView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36)); addGap = true; } if (showPrivateMessageEdit) { MessagePrivateSeenView messagePrivateSeenView = new MessagePrivateSeenView(getContext(), MessagePrivateSeenView.TYPE_EDIT, message, () -> { closeMenu(true); }, themeDelegate); popupLayout.addView(messagePrivateSeenView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36)); addGap = true; } if (showPrivateMessageFwdOriginal) { MessagePrivateSeenView messagePrivateSeenView = new MessagePrivateSeenView(getContext(), MessagePrivateSeenView.TYPE_FORWARD, message, () -> { closeMenu(true); }, themeDelegate); popupLayout.addView(messagePrivateSeenView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36)); 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(), !showPrivateMessageSeen && !showPrivateMessageEdit && !showPrivateMessageFwdOriginal, false, themeDelegate); cell.setMinimumWidth(AndroidUtilities.dp(200)); cell.setTextAndIcon(getString(R.string.SaveForNotifications), R.drawable.msg_tone_add); popupLayout.addView(cell); cell.setOnClickListener(v1 -> { if (getMediaDataController().saveToRingtones(message.getDocument())) { UndoView undoView = getUndoView(); if (undoView != null) { undoView.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) { popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } if (showMessageAuthor) { final MessageAuthorView messageAuthorView = new MessageAuthorView(contentView.getContext(), currentAccount, message, currentChat) { @Override protected void openUser(long userId) { closeMenu(true); Bundle args = new Bundle(); args.putLong("user_id", userId); if (userId == getUserConfig().getClientUserId()) { args.putBoolean("my_profile", true); } presentFragment(new ProfileActivity(args)); } }; final FrameLayout messageSeenLayout = new FrameLayout(contentView.getContext()); messageSeenLayout.addView(messageAuthorView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); popupLayout.addView(messageSeenLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36)); popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), 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(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); rateUp.setContentDescription(LocaleController.getString(R.string.AccDescrRateTranscriptionUp)); 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); rateDown.setContentDescription(LocaleController.getString(R.string.AccDescrRateTranscriptionDown)); 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(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); } if (selectedObject != null && selectedObject.isSponsored()) { if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith("https://" + getMessagesController().linkPrefix)) { LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(LinearLayout.VERTICAL); ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); backCell.setItemHeight(44); backCell.setTextAndIcon(LocaleController.getString(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)); linearLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); ArrayList sections = new ArrayList<>(); if (selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith(getMessagesController().linkPrefix)) { TextView textView = new TextView(getParentActivity()); textView.setTextColor(getThemedColor(Theme.key_chat_messageLinkIn)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); Uri uri = Uri.parse(selectedObject.sponsoredUrl); textView.setText(Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null)); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, selectedObject.sponsoredAdditionalInfo == null ? 6 : 0)); textView.setOnClickListener(e -> { if (selectedObject == null) { return; } logSponsoredClicked(selectedObject, false, false); Browser.openUrl(getContext(), Uri.parse(selectedObject.sponsoredUrl), true, false, false, null, null, false, getMessagesController().sponsoredLinksInappAllow, false); }); textView.setOnLongClickListener(e -> { if (selectedObject == null) { return false; } if (AndroidUtilities.addToClipboard(selectedObject.sponsoredUrl)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getParentActivity()), themeDelegate).createCopyLinkBulletin().show(); } return true; }); sections.add(textView); } if (selectedObject.sponsoredInfo != null) { TextView textView = new TextView(getParentActivity()); textView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); textView.setText(selectedObject.sponsoredInfo); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, selectedObject.sponsoredAdditionalInfo == null ? 6 : 0)); textView.setOnClickListener(e -> { if (AndroidUtilities.addToClipboard(selectedObject.sponsoredInfo)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getParentActivity()), themeDelegate).createCopyBulletin(LocaleController.getString(R.string.TextCopied)).show(); } }); sections.add(textView); } if (selectedObject.sponsoredAdditionalInfo != null) { TextView textView = new TextView(getParentActivity()); textView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); textView.setText(selectedObject.sponsoredAdditionalInfo); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, 6)); textView.setOnClickListener(e -> { if (AndroidUtilities.addToClipboard(selectedObject.sponsoredAdditionalInfo)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getParentActivity()), themeDelegate).createCopyBulletin(LocaleController.getString(R.string.TextCopied)).show(); } }); sections.add(textView); } for (int i = 0; i < sections.size(); ++i) { View section = sections.get(i); if (i > 0) { FrameLayout separator = new FrameLayout(getParentActivity()); separator.setBackgroundColor(getThemedColor(Theme.key_divider)); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 1); params.height = 1; linearLayout.addView(separator, params); } linearLayout.addView(section, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } final int foregroundIndex = popupLayout.addViewToSwipeBack(linearLayout); ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); cell.setTextAndIcon(LocaleController.getString(selectedObject.sponsoredCanReport ? R.string.SponsoredMessageSponsorReportable : R.string.SponsoredMessageSponsor), R.drawable.msg_channel); popupLayout.addView(cell); cell.setOnClickListener(v1 -> { if (contentView == null || getParentActivity() == null) { return; } popupLayout.getSwipeBack().openForeground(foregroundIndex); }); popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } if (!selectedObject.sponsoredCanReport) { FrameLayout sponsoredAbout = new FrameLayout(getParentActivity()) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }; sponsoredAbout.setMinimumHeight(AndroidUtilities.dp(56)); sponsoredAbout.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), popupLayout.getItemsCount() <= 0 ? 6 : 0, 0)); sponsoredAbout.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); ImageView infoImage = new ImageView(getParentActivity()); infoImage.setScaleType(ImageView.ScaleType.CENTER); infoImage.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.MULTIPLY)); infoImage.setImageResource(R.drawable.msg_info); sponsoredAbout.addView(infoImage, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 40, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT))); TextView infoText = new TextView(getParentActivity()) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST && getLayout() != null) { Layout layout = getLayout(); int width = 0; for (int i = 0; i < layout.getLineCount(); ++i) { width = Math.max(width, (int) Math.ceil(layout.getLineWidth(i))); } widthMeasureSpec = MeasureSpec.makeMeasureSpec(getPaddingLeft() + width + getPaddingRight(), MeasureSpec.EXACTLY); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }; infoText.setMaxLines(3); infoText.setGravity(Gravity.LEFT); infoText.setEllipsize(TextUtils.TruncateAt.END); infoText.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); infoText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); infoText.setMaxWidth(AndroidUtilities.dp(240)); infoText.setText(LocaleController.getString(R.string.SponsoredMessageInfo)); infoText.setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(43), 0, LocaleController.isRTL ? AndroidUtilities.dp(43) : 0, 0); sponsoredAbout.addView(infoText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL)); popupLayout.addView(sponsoredAbout); sponsoredAbout.setOnClickListener(v1 -> { if (contentView == null || getParentActivity() == null) { return; } BottomSheet.Builder builder = new BottomSheet.Builder(contentView.getContext()); builder.setCustomView(new SponsoredMessageInfoView(getParentActivity(), null, themeDelegate)); builder.show(); }); popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } } scrimPopupWindowItems = new ActionBarMenuSubItem[items.size()]; for (int a = 0, N = items.size(); a < N; a++) { 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 == OPTION_DELETE && selectedObject != null) { if (selectedObject.messageOwner.ttl_period != 0) { menuDeleteItem = cell; updateDeleteItemRunnable.run(); cell.setSubtextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText6)); } else if (selectedObject.isPaidSuggestedPostProtected()) { final long until = selectedObject.messageOwner.date + getMessagesController().config.starsSuggestedPostAgeMin.get(TimeUnit.SECONDS); cell.setSubtext(LocaleController.formatString(R.string.SuggestedOfferPaidUntil, LocaleController.formatDateTime(until, false))); cell.setSubtextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText6)); } } scrimPopupWindowItems[a] = cell; if (option == OPTION_REMOVE_ADS) { popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } 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) { final boolean translateEnabled = getMessagesController().getTranslateController().isContextTranslateEnabled(); String toLangDefault = LocaleController.getInstance().getCurrentLocale().getLanguage(); String toLang = TranslateAlert2.getToLanguage(); int[] messageIdToTranslate = new int[] { message.getId() }; final CharSequence finalMessageText = message.getMessageTextToTranslate(groupedMessages, messageIdToTranslate); Utilities.CallbackReturn onLinkPress = (link) -> { didPressMessageUrl(link, false, selectedObject, v instanceof ChatMessageCell ? (ChatMessageCell) v : null); return true; }; TLRPC.InputPeer inputPeer = selectedObject != null && (selectedObject.isPoll() || selectedObject.isVoiceTranscriptionOpen() || selectedObject.isSponsored() || selectedObject.scheduled || chatMode == MODE_QUICK_REPLIES) ? null : getMessagesController().getInputPeer(dialog_id); if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.originalLanguage != null) { waitForLangDetection.set(false); String fromLang = selectedObject.messageOwner.originalLanguage; cell.setVisibility( fromLang != null && (!fromLang.equals(toLang) || !fromLang.equals(toLangDefault) || fromLang.equals(TranslateController.UNKNOWN_LANGUAGE)) && ( translateEnabled && !RestrictedLanguagesSelectActivity.getRestrictedLanguages().contains(fromLang) || (currentChat != null && (currentChat.has_link || ChatObject.isPublic(currentChat)) || selectedObject.messageOwner.fwd_from != null) && ("uk".equals(fromLang) || "ru".equals(fromLang)) ) ? View.VISIBLE : View.GONE ); cell.setOnClickListener(e -> { if (selectedObject == null || i >= options.size() || getParentActivity() == null) { return; } String toLangValue = fromLang != null && fromLang.equals(toLang) ? toLangDefault : toLang; ArrayList entities = selectedObject != null && selectedObject.messageOwner != null ? selectedObject.messageOwner.entities : null; TranslateAlert2 alert = TranslateAlert2.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageIdToTranslate[0], fromLang, toLangValue, finalMessageText, entities, noforwardsOrPaidMedia, onLinkPress, () -> dimBehindView(false)); alert.setDimBehind(false); closeMenu(false); int hintCount = MessagesController.getNotificationsSettings(currentAccount).getInt("dialog_show_translate_count" + getDialogId(), 5); if (hintCount > 0) { hintCount--; MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dialog_show_translate_count" + getDialogId(), hintCount).apply(); updateTopPanel(true); } }); } else 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(toLangDefault) || fromLang[0].equals(TranslateController.UNKNOWN_LANGUAGE)) && ( translateEnabled && !RestrictedLanguagesSelectActivity.getRestrictedLanguages().contains(fromLang[0]) || (currentChat != null && (currentChat.has_link || ChatObject.isPublic(currentChat)) || selectedObject.messageOwner.fwd_from != 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; } String toLangValue = fromLang[0] != null && fromLang[0].equals(toLang) ? toLangDefault : toLang; ArrayList entities = selectedObject != null && selectedObject.messageOwner != null ? selectedObject.messageOwner.entities : null; TranslateAlert2 alert = TranslateAlert2.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageIdToTranslate[0], fromLang[0], toLangValue, finalMessageText, entities, noforwardsOrPaidMedia, onLinkPress, () -> dimBehindView(false)); alert.setDimBehind(false); closeMenu(false); int hintCount = MessagesController.getNotificationsSettings(currentAccount).getInt("dialog_show_translate_count" + getDialogId(), 5); if (hintCount > 0) { hintCount--; MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dialog_show_translate_count" + getDialogId(), hintCount).apply(); updateTopPanel(true); } }); cell.postDelayed(() -> { if (onLangDetectionDone.get() != null) { onLangDetectionDone.getAndSet(null).run(); } }, 250); } else if (translateEnabled) { cell.setOnClickListener(e -> { if (selectedObject == null || i >= options.size() || getParentActivity() == null) { return; } TranslateAlert2 alert = TranslateAlert2.showAlert(getParentActivity(), this, currentAccount, inputPeer, messageIdToTranslate[0], "und", toLang, finalMessageText, null, noforwardsOrPaidMedia, onLinkPress, () -> dimBehindView(false)); alert.setDimBehind(false); closeMenu(false); int hintCount = MessagesController.getNotificationsSettings(currentAccount).getInt("dialog_show_translate_count" + getDialogId(), 5); if (hintCount > 0) { hintCount--; MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dialog_show_translate_count" + getDialogId(), hintCount).apply(); updateTopPanel(true); } }); } else { cell.setVisibility(View.GONE); } } } if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.video_processing_pending) { popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); FrameLayout layout = new FrameLayout(getParentActivity()) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }; TextView infoText = new TextView(getParentActivity()) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST && getLayout() != null) { Layout layout = getLayout(); int width = 0; for (int i = 0; i < layout.getLineCount(); ++i) { width = Math.max(width, (int) Math.ceil(layout.getLineWidth(i))); } widthMeasureSpec = MeasureSpec.makeMeasureSpec(getPaddingLeft() + width + getPaddingRight(), MeasureSpec.EXACTLY); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }; infoText.setMaxLines(6); infoText.setGravity(Gravity.LEFT); infoText.setEllipsize(TextUtils.TruncateAt.END); infoText.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); infoText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); infoText.setMaxWidth(AndroidUtilities.dp(240)); infoText.setText(getString(R.string.VideoConversionInfo)); infoText.setPadding(dp(13), dp(8), dp(13), dp(8)); layout.addView(infoText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL)); popupLayout.addView(layout); } } 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 { final boolean tags = getUserConfig().getClientUserId() == getDialogId(); reactionsLayout = new ReactionsContainerLayout(tags ? ReactionsContainerLayout.TYPE_TAGS : ReactionsContainerLayout.TYPE_DEFAULT, ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); if (tags) { reactionsLayout.setHint(getUserConfig().isPremium() ? LocaleController.getString(R.string.SavedTagReactionsHint2) : AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.SavedTagReactionsPremiumHint), Theme.key_windowBackgroundWhiteBlueText2, 0, () -> { closeMenu(false); PremiumFeatureBottomSheet sheet = new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true); sheet.setDimBehind(false); sheet.setOnHideListener(d -> { dimBehindView(false); }); sheet.show(); })); } if (isReactionsAvailable && (!tags || !getMessagesController().premiumFeaturesBlocked())) { int pad = 22; int sPad = 24; reactionsLayout.setPadding(dp(4) + (LocaleController.isRTL ? 0 : sPad), dp(4), dp(4) + (LocaleController.isRTL ? sPad : 0), dp(pad)); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; reactionsLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { @Override public void onReactionClicked(View v, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean longpress, boolean addToRecent) { float x = 0, y = 0; BaseCell cell = findMessageCell(primaryMessage.getId(), true); if (cell instanceof ChatMessageCell) { final ChatMessageCell messageCell = (ChatMessageCell) cell; final ReactionsLayoutInBubble.ReactionButton btn = messageCell.reactionsLayoutInBubble.getReactionButton(visibleReaction); if (btn != null) { x = messageCell.reactionsLayoutInBubble.x + btn.x + btn.width / 2f; y = messageCell.reactionsLayoutInBubble.y + btn.y + btn.height / 2f; } } else if (cell instanceof ChatActionCell) { final ChatActionCell actionCell = (ChatActionCell) cell; final ReactionsLayoutInBubble.ReactionButton btn = actionCell.reactionsLayoutInBubble.getReactionButton(visibleReaction); if (btn != null) { x = actionCell.reactionsLayoutInBubble.x + btn.x + btn.width / 2f; y = actionCell.reactionsLayoutInBubble.y + btn.y + btn.height / 2f; } } if (visibleReaction != null && visibleReaction.isStar) { longpress = true; } selectReaction(cell, primaryMessage, finalReactionsLayout, v, x, y, visibleReaction,false, longpress, addToRecent, false); } @Override public void hideMenu() { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(false); } } }); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, (int) (52 + reactionsLayout.getTopOffset() / AndroidUtilities.density + pad), Gravity.RIGHT, 0, 50, 0, -20); scrimPopupContainerLayout.addView(reactionsLayout, params); scrimPopupContainerLayout.setReactionsLayout(reactionsLayout); scrimPopupContainerLayout.setClipChildren(false); MessageObject messageWithReactions = message; MessageObject.GroupedMessages group = getValidGroupedMessage(message); if (group != null) { messageWithReactions = group.findPrimaryMessageObject(); } reactionsLayout.setMessage(messageWithReactions, chatInfo, true); 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(false); isEnter = true; } else if (toProgress == 1 && isEnter) { finalReactionsLayout.setAlpha(1f - progress); if (progress == 1f) { isEnter = false; } } } }); } } boolean showNoForwards = (getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards && currentUser != null && currentUser.bot) && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED && chatMode != MODE_SAVED && getDialogId() != UserObject.VERIFY; 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(R.string.ForwardsRestrictedInfoChannel) : LocaleController.getString(R.string.ForwardsRestrictedInfoGroup)); } else { tv.setText(LocaleController.getString(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.isSendError() && message.messageOwner != null && message.messageOwner.errorNewPriceStars > 0) { popupLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); TextView tv = new TextView(contentView.getContext()); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); tv.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); CharSequence text = TextUtils.concat( StarsIntroActivity.replaceStars(LocaleController.formatPluralString("PaidMessagesSendErrorState1", (int) message.messageOwner.errorAllowedPriceStars)), " ", StarsIntroActivity.replaceStars(LocaleController.formatPluralString("PaidMessagesSendErrorState2", (int) message.messageOwner.errorNewPriceStars)) ); tv.setText(text); 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 && !getMessagesController().premiumFeaturesBlocked()) { 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, MessageContainsEmojiButton.EMOJI_TYPE); button.setOnClickListener(e -> { final 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)); popupLayout.precalculateHeight(); } } } } ReactionsContainerLayout finalReactionsLayout1 = reactionsLayout; if (reactionsLayout != null) { reactionsLayout.setParentLayout(scrimPopupContainerLayout); } scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { @Override public void dismiss() { super.dismiss(); if (scrimPopupWindow != this) { return; } if (Bulletin.getVisibleBulletin() == messageSeenPrivacyBulletin && messageSeenPrivacyBulletin != null) { messageSeenPrivacyBulletin.hide(); messageSeenPrivacyBulletin = null; } scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); if (scrimPopupWindowHideDimOnDismiss) { dimBehindView(false); } else { scrimPopupWindowHideDimOnDismiss = true; } if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } } @Override public void dismiss(boolean animated) { super.dismiss(animated); if (finalReactionsLayout1 != null) { finalReactionsLayout1.dismissParent(animated); } } }; scrimPopupWindow.setPauseNotifications(true); scrimPopupWindow.setDismissAnimationDuration(220); scrimPopupWindow.setOutsideTouchable(true); scrimPopupWindow.setClippingEnabled(true); if (!isReactionsAvailable || reactionsLayout == null || !ReactionsContainerLayout.allowSmoothEnterTransition()) { scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); } else { scrimPopupWindow.setAnimationStyle(0); } 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_ADJUST_NOTHING); 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; int minY = (int) (chatListView.getY() + dp(24)); int maxY = totalHeight - height - dp(8); if (height < totalHeight) { popupY = (int) (chatListView.getY() + v.getTop() + y); if (isInsideContainer) { int[] location = new int[2]; v.getLocationInWindow(location); popupY = (int) (location[1] + y); chatListView.getLocationInWindow(location); minY = dp(24); maxY = Math.min(location[1] + chatListView.getMeasuredHeight(), AndroidUtilities.displaySize.y) - dp(8) - height; } else if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { popupY += AndroidUtilities.dp(240) - height; } popupY = Utilities.clamp(popupY, maxY, minY); } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } final int finalPopupX = scrimPopupX = popupX; final int finalPopupY = scrimPopupY = popupY; scrimPopupContainerLayout.setMaxHeight(maxY + height - popupY); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; Runnable showMenu = () -> { if (scrimPopupWindow == null || fragmentView == null || scrimPopupWindow.isShowing() || !AndroidUtilities.isActivityRunning(getParentActivity())) { return; } scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); if (isReactionsAvailableFinal && finalReactionsLayout != null) { finalReactionsLayout.startEnterAnimation(true); } 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() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } return true; } if (chatActivityEnterView != null && (chatActivityEnterView.isRecordingAudioVideo() || chatActivityEnterView.isRecordLocked())) { return false; } if (message != null && message.type == MessageObject.TYPE_JOINED_CHANNEL) { return false; } createActionMode(); final ActionBarMenu actionMode = actionBar.createActionMode(); actionMode.setItemVisibility(delete, View.VISIBLE); actionsButtonsLayout.bringToFront(); bottomViewsVisibilityController.setViewVisible(MESSAGE_ACTION_CONTAINER, true, true); int translationY = chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(51); createActionMode(); 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, null, null, views.toArray(new View[0]), new boolean[]{false, true, true}, null, 0); if (getParentActivity() instanceof LaunchActivity) { ((LaunchActivity) getParentActivity()).hideVisibleActionMode(); } if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } } else if (bottomChannelButtonsLayout.getVisibility() == View.VISIBLE) { actionBar.showActionMode(true, null, null, null, new boolean[]{true}, null, 0); } else { actionBar.showActionMode(true, null, null, null, null, null, 0); } 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; } if (selectedMessagesCountTextView != null) { selectedMessagesCountTextView.setNumber(selectedMessagesIds[0].size() + selectedMessagesIds[1].size(), false); } updateVisibleRows(); if (chatActivityEnterView != null) { chatActivityEnterView.hideBotCommands(); } return false; } private void createEmptyView(boolean recreate) { if (emptyViewContainer != null && !recreate || getContext() == null) { return; } if (emptyViewContainer == null) { emptyViewContainer = new FrameLayout(getContext()); // emptyViewContainer.setOnTouchListener((v, event) -> true); emptyViewContainer.setVisibility(View.INVISIBLE); contentView.addView(emptyViewContainer, 3, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else { emptyViewContainer.removeAllViews(); } emptyViewContainer.setTranslationX(getSideMenuWidth() / 2f); if (chatAdapter.isFiltered) { emptyView = new TextView(getContext()); emptyView.setText(LocaleController.getString(R.string.NoFilteredMessages)); emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(getThemedColor(Theme.key_chat_serviceText)); emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyView.setTypeface(AndroidUtilities.bold()); emptyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(2), AndroidUtilities.dp(10), AndroidUtilities.dp(3)); emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else if (chatMode == MODE_QUICK_REPLIES) { quickRepliesEmptyView = new QuickRepliesEmptyView(getContext(), chatMode, dialog_id, threadMessageId, quickReplyShortcut, getResourceProvider()); quickRepliesEmptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(16), quickRepliesEmptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContainer.addView(quickRepliesEmptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else if (chatMode == MODE_EDIT_BUSINESS_LINK) { businessLinksEmptyView = new BusinessLinksEmptyView(getContext(), this, businessLink, getResourceProvider()); businessLinksEmptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(16), businessLinksEmptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContainer.addView(businessLinksEmptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else if (preloadedGreetingsSticker != null && currentUser != null && !userBlocked || userInfo != null && getDialogId() != getUserConfig().getClientUserId() && (userInfo.contact_require_premium && !getUserConfig().isPremium() || userInfo.send_paid_messages_stars > StarsController.getInstance(currentAccount).getBalance().amount)) { greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, currentAccount, preloadedGreetingsSticker, themeDelegate) { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); setVisiblePart(getY() + emptyViewContent.getY(), getServiceHeight(this)); } }; updateGreetingLock(); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, replyingQuote, null, true, 0, 0, false, null, quickReplyShortcut, getQuickReplyId(), 0, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); }); // greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(16), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContent = new LinearLayout(getContext()); emptyViewContent.setOrientation(LinearLayout.VERTICAL); emptyViewContent.setGravity(Gravity.CENTER); emptyViewContent.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); emptyViewContainer.addView(emptyViewContent, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); if (userInfo != null && userInfo.business_intro != null) { greetingsViewContainer.setPreview(userInfo.business_intro.title, userInfo.business_intro.description); greetingsViewContainer.setSticker(userInfo.business_intro.sticker); } updateGreetInfo(); } else if (currentEncryptedChat == null) { if (isTopic && chatMode == 0) { CreateTopicEmptyView createTopicEmptyView = new CreateTopicEmptyView(getContext(), contentView, themeDelegate); emptyViewContainer.addView(createTopicEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else if (!isThreadChat() && chatMode == 0 && ((currentUser != null && currentUser.self) || (currentChat != null && currentChat.creator && !ChatObject.isChannelAndNotMegaGroup(currentChat)))) { bigEmptyView = new ChatBigEmptyView(getContext(), 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(R.string.GroupEmptyTitle1))); } } else { String emptyMessage = null; if (isThreadChat() && chatMode == 0) { if (isComments) { emptyMessage = LocaleController.getString(R.string.NoComments); } else { emptyMessage = LocaleController.getString(R.string.NoReplies); } } else if (chatMode == MODE_SCHEDULED) { emptyMessage = LocaleController.getString(R.string.NoScheduledMessages); } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { emptyMessage = LocaleController.getString(R.string.GotAQuestion); } else if (chatMode != MODE_SUGGESTIONS && (currentUser == null || currentUser.self || currentUser.deleted || userBlocked)) { emptyMessage = LocaleController.getString(R.string.NoMessages); } if (emptyMessage == null) { greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, currentAccount, preloadedGreetingsSticker, themeDelegate) { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); setVisiblePart(getY() + emptyViewContent.getY(), getServiceHeight(this)); } }; updateGreetingLock(); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, replyingQuote, null, true, 0, 0, false, null, quickReplyShortcut, getQuickReplyId(), 0, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); }); // greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(16), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); if (userInfo != null && userInfo.business_intro != null) { greetingsViewContainer.setPreview(userInfo.business_intro.title, userInfo.business_intro.description); greetingsViewContainer.setSticker(userInfo.business_intro.sticker); } emptyViewContent = new LinearLayout(getContext()); emptyViewContent.setOrientation(LinearLayout.VERTICAL); emptyViewContent.setGravity(Gravity.CENTER); emptyViewContent.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); emptyViewContainer.addView(emptyViewContent, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); updateGreetInfo(); } else { emptyView = new TextView(getContext()); 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(30), emptyView, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyView.setTypeface(AndroidUtilities.bold()); emptyView.setPadding(AndroidUtilities.dp(9), AndroidUtilities.dp(2), AndroidUtilities.dp(9), AndroidUtilities.dp(3)); emptyViewContainer.addView(emptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } } } else { bigEmptyView = new ChatBigEmptyView(getContext(), contentView, ChatBigEmptyView.EMPTY_VIEW_TYPE_SECRET, themeDelegate); if (currentEncryptedChat.admin_id == getUserConfig().getClientUserId()) { bigEmptyView.setStatusText(LocaleController.formatString(R.string.EncryptedPlaceholderTitleOutgoing, UserObject.getFirstName(currentUser))); } else { bigEmptyView.setStatusText(LocaleController.formatString(R.string.EncryptedPlaceholderTitleIncoming, UserObject.getFirstName(currentUser))); } emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } } private void updateGreetingLock() { if (greetingsViewContainer == null) return; if (ChatObject.isMonoForum(currentChat)) { TLRPC.Chat mfChat = getLinkedMonoForumChat(); if (mfChat != null && currentChat != null && !ChatObject.canManageMonoForum(currentAccount, currentChat)) { final long send_paid_messages_stars = currentChat.send_paid_messages_stars; final CharSequence title = AndroidUtilities.replaceTags(StarsIntroActivity.replaceStars(send_paid_messages_stars > 0 ? formatString(R.string.SuggestionLockedStars, DialogObject.getShortName(-mfChat.id), LocaleController.formatNumber(send_paid_messages_stars, ',')): formatString(R.string.SuggestionUnlockedStars, DialogObject.getShortName(-mfChat.id)), 1.0f)); final CharSequence button = send_paid_messages_stars > 0 ? LocaleController.getString(R.string.MessageStarsUnlock) : null; greetingsViewContainer.setPremiumLock(true, true, title, button, v -> { final long balance = StarsController.getInstance(currentAccount).getBalance().amount; if (balance < send_paid_messages_stars) { new StarsIntroActivity.StarsNeededSheet(getContext(), getResourceProvider(), send_paid_messages_stars, StarsIntroActivity.StarsNeededSheet.TYPE_PRIVATE_MESSAGE, DialogObject.getShortName(getDialogId()), this::updateBottomOverlay, getDialogId()).show(); } else { new StarsIntroActivity.StarsOptionsSheet(getContext(), resourceProvider).show(); } }); } else { greetingsViewContainer.resetPremiumLock(); } } else if (getDialogId() != getUserConfig().getClientUserId()) { if (userInfo != null && userInfo.contact_require_premium) { greetingsViewContainer.setPremiumLock(!getUserConfig().isPremium(), AndroidUtilities.replaceTags(formatString(getMessagesController().premiumFeaturesBlocked() ? R.string.MessageLockedPremiumLocked : R.string.MessageLockedPremium, DialogObject.getShortName(dialog_id))), LocaleController.getString(R.string.MessagePremiumUnlock), v -> { BaseFragment fragment = LaunchActivity.getLastFragment(); if (fragment != null) { fragment.presentFragment(new PremiumPreviewFragment("contact")); } }); } else if (userInfo != null && userInfo.send_paid_messages_stars > 0) { final long send_paid_messages_stars = userInfo.send_paid_messages_stars; greetingsViewContainer.setPremiumLock(send_paid_messages_stars > 0, AndroidUtilities.replaceTags(StarsIntroActivity.replaceStars(formatString(R.string.MessageLockedStars, DialogObject.getShortName(dialog_id), LocaleController.formatNumber(userInfo.send_paid_messages_stars, ',')), 1.0f)), LocaleController.getString(R.string.MessageStarsUnlock), v -> { final long balance = StarsController.getInstance(currentAccount).getBalance().amount; if (balance < send_paid_messages_stars) { new StarsIntroActivity.StarsNeededSheet(getContext(), getResourceProvider(), send_paid_messages_stars, StarsIntroActivity.StarsNeededSheet.TYPE_PRIVATE_MESSAGE, DialogObject.getShortName(getDialogId()), this::updateBottomOverlay, getDialogId()).show(); } else { new StarsIntroActivity.StarsOptionsSheet(getContext(), resourceProvider).show(); } }); } else { greetingsViewContainer.resetPremiumLock(); } } else { greetingsViewContainer.resetPremiumLock(); } } 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(); } } private void updateGreetInfo() { showGreetInfo( getDialogId() != getUserConfig().getClientUserId() && userInfo != null && userInfo.business_intro != null && !(userInfo != null && (userInfo.contact_require_premium && !getUserConfig().isPremium() || userInfo.send_paid_messages_stars > 0)) ); } private void showGreetInfo(boolean show) { if (emptyViewContent == null) return; if (show && greetingsInfo == null) { greetingsInfo = new ChatActionCell(getContext(), false, getResourceProvider()) { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); setVisiblePart(getY() + emptyViewContent.getY(), getServiceHeight(this)); } }; ScaleStateListAnimator.apply(greetingsInfo, .02f, 1.2f); greetingsInfo.setOnClickListener(v -> { showDialog(new PremiumFeatureBottomSheet(this, PremiumPreviewFragment.PREMIUM_FEATURE_BUSINESS, true)); }); } if (greetingsInfo == null) return; if (!show) { greetingsInfo.setVisibility(View.GONE); return; } else { greetingsInfo.setVisibility(View.VISIBLE); } String string = LocaleController.formatString(userInfo != null && userInfo.business_intro != null && TextUtils.isEmpty(userInfo.business_intro.title) && TextUtils.isEmpty(userInfo.business_intro.title) ? R.string.GreetingHowSticker : R.string.GreetingHow, UserObject.getFirstName(currentUser)); int fromIndex = string.indexOf("**"), toIndex; SpannableStringBuilder ssb = new SpannableStringBuilder(string); if (fromIndex > 0) { string = string.substring(0, fromIndex) + string.substring(fromIndex + 2); toIndex = string.indexOf("**"); if (toIndex > 0) { string = string.substring(0, toIndex) + string.substring(toIndex + 2); ssb = new SpannableStringBuilder(string); ProfileActivity.ShowDrawable drawable = new ProfileActivity.ShowDrawable(string.substring(fromIndex, toIndex)); drawable.setTextColor(Color.WHITE); drawable.setBackgroundColor(0x1e000000); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); ssb.setSpan(new ImageSpan(drawable), fromIndex, toIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } greetingsInfo.setCustomText(ssb); greetingsInfo.setOverrideTextMaxWidth(HintView2.cutInFancyHalf(string, (TextPaint) getThemedPaint(Theme.key_paint_chatActionText))); if (greetingsInfo.getParent() != null && (!show || greetingsInfo.getParent() != emptyViewContent)) { ((ViewGroup) greetingsInfo.getParent()).removeView(greetingsInfo); } if (show && greetingsInfo.getParent() != emptyViewContent) { emptyViewContent.addView(greetingsInfo, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 10, 0, 0)); } } Runnable updateReactionRunnable; private void showMultipleReactionsPromo(View cell, ReactionsLayoutInBubble.VisibleReaction visibleReaction, int currentChosenReactions) { if (SharedConfig.multipleReactionsPromoShowed || cell == null || visibleReaction == null || getUserConfig().isPremium()) { return; } if (currentChosenReactions == 1) { SharedConfig.setMultipleReactionsPromoShowed(true); TLRPC.Document document; if (visibleReaction.documentId == 0) { TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(visibleReaction.emojicon); if (availableReaction == null) { return; } document = availableReaction.center_icon; } else { document = AnimatedEmojiDrawable.findDocument(currentAccount, visibleReaction.documentId); } if (document == null) { return; } BulletinFactory.of(ChatActivity.this).createEmojiBulletin( document, LocaleController.getString(R.string.ChatMultipleReactionsPromo) ).setDuration(Bulletin.DURATION_PROLONG).show(); } } public void selectReaction(View cell, MessageObject primaryMessage, ReactionsContainerLayout reactionsLayout, View fromView, float x, float y, ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean fromDoubleTap, boolean bigEmoji, boolean addToRecent, boolean withoutAnimation) { if (isInScheduleMode() || primaryMessage == null) { return; } if (getMessagesController().isFrozen()) { AccountFrozenAlert.show(currentAccount); return; } if (visibleReaction != null && visibleReaction.isStar) { closeMenu(); if (cell == null) { cell = findMessageCell(primaryMessage.getId(), true); } if (bigEmoji) { if (cell != null) { try { cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); } catch (Exception ignored) {} } ArrayList reactors = null; if (primaryMessage != null && primaryMessage.messageOwner != null && primaryMessage.messageOwner.reactions != null) { reactors = primaryMessage.messageOwner.reactions.top_reactors; } final long chatId = -StarsController.MessageId.from(primaryMessage).did; final TLRPC.ChatFull chatFull = getMessagesController().getChatFull(chatId); if (chatFull != null && !chatFull.paid_reactions_available && !(reactors != null && !reactors.isEmpty())) { final TLRPC.Chat chat = getMessagesController().getChat(chatId); BulletinFactory.of(this).createSimpleBulletin(R.raw.stars_topup, AndroidUtilities.replaceTags(LocaleController.formatString(R.string.StarsReactionsDisabled, (chat != null ? chat.title : "")))).show(true); return; } StarsController.getInstance(currentAccount).commitPaidReaction(); final StarsReactionsSheet sheet = new StarsReactionsSheet(getContext(), currentAccount, dialog_id, ChatActivity.this, primaryMessage, reactors, chatFull == null || chatFull.paid_reactions_available, false, 0, themeDelegate); sheet.setMessageCell(ChatActivity.this, primaryMessage.getId(), cell); sheet.show(); return; } if (fragmentView != null) { try { fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} } final long chatId = -StarsController.MessageId.from(primaryMessage).did; final TLRPC.ChatFull chatFull = getMessagesController().getChatFull(chatId); if (chatFull != null && !chatFull.paid_reactions_available) { final TLRPC.Chat chat = getMessagesController().getChat(chatId); BulletinFactory.of(this).createSimpleBulletin(R.raw.stars_topup, AndroidUtilities.replaceTags(LocaleController.formatString(R.string.StarsReactionsDisabled, (chat != null ? chat.title : "")))).show(true); return; } StarsController.PendingPaidReactions pending = StarsController.getInstance(currentAccount).sendPaidReaction(primaryMessage, ChatActivity.this, +1, true, true, null); if (pending != null && cell instanceof BaseCell) { final StarReactionsOverlay overlay = getStarReactionsOverlay(); overlay.setMessageCell((BaseCell) cell); pending.setOverlay(overlay); overlay.show(); final int[] loc = new int[2], loc2 = new int[2]; cell.getLocationInWindow(loc); overlay.getLocationInWindow(loc2); overlay.tap(loc[0] - loc2[0] + x, loc[1] - loc2[1] + y + (cell instanceof ChatMessageCell ? ((ChatMessageCell) cell).starsPriceTopPadding : 0), false, true); } return; } if (getDialogId() == getUserConfig().getClientUserId() && !getUserConfig().isPremium() && primaryMessage.messageOwner != null && (primaryMessage.messageOwner.reactions == null || (primaryMessage.messageOwner.reactions.reactions_as_tags || primaryMessage.messageOwner.reactions.results.isEmpty()))) { new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); return; } ReactionsEffectOverlay.removeCurrent(false); final int currentChosenReactions = primaryMessage.getChoosenReactions().size(); final boolean added = primaryMessage.selectReaction(visibleReaction, 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) { cell = findMessageCell(finalMessageIdForCell, true); showMultipleReactionsPromo(cell, visibleReaction, currentChosenReactions); if (!fromDoubleTap) { ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, fromView, x, y, visibleReaction, currentAccount, reactionsLayout != null ? (bigEmoji ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.ONLY_MOVE_ANIMATION) : ReactionsEffectOverlay.SHORT_ANIMATION); } } if (added && visibleReaction != null && visibleReaction.emojicon != null) { AndroidUtilities.makeAccessibilityAnnouncement(LocaleController.formatString(R.string.AccDescrYouReactedWith, visibleReaction.emojicon)); } ArrayList visibleReactions = new ArrayList<>(); visibleReactions.addAll(primaryMessage.getChoosenReactions()); getSendMessagesHelper().sendReaction(primaryMessage, visibleReactions, added ? visibleReaction : null, bigEmoji, addToRecent, ChatActivity.this, updateReactionRunnable = new Runnable() { @Override public void run() { if (withoutAnimation) { return; } if (updateReactionRunnable != null) { updateReactionRunnable = null; if (fromDoubleTap) { doOnIdle(() -> { AndroidUtilities.runOnUIThread(() -> { BaseCell cell = findMessageCell(finalMessageIdForCell, true); if (added) { ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, null, x, y, visibleReaction, currentAccount, ReactionsEffectOverlay.SHORT_ANIMATION); ReactionsEffectOverlay.startAnimation(); } }, 50); }); } else { doOnIdle(() -> { MessageObject messageToUpdate = primaryMessage; MessageObject messageInDict = messagesDict[0].get(primaryMessage.getId()); if (messageInDict != null && messageInDict != primaryMessage) { messageToUpdate = messagesDict[0].get(primaryMessage.getId()); messageToUpdate.messageOwner.reactions = primaryMessage.messageOwner.reactions; } updateMessageAnimated(messageToUpdate, true); ReactionsEffectOverlay.startAnimation(); }); } closeMenu(); } } }); if (fromDoubleTap || withoutAnimation) { updateMessageAnimated(primaryMessage, true); updateReactionRunnable.run(); } if (!withoutAnimation) { AndroidUtilities.runOnUIThread(updateReactionRunnable, 50); } } @SuppressLint("NotifyDataSetChanged") private void updateMessageAnimated(MessageObject message, boolean updateReactions) { if (chatAdapter == null) { return; } getNotificationCenter().doOnIdle(() -> updateMessageAnimatedInternal(message, updateReactions)); } @SuppressLint("NotifyDataSetChanged") private void updateMessageAnimatedInternal(MessageObject message, boolean updateReactions) { if (chatAdapter == null) { return; } 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 { MessageObject messageInList = messagesDict[0].get(message.getId()); if (updateReactions) { message.forceUpdate = true; message.reactionsChanged = true; } if (chatAdapter.isFiltered) { MessageObject filteredMessage = filteredMessagesDict != null ? filteredMessagesDict.get(message.getId()) : null; int index = chatAdapter.filteredMessages.indexOf(filteredMessage); if (filteredMessage != null && updateReactions) { filteredMessage.forceUpdate = true; filteredMessage.reactionsChanged = true; } if (index >= 0) { chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); } } else { int index = messages.indexOf(messageInList); if (index >= 0) { chatAdapter.notifyItemChanged(chatAdapter.messagesStartRow + index); } } } } public BaseCell findMessageCell(int id, boolean visibleForUser) { if (chatListView == null) { return null; } for (int i = 0, n = chatListView.getChildCount(); i < n; i++) { final View child = chatListView.getChildAt(i); final MessageObject messageObject; if (child instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) child).getMessageObject(); } else if (child instanceof ChatActionCell) { messageObject = ((ChatActionCell) child).getMessageObject(); } else continue; if (messageObject != null && messageObject.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 (BaseCell) child; } } return null; } public View findCell(int id, boolean visibleForUser) { if (chatListView == null) { return null; } for (int i = 0, n = chatListView.getChildCount(); i < n; i++) { final View child = chatListView.getChildAt(i); final MessageObject messageObject; if (child instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) child).getMessageObject(); } else if (child instanceof ChatActionCell) { messageObject = ((ChatActionCell) child).getMessageObject(); } else continue; if (messageObject == null) continue; if (messageObject.getId() == id) { if (visibleForUser) { final float clipTop = chatListViewPaddingTop - chatListViewPaddingVisibleOffset - dp(4); if (child.getY() + child.getMeasuredHeight() < clipTop || child.getY() > chatListView.getMeasuredHeight() - blurredViewBottomOffset) { return null; } } return child; } } return null; } private void startEditingMessageObject(MessageObject messageObject) { startEditingMessageObject(messageObject, false); } private void startEditingMessageObject(MessageObject messageObject, boolean asSuggestion) { if (messageObject == null || getParentActivity() == null) { return; } if (selectionReactionsOverlay != null && selectionReactionsOverlay.isVisible()) { selectionReactionsOverlay.setHiddenByScroll(true); } if (searchItem != null && actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(); chatActivityEnterView.setFieldFocused(); } mentionContainer.getAdapter().setNeedBotContext(false); chatActivityEnterView.setVisibility(View.VISIBLE); showFieldPanelForEdit(true, messageObject); updateBottomOverlay(); if (!asSuggestion) { checkEditTimer(); } if (asSuggestion) { messageSuggestionParams = MessageSuggestionParams.of(messageObject.messageOwner.suggested_post); } chatActivityEnterView.setAllowStickersAndGifs(true, false, false, true); updatePinnedMessageView(true); updateVisibleRows(); if (!asSuggestion && !messageObject.scheduled && !messageObject.isQuickReply()) { 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(R.string.AppName)); builder.setMessage(LocaleController.getString(R.string.EditMessageError)); builder.setPositiveButton(LocaleController.getString(R.string.OK), null); showDialog(builder.create()); if (chatActivityEnterView != null) { chatActivityEnterView.setEditingMessageObject(null, 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(); } } } public static 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 = MessagesController.getInstance(messageObject.currentAccount).getUser(fromId); if (user != null) { str.append(ContactsController.formatName(user.first_name, user.last_name)).append(":\n"); } } else if (fromId < 0) { TLRPC.Chat chat = MessagesController.getInstance(messageObject.currentAccount).getChat(-fromId); if (chat != null) { str.append(chat.title).append(":\n"); } } } } String restrictionReason = MessagesController.getInstance(messageObject.currentAccount).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 static ChatActivity openReportChat(long dialogId, String title, byte[] option, String message) { final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment(); if (lastFragment == null) return null; Bundle args = new Bundle(); if (DialogObject.isUserDialog(dialogId)) { args.putLong("user_id", dialogId); } else { args.putLong("chat_id", -dialogId); } args.putString("reportTitle", title); args.putByteArray("reportOption", option); args.putString("reportMessage", message); final ChatActivity fragment = new ChatActivity(args); lastFragment.presentFragment(fragment); return fragment; } 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)) { File f = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path) && messageObject.cachedQuality != null && messageObject.cachedQuality.isCached()) { File f = new File(messageObject.cachedQuality.uri.getPath()); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path) && messageObject.qualityToSave != null) { File f = FileLoader.getInstance(currentAccount).getPathToAttach(messageObject.qualityToSave, null, false, true); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path)) { return; } 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: { final MessageObject object = selectedObject; final MessageObject.GroupedMessages group = selectedObjectGroup; AlertsCreator.ensurePaidMessageConfirmation(currentAccount, getDialogId(), group != null ? group.messages.size() : 1, payStars -> { if (group != null) { boolean success = true; for (int a = 0; a < group.messages.size(); a++) { if (!getSendMessagesHelper().retrySendMessage(group.messages.get(a), false, payStars)) { success = false; } } if (success && chatMode == 0) { moveScrollToLastMessage(false); } } else { if (getSendMessagesHelper().retrySendMessage(object, false, payStars)) { 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, true); break; } case OPTION_FORWARD: { if (getMessagesController().isFrozen()) { AccountFrozenAlert.show(currentAccount); selectedObject = null; selectedObjectToEditCaption = null; selectedObjectGroup = null; return; } forwardingMessage = selectedObject; forwardingMessageGroup = selectedObjectGroup; Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); args.putInt("messagesCount", 1); args.putInt("hasPoll", forwardingMessage.isTodo() ? 3 : forwardingMessage.isPoll() ? (forwardingMessage.isPublicPoll() ? 2 : 1) : 0); if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat) && currentChat.linked_monoforum_id != 0) { args.putLong("forward_into_channel", -currentChat.linked_monoforum_id); } args.putBoolean("hasInvoice", forwardingMessage.isInvoice()); args.putBoolean("canSelectTopics", true); 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)); } } createUndoView(); if (undoView == null) { return; } 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.of(this).createDownloadBulletin(selectedObject.isVideo() ? BulletinFactory.FileType.VIDEO : BulletinFactory.FileType.PHOTO, 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(R.string.AppName)); builder.setMessage(LocaleController.getString(R.string.IncorrectTheme)); builder.setPositiveButton(LocaleController.getString(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(R.string.AppName)); builder.setMessage(LocaleController.getString(R.string.IncorrectLocalization)); builder.setPositiveButton(LocaleController.getString(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(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 (TextUtils.isEmpty(path)) { File f = FileLoader.getInstance(currentAccount).getPathToMessage(selectedObject.messageOwner); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path) && selectedObject.cachedQuality != null && selectedObject.cachedQuality.isCached()) { File f = new File(selectedObject.cachedQuality.uri.getPath()); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path) && selectedObject.qualityToSave != null) { File f = FileLoader.getInstance(currentAccount).getPathToAttach(selectedObject.qualityToSave, null, false, true); if (f != null && f.exists()) { path = f.getPath(); } } 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 (TextUtils.isEmpty(path)) { return; } MediaController.saveFile(path, getParentActivity(), 0, null, null); BulletinFactory.createSaveToGalleryBulletin(this, selectedObject.isVideo(), themeDelegate).show(); break; } case OPTION_REPLY: { if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.noforwards) { return; } if (selectedObject != null && currentChat != null && (ChatObject.isNotInChat(currentChat) && !ChatObject.isMonoForum(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { MessageObject messageObject = selectedObject; if (messageObject.getGroupId() != 0) { MessageObject.GroupedMessages group = getGroup(messageObject.getGroupId()); if (group != null) { messageObject = group.captionMessage; } } replyingMessageObject = messageObject; Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); args.putBoolean("quote", true); args.putBoolean("reply_to", true); final long author = DialogObject.getPeerDialogId(selectedObject.getFromPeer()); if (author != 0 && author != getDialogId() && author != getUserConfig().getClientUserId() && author > 0) { args.putLong("reply_to_author", author); } args.putInt("messagesCount", 1); args.putBoolean("canSelectTopics", true); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(this); presentFragment(fragment); } else { showFieldPanelForReply(selectedObject); } break; } case OPTION_ADD_TO_STICKERS_OR_MASKS: { StickersAlert alert = new StickersAlert(getParentActivity(), this, selectedObject.getInputStickerSet(), null, bottomChannelButtonsLayout.getVisibility() != View.VISIBLE && (currentChat == null || ChatObject.canSendStickers(currentChat)) ? chatActivityEnterView : null, themeDelegate, false); 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 (TextUtils.isEmpty(path)) { File f = FileLoader.getInstance(currentAccount).getPathToMessage(selectedObject.messageOwner); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path) && selectedObject.cachedQuality != null && selectedObject.cachedQuality.isCached()) { File f = new File(selectedObject.cachedQuality.uri.getPath()); if (f != null && f.exists()) { path = f.getPath(); } } if (TextUtils.isEmpty(path) && selectedObject.qualityToSave != null) { File f = FileLoader.getInstance(currentAccount).getPathToAttach(selectedObject.qualityToSave, null, false, true); if (f != null && f.exists()) { path = f.getPath(); } } MediaController.saveFile(path, getParentActivity(), 2, fileName, selectedObject.getDocument() != null ? selectedObject.getDocument().mime_type : "", uri -> { 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_SUGGESTION_EDIT_MESSAGE: case OPTION_EDIT: { if (selectedObjectToEditCaption != null) { startEditingMessageObject(selectedObjectToEditCaption, option == OPTION_SUGGESTION_EDIT_MESSAGE); } else { startEditingMessageObject(selectedObject, option == OPTION_SUGGESTION_EDIT_MESSAGE); } selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; break; } case OPTION_EDIT_PRICE: { final MessageObject msg = selectedObject; TLRPC.TL_messageMediaPaidMedia paidMedia = (TLRPC.TL_messageMediaPaidMedia) selectedObject.messageOwner.media; StarsIntroActivity.showMediaPriceSheet(getContext(), paidMedia.stars_amount, false, (stars, done) -> { StarsController.getInstance(currentAccount).updateMediaPrice(msg, stars, done); }, themeDelegate); selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; break; } case OPTION_GIFT: { showDialog(new GiftSheet(getContext(), currentAccount, getDialogId(), null, 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(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(R.string.PinOldMessageAlert)); } else { builder.setMessage(LocaleController.getString(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(AndroidUtilities.dp(LocaleController.isRTL ? 16 : 8), 0, AndroidUtilities.dp(LocaleController.isRTL ? 8 : 16), 0); frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT)); cell.setOnClickListener(v -> { CheckBoxCell cell1 = (CheckBoxCell) v; checks[1] = !checks[1]; cell1.setChecked(checks[1], true); }); builder.setCustomViewOffset(6); 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(R.string.PinOldMessageAlert)); checks = new boolean[]{false, true}; } else { if (isTopic) { builder.setMessage(LocaleController.getString(R.string.PinMessageInTopicAlert)); } else { builder.setMessage(LocaleController.getString(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(R.string.PinNotify), "", true, false); cell.setPadding(AndroidUtilities.dp(LocaleController.isRTL ? 16 : 8), 0, AndroidUtilities.dp(LocaleController.isRTL ? 8 : 16), 0); frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT)); cell.setOnClickListener(v -> { CheckBoxCell cell1 = (CheckBoxCell) v; checks[0] = !checks[0]; cell1.setChecked(checks[0], true); }); builder.setCustomViewOffset(9); builder.setView(frameLayout); } } else { if (currentPinnedMessageId != 0 && mid < currentPinnedMessageId) { builder.setMessage(LocaleController.getString(R.string.PinOldMessageAlert)); } else { builder.setMessage(LocaleController.getString(R.string.PinMessageAlertChannel)); } checks = new boolean[]{false, true}; } builder.setPositiveButton(LocaleController.getString(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(() -> { try { view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {} }, 550); }); builder.setNegativeButton(LocaleController.getString(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() || isTopic; } 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/")).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 { ReportBottomSheet.openMessage(ChatActivity.this, selectedObject); } 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(), AlertDialog.ALERT_TYPE_SPINNER, 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_EDIT_TODO: case OPTION_ADD_TO_TODO: { if (!getUserConfig().isPremium()) { showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_TODO, false)); } else { final MessageObject object = selectedObject; final boolean adding = option == OPTION_ADD_TO_TODO; final int oldAnswersCount; if (MessageObject.getMedia(object) instanceof TLRPC.TL_messageMediaToDo) { final TLRPC.TL_messageMediaToDo m = (TLRPC.TL_messageMediaToDo) MessageObject.getMedia(object); oldAnswersCount = m.todo.list.size(); } else { oldAnswersCount = 0; } PollCreateActivity pollCreateActivity = new PollCreateActivity(ChatActivity.this, true, false); pollCreateActivity.setEditing(MessageObject.getMedia(object), adding); pollCreateActivity.setDelegate((poll, params, notify, scheduleDate) -> { if (adding) { int maxUsedId = 0; final TLRPC.TL_messages_appendTodoList req = new TLRPC.TL_messages_appendTodoList(); req.peer = getMessagesController().getInputPeer(object.getDialogId()); req.msg_id = object.getId(); if (poll instanceof TLRPC.TL_messageMediaToDo) { final TLRPC.TL_messageMediaToDo m = (TLRPC.TL_messageMediaToDo) poll; for (int i = 0; i < oldAnswersCount; ++i) { final TLRPC.TodoItem item = m.todo.list.get(i); maxUsedId = Math.max(maxUsedId, item.id); } for (int i = oldAnswersCount; i < m.todo.list.size(); ++i) { final TLRPC.TodoItem item = m.todo.list.get(i); if (item.id <= maxUsedId) { item.id = maxUsedId + 1; } req.list.add(item); maxUsedId = Math.max(maxUsedId, item.id); } if (object.messageOwner.media instanceof TLRPC.TL_messageMediaToDo) { m.completions = ((TLRPC.TL_messageMediaToDo) object.messageOwner.media).completions; } } object.messageOwner.media = poll; getConnectionsManager().sendRequest(req, null); } else { if (poll instanceof TLRPC.TL_messageMediaToDo && object.messageOwner.media instanceof TLRPC.TL_messageMediaToDo) { ((TLRPC.TL_messageMediaToDo) poll).completions = ((TLRPC.TL_messageMediaToDo) object.messageOwner.media).completions; } object.messageOwner.media = poll; getSendMessagesHelper().editMessage(object, null, null, null, null, null, null, false, false, null); } }); presentFragment(pollCreateActivity); } 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(R.string.StopQuizAlertTitle)); builder.setMessage(LocaleController.getString(R.string.StopQuizAlertText)); } else { builder.setTitle(LocaleController.getString(R.string.StopPollAlertTitle)); builder.setMessage(LocaleController.getString(R.string.StopPollAlertText)); } builder.setPositiveButton(LocaleController.getString(R.string.Stop), (dialogInterface, i) -> { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, 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(R.string.Cancel), null); showDialog(builder.create()); break; } case OPTION_VIEW_REPLIES_OR_THREAD: { MessageObject message = selectedObjectGroup != null ? selectedObjectGroup.findPrimaryMessageObject() : selectedObject; if (message != null) { openDiscussionMessageChat(currentChat.id, null, message.getId(), 0, -1, 0, null); } break; } case OPTION_VIEW_IN_TOPIC: { long topicId = MessageObject.getTopicId(currentAccount, selectedObject.messageOwner, true); if (topicId != 0) { TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, topicId); if (topic != null) { ForumUtilities.openTopic(ChatActivity.this, currentChat.id, topic, selectedObject.getId()); } } break; } case OPTION_STATISTICS: { presentFragment(new MessageStatisticActivity(selectedObject)); break; } case OPTION_SEND_NOW: { closeMenu(!preserveDim); Runnable send = () -> { 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, getUserConfig().getClientUserId() == dialog_id ? 0 : -dialog_id, true, true)); } else if (error.text != null) { AndroidUtilities.runOnUIThread(() -> { if (error.text.startsWith("SLOWMODE_WAIT_")) { AlertsCreator.showSimpleToast(ChatActivity.this, LocaleController.getString(R.string.SlowmodeSendError)); } else if (error.text.equals("CHAT_SEND_MEDIA_FORBIDDEN")) { AlertsCreator.showSimpleToast(ChatActivity.this, LocaleController.getString(R.string.AttachMediaRestrictedForever)); } else { AlertsCreator.showSimpleToast(ChatActivity.this, error.text); } }); } }); } }; if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.video_processing_pending) { scheduleNowDialog = new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(LocaleController.getString(R.string.VideoConversionNowTitle)) .setMessage(LocaleController.getString(R.string.VideoConversionNowText)) .setPositiveButton(LocaleController.getString(R.string.VideoConversionNowSend), (di, w) -> { send.run(); }) .setNegativeButton(LocaleController.getString(R.string.Cancel), null) .show(); return; } else { send.run(); } break; } case OPTION_EDIT_SCHEDULE_TIME: { MessageObject message = selectedObject; MessageObject.GroupedMessages group = selectedObjectGroup; AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, message.messageOwner.date, message.messageOwner.schedule_repeat_period, (notify, scheduleDate, scheduleRepeatPeriod) -> { if (group != null && !group.messages.isEmpty()) { SendMessagesHelper.getInstance(currentAccount).editMessage(group.messages.get(0), null, false, ChatActivity.this, null, scheduleDate, scheduleRepeatPeriod); } else { SendMessagesHelper.getInstance(currentAccount).editMessage(message, null, false, ChatActivity.this, null, scheduleDate, scheduleRepeatPeriod); } }, null, themeDelegate) .setOnPreDismissListener(di -> dimBehindView(false)) .setDimBehind(false); preserveDim = true; break; } case OPTION_HIDE_SPONSORED_MESSAGE: { hideAds(); break; } case OPTION_ABOUT_REVENUE_SHARING_ADS: { RevenueSharingAdsInfoBottomSheet.showAlert(contentView.getContext(),ChatActivity.this, false, resourceProvider); break; } case OPTION_REPORT_AD: { ReportBottomSheet.openSponsored(ChatActivity.this, selectedObject, themeDelegate); break; } case OPTION_REMOVE_ADS: { hideAds(); break; } case OPTION_SPEED_PROMO: { showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_DOWNLOAD_SPEED, true)); break; } case OPTION_OPEN_PROFILE: { TLRPC.Peer from = selectedObject.messageOwner.from_id; openUserProfile(from.user_id != 0 ? from.user_id : from.channel_id != 0 ? from.channel_id : from.chat_id); break; } case OPTION_FACT_CHECK: { MessageObject msg = selectedObjectGroup != null ? selectedObjectGroup.findPrimaryMessageObject() : selectedObject; FactCheckController.getInstance(currentAccount).openFactCheckEditor(getContext(), getResourceProvider(), msg, false); break; } case OPTION_SUGGESTION_ADD_OFFER: case OPTION_SUGGESTION_EDIT_PRICE: { final MessageObject msg = selectedObjectGroup != null ? selectedObjectGroup.findPrimaryMessageObject() : selectedObject; final TLRPC.SuggestedPost suggestedPost = msg != null && msg.messageOwner != null ? msg.messageOwner.suggested_post : null; new MessageSuggestionOfferSheet(getContext(), currentAccount, dialog_id, MessageSuggestionParams.of(suggestedPost), this, getResourceProvider(), MessageSuggestionOfferSheet.MODE_EDIT, newParams -> { final TLRPC.SuggestedPost newSuggestedPost = newParams.toTl(); if (msg != null && msg.messageOwner != null && newSuggestedPost != null) { getMessagesController().addOfferToSuggestedMessage(msg, newSuggestedPost); } }).show(); break; } case OPTION_SUGGESTION_EDIT_TIME: { final MessageObject msg = selectedObjectGroup != null ? selectedObjectGroup.findPrimaryMessageObject() : selectedObject; final TLRPC.SuggestedPost suggestedPost = msg != null && msg.messageOwner != null ? msg.messageOwner.suggested_post : null; checkStarsNeedSheet(() -> AlertsCreator.createSuggestedMessageDatePickerDialog(getContext(), suggestedPost != null ? suggestedPost.schedule_date : 0, (notify, scheduleDate, scheduleRepeatPeriod) -> { if (notify) { final TLRPC.SuggestedPost newSuggestedPost = MessageSuggestionParams.of(AmountUtils.Amount.of(suggestedPost != null ? suggestedPost.price : null), scheduleDate).toTl(); if (msg != null && msg.messageOwner != null && newSuggestedPost != null) { getMessagesController().addOfferToSuggestedMessage(msg, newSuggestedPost); } } }, getResourceProvider(), AlertsCreator.SUGGEST_DATE_PICKER_MODE_EDIT).show(), AmountUtils.Amount.of(suggestedPost != null ? suggestedPost.price : null), !ChatObject.canManageMonoForum(currentAccount, getDialogId())); break; } } selectedObject = null; selectedObjectGroup = null; selectedObjectToEditCaption = null; closeMenu(!preserveDim); } public void showSuggestionOfferForEditMessage(MessageSuggestionParams oldParams) { if (editingMessageObject == null) { return; } new MessageSuggestionOfferSheet(getContext(), currentAccount, dialog_id, oldParams, this, getResourceProvider(), MessageSuggestionOfferSheet.MODE_INPUT, params -> { messageSuggestionParams = params; editingMessageObject.messageOwner.suggested_post = params.toTl(); showFieldPanelForEdit(true, editingMessageObject); }).show(); } public void checkStarsNeedSheet(Runnable runnable, AmountUtils.Amount amountRequired, boolean needCheck) { if (amountRequired == null || !needCheck) { runnable.run(); return; } Runnable onLoad = () -> { if (isFinished) { return; } final StarsController starsController = StarsController.getInstance(currentAccount, amountRequired.currency); if (AmountUtils.Amount.ofSafe(starsController.getBalance()).asNano() < amountRequired.asNano()) { if (amountRequired.currency == AmountUtils.Currency.STARS) { new StarsIntroActivity.StarsNeededSheet(getContext(), getResourceProvider(), amountRequired.asDecimal(), StarsIntroActivity.StarsNeededSheet.TYPE_PRIVATE_MESSAGE, ForumUtilities.getMonoForumTitle(currentAccount, getDialogId(), true), null, getDialogId()).show(); } else if (amountRequired.currency == AmountUtils.Currency.TON) { new TONIntroActivity.StarsNeededSheet(getContext(), getResourceProvider(), amountRequired, true, null).show(); } } else { runnable.run(); } }; final StarsController starsController = StarsController.getInstance(currentAccount, amountRequired.currency); if (!starsController.balanceAvailable()) { starsController.getBalance(true, onLoad, true); } else { onLoad.run(); } } private void hideAds() { if (getUserConfig().isPremium()) { BulletinFactory.of(ChatActivity.this) .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) .show(); getMessagesController().disableAds(true); removeFromSponsored(selectedObject); removeMessageWithThanos(selectedObject); } else { showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); } } @Override public boolean didSelectDialogs(DialogsActivity fragment, ArrayList dids, CharSequence message, boolean param, boolean notify, int scheduleDate, int scheduleRepeatPeriod, TopicsFragment topicsFragment) { if ((messagePreviewParams == null && (!fragment.isQuote || replyingMessageObject == null) || fragment.isQuote && replyingMessageObject == null) && forwardingMessage == null && selectedMessagesIds[0].size() == 0 && selectedMessagesIds[1].size() == 0) { return false; } ArrayList fmessages = new ArrayList<>(); if (forwardingMessage != null) { if (forwardingMessageGroup != null) { fmessages.addAll(forwardingMessageGroup.messages); } else { fmessages.add(forwardingMessage); } } 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); } } } } for (int j = 0; j < dids.size(); j++) { TLRPC.Chat chat = getMessagesController().getChat(-dids.get(j).dialogId); if (chat != null) { for (int i = 0; i < fmessages.size(); i++) { int sendError = SendMessagesHelper.canSendMessageToChat(chat, fmessages.get(i)); if (sendError != 0) { AlertsCreator.showSendMediaAlert(sendError, fragment, null); return false; } } } } if (!fragment.isQuote && (dids.size() > 1 || dids.get(0).dialogId == getUserConfig().getClientUserId() || message != null || scheduleDate != 0 || !notify)) { return !AlertsCreator.ensurePaidMessagesMultiConfirmationTopicKeys(currentAccount, dids, fmessages.size() + (TextUtils.isEmpty(message) ? 0 : 1), prices -> { if (fragment.resetDelegate) { fragment.setDelegate(null); } if (forwardingMessage != null) { forwardingMessage = null; forwardingMessageGroup = null; } else { for (int a = 1; a >= 0; a--) { selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); selectedMessagesIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } messagePreviewParams = null; hideFieldPanel(false); for (int a = 0; a < dids.size(); a++) { final long did = dids.get(a).dialogId; final Long price = prices == null ? (Long) 0L : prices.get(did); if (message != null) { final SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(message.toString(), did, null, null, null, true, null, null, null, notify, scheduleDate, scheduleRepeatPeriod, null, false); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.payStars = price == null ? 0 : price; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; getSendMessagesHelper().sendMessage(params); } getSendMessagesHelper().sendMessage(fmessages, did, false, false, notify, scheduleDate, scheduleRepeatPeriod, null, -1, price == null ? 0 : price, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); } fragment.finishFragment(); createUndoView(); if (undoView != null) { if (dids.size() == 1) { if (!BulletinFactory.of(ChatActivity.this).showForwardedBulletinWithTag(dids.get(0).dialogId, fmessages.size())) { undoView.showWithAction(dids.get(0).dialogId, UndoView.ACTION_FWD_MESSAGES, fmessages.size()); } } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, fmessages.size(), dids.size(), null, null); } } }); } else { if (forwardingMessage != null) { forwardingMessage = null; forwardingMessageGroup = null; } else { for (int a = 1; a >= 0; a--) { selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); selectedMessagesIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } MessagesStorage.TopicKey topicKey = dids.get(0); final long did = topicKey.dialogId; if (did != dialog_id || getTopicId() != topicKey.topicId || 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 true; } } if (getMessagesStorage().isMonoForum(topicKey.dialogId)) { args.putInt("chatMode", ChatActivity.MODE_SUGGESTIONS); if (!getMessagesController().isMonoForumWithManageRights(topicKey.dialogId)) { args.putBoolean("isSubscriberSuggestions", true); } } args.putBoolean("historyPreloaded", false); addToPulledDialogsMyself(); ChatActivity chatActivity = new ChatActivity(args); if (topicKey.topicId != 0) { ForumUtilities.applyTopic(chatActivity, topicKey); if (fragment != null) { fragment.removeSelfFromStack(); } } if (presentFragment(chatActivity, true)) { if (fragment.isQuote && replyingMessageObject != null) { if (chatActivityEnterView != null && chatActivity.chatActivityEnterView != null) { chatActivity.chatActivityEnterView.setFieldText( chatActivityEnterView.getFieldText() ); } if (replyingQuoteGroup != null) { chatActivity.replyingQuoteGroup = replyingQuoteGroup; } else if (replyingMessageObject != null) { chatActivity.replyingQuoteGroup = getGroup(replyingMessageObject.getGroupId()); } if (replyingTopMessage != null) { chatActivity.replyingTopMessage = replyingTopMessage; } else if (threadMessageObject != null) { chatActivity.replyingTopMessage = threadMessageObject; } chatActivity.onHideFieldPanelRunnable = () -> { if (chatActivityEnterView != null) { chatActivityEnterView.hideTopView(true); } }; chatActivity.showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); } else { chatActivity.showFieldPanelForForward(true, fmessages); } if (chatActivity.getDialogId() == getDialogId() && !AndroidUtilities.isTablet()) { removeSelfFromStack(); } } else { fragment.finishFragment(); } } else { List fragments = new ArrayList<>(getParentLayout().getFragmentStack()); if (!fragments.isEmpty() && fragments.get(fragments.size() - 1) == fragment) { fragment.finishFragment(); } else { int fragmentIndex = fragments.indexOf(fragment); if (fragmentIndex > 0) { for (int i = fragmentIndex; i < fragments.size(); i++) { if (i == fragments.size() - 1) { fragments.get(i).finishFragment(); } else { fragment.removeSelfFromStack(); } } } } moveScrollToLastMessage(false); if (fragment.isQuote && replyingMessageObject != null) { showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); } else { showFieldPanelForForward(true, fmessages); } if (AndroidUtilities.isTablet()) { hideActionMode(); updatePinnedMessageView(true); } updateVisibleRows(); if (keyboardWasVisible && chatActivityEnterView != null) { chatActivityEnterView.openKeyboardInternal(); chatActivityEnterView.freezeEmojiView(false); keyboardWasVisible = false; } } } return true; } public boolean checkRecordLocked(boolean invoked, boolean forceCloseOnDiscard) { if (chatActivityEnterView != null && chatActivityEnterView.isRecordLocked()) { if (invoked) { final AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); if (chatActivityEnterView.isInVideoMode()) { builder.setTitle(LocaleController.getString(R.string.DiscardVideoMessageTitle)); builder.setMessage(LocaleController.getString(R.string.DiscardVideoMessageDescription)); } else { builder.setTitle(LocaleController.getString(R.string.DiscardVoiceMessageTitle)); builder.setMessage(LocaleController.getString(R.string.DiscardVoiceMessageDescription)); } builder.setPositiveButton(LocaleController.getString(R.string.DiscardVoiceMessageAction), (dialog, which) -> { if (chatActivityEnterView != null) { if (forceCloseOnDiscard) { finishFragment(); } else { chatActivityEnterView.cancelRecordingAudioVideo(); } } }); builder.setNegativeButton(LocaleController.getString(R.string.Continue), null); showDialog(builder.create()); } return true; } return false; } @Override public boolean onBackPressed(boolean invoked) { final Bulletin bulletin = Bulletin.getVisibleBulletin(); if (bulletin != null && bulletin.getLayout() instanceof Bulletin.LottieLayoutWithReactions) { if (invoked) { ((Bulletin.LottieLayoutWithReactions) bulletin.getLayout()).hideReactionsDialog(); bulletin.hide(); } return false; } if (secretVoicePlayer != null && secretVoicePlayer.isShown()) { if (invoked) secretVoicePlayer.dismiss(); return false; } else if (hasShownSheet()) { if (invoked) closeSheet(); return false; } else if (selectionReactionsOverlay != null && !selectionReactionsOverlay.onBackPressed(invoked)) { return false; } else if (ContentPreviewViewer.getInstance().isVisible()) { if (invoked) ContentPreviewViewer.getInstance().closeWithMenu(); return false; } else if (forwardingPreviewView != null && forwardingPreviewView.isShowing()) { if (invoked) forwardingPreviewView.dismiss(true); return false; } else if (messagesSearchListContainer.getTag() != null) { if (invoked) showMessagesSearchListView(false); return false; } else if (scrimPopupWindow != null) { if (invoked) closeMenu(); return false; } else if (checkRecordLocked(invoked, false)) { return false; } else if (textSelectionHelper.isInSelectionMode()) { if (invoked) textSelectionHelper.clear(); return false; } else if (actionBar != null && actionBar.isActionModeShowed()) { if (invoked) clearSelectionMode(); return false; } else if (chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) { if (invoked) chatActivityEnterView.hidePopup(true); return false; // } else if (chatActivityEnterView != null && chatActivityEnterView.hasBotWebView() && chatActivityEnterView.botCommandsMenuIsShowing() && chatActivityEnterView.onBotWebViewBackPressed()) { // return false; } else if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuIsShowing()) { if (invoked) chatActivityEnterView.hideBotCommands(); return false; } else if (chatActivityEnterView != null && chatActivityEnterView.closeCreationLinkDialog(invoked)) { return false; } else if (chatMode == MODE_EDIT_BUSINESS_LINK && BusinessLinksActivity.closeRenameAlert(invoked)) { return false; } else if (ChatObject.isMonoForum(currentChat) && !isSubscriberSuggestions && topicsTabs != null && getTopicId() != 0) { if (invoked) topicsTabs.selectTopic(0, topicChangedFromMessage); return false; } else if (chatMode == MODE_QUICK_REPLIES && !(QuickRepliesController.GREETING.equalsIgnoreCase(quickReplyShortcut) || QuickRepliesController.AWAY.equalsIgnoreCase(quickReplyShortcut)) && (messages.isEmpty() || threadMessageId == 0)) { if (invoked) showQuickRepliesRemoveAlert(); return false; } else if (chatMode == MODE_EDIT_BUSINESS_LINK && chatActivityEnterView.businessLinkHasChanges()) { if (invoked) showBusinessLinksDiscardAlert(this::finishFragment); return false; } else if (actionBar != null && actionBar.isSearchFieldVisible()) { if (invoked) actionBar.closeSearchField(); return false; } if (invoked) { if (backToPreviousFragment != null) { parentLayout.addFragmentToStack(backToPreviousFragment, parentLayout.getFragmentStack().size() - 1); backToPreviousFragment = null; } if (instantCameraView != null) { instantCameraView.cancel(false); } } return true; } private void showQuickRepliesRemoveAlert() { showDialog( new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(LocaleController.getString(R.string.BusinessRepliesRemoveTitle)) .setMessage(LocaleController.getString(R.string.BusinessRepliesRemoveMessage)) .setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { finishFragment(); }) .setNegativeButton(LocaleController.getString(R.string.Cancel), null) .create() ); } private void showBusinessLinksDiscardAlert(Runnable onDiscard) { AlertDialog dialog = new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(LocaleController.getString(R.string.BusinessLinkDiscardChangesTitle)) .setMessage(LocaleController.getString(R.string.BusinessLinkDiscardChangesMessage)) .setPositiveButton(LocaleController.getString(R.string.Discard), (di, w) -> { onDiscard.run(); }) .setNegativeButton(LocaleController.getString(R.string.Cancel), null) .create(); showDialog(dialog); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(getThemedColor(Theme.key_text_RedBold)); } } public void clearSelectionMode() { clearSelectionMode(false); } public void clearSelectionMode(boolean suppressUpdateMessageObject) { for (int a = 1; a >= 0; a--) { selectedMessagesIds[a].clear(); selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(suppressUpdateMessageObject); updateSelectedMessageReactions(); } public void onListItemAnimatorTick() { invalidateMessagesVisiblePart(); if (scrimView != null) { fragmentView.invalidate(); } } public void setSavedDialog(long savedDialogId) { threadMessageId = savedDialogId; } private MessageObject quickReplyMessage; public void setQuickReplyId(long topicId) { threadMessageId = topicId; TLRPC.TL_message message = new TLRPC.TL_message(); message.id = (int) topicId; quickReplyMessage = new MessageObject(currentAccount, message, false, false); } public void setMonoForumThreadMessages(int maxInboxReadId, int maxOutboxReadId, TLRPC.TL_forumTopic forumTopic) { threadMaxInboxReadId = maxInboxReadId; threadMaxOutboxReadId = maxOutboxReadId; replyMaxReadId = Math.max(1, maxInboxReadId); threadMessageId = forumTopic != null ? DialogObject.getPeerDialogId(forumTopic.from_id) : 0; updatePinnedTopicStarterMessage(); updateTopPanel(false); updateBottomOverlay(); } public void setThreadMessages(ArrayList messageObjects, TLRPC.Chat originalChat, int originalMessage, int maxInboxReadId, int maxOutboxReadId, TLRPC.TL_forumTopic forumTopic) { this.forumTopic = forumTopic; 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; isTopic = forumTopic != null; isComments = replyingMessageObject.messageOwner.fwd_from != null && replyingMessageObject.messageOwner.fwd_from.channel_post != 0 && !isTopic; if (isTopic) { replyingMessageObject.isTopicMainMessage = true; } updatePinnedTopicStarterMessage(); updateTopPanel(false); updateBottomOverlay(); } public void updatePinnedTopicStarterMessage() { topicStarterMessageObject = isTopic && !pinnedMessageObjects.isEmpty() && pinnedMessageIds.size() == 1 && pinnedMessageIds.get(0) == getTopicId() + 1 ? pinnedMessageObjects.get(pinnedMessageIds.get(0)) : null; if (isTopic && topicStarterMessageObject != null && topicStarterMessageObject.messageOwner != null && forumTopic != null && !MessageObject.peersEqual(forumTopic.from_id, topicStarterMessageObject.messageOwner.from_id) && !MessageObject.peersEqual(currentChat, topicStarterMessageObject.messageOwner.from_id)) { topicStarterMessageObject = null; } } public void setHighlightMessageId(int id) { highlightMessageId = id; } public void setHighlightQuote(int id, String quote, int quote_offset) { highlightMessageId = id; highlightMessageQuoteFirst = true; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = quote; highlightMessageQuoteOffset = quote_offset; showNoQuoteAlert = true; } public void showNoQuoteFound() { BulletinFactory.of(this).createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.QuoteNotFound)).show(true); } public boolean isThreadChat() { return threadMessageObject != null; } public boolean isReplyChatComment() { return threadMessageObject != null && isComments; } public void updateVisibleRows() { updateVisibleRows(false); } private void updateVisibleRows(boolean suppressUpdateMessageObject) { 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 = getScrollingOffsetForView(child); } 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() || isReport()) { highlightMessageQuoteFirst = false; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = null; highlightTaskId = null; cell.setCheckBoxVisible(threadMessageObjects == null || messageObject == null || !threadMessageObjects.contains(messageObject), true); int idx = messageObject == null || messageObject.getDialogId() == dialog_id ? 0 : 1; if (messageObject != null && 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 (messageObject != null && (!messageObject.deleted || cell.linkedChatId != linkedChatId) && !suppressUpdateMessageObject) { cell.setIsUpdating(true); cell.linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; cell.setMessageObject(messageObject, cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop(), cell.isFirstInChat(), cell.isLastInChatList()); 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 (cell.isHighlighted() && highlightMessageQuote != null) { final long now = System.currentTimeMillis(); if (!cell.setHighlightedText(highlightMessageQuote, true, highlightMessageQuoteOffset, highlightMessageQuoteFirst || now - highlightMessageQuoteFirstTime < 200) && showNoQuoteAlert) { showNoQuoteFound(); } if (highlightMessageQuoteFirst) { highlightMessageQuoteFirstTime = now; } highlightMessageQuoteFirst = false; showNoQuoteAlert = false; } else if (cell.isHighlighted() && highlightTaskId != null) { cell.setHighlightedTask(highlightTaskId); } else if (chatMode == MODE_SEARCH && searchingHashtag != null && searchingQuery != null) { cell.setHighlightedText(searchingQuery); } else if (searchItem != null && searchItemVisible && messageObject != null && 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; if (!suppressUpdateMessageObject) { cell.setMessageObject(cell.getMessageObject()); } cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } } if (lastVisibleItem != RecyclerView.NO_POSITION) { chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top); } } private void updateVisibleRows(Utilities.CallbackReturn condition) { 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 = getScrollingOffsetForView(child); } 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(); if (condition.run(messageObject)) { messageObject.forceUpdate = true; cell.setMessageObject(messageObject, cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop(), cell.isFirstInChat(), cell.isLastInChatList()); chatAdapter.updateRowAtPosition(chatListView.getChildAdapterPosition(cell)); } } } 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()) && !messageObject.isVoiceOnce() && !messageObject.isRoundOnce() && (!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(R.string.AppName)); builder.setPositiveButton(LocaleController.getString(R.string.OK), null); if (message.type == MessageObject.TYPE_VIDEO) { builder.setMessage(LocaleController.getString(R.string.NoPlayerInstalled)); } else { builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type)); } showDialog(builder.create()); } public void openSearchWithText(String text) { boolean delay = false; if (savedMessagesHint != null && savedMessagesHint.shown()) { savedMessagesHint.hide(); delay = true; } if (savedMessagesSearchHint != null && savedMessagesSearchHint.shown()) { savedMessagesSearchHint.hide(); delay = true; } if (delay) { AndroidUtilities.runOnUIThread(() -> openSearchWithText(text), 200); return; } 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 || chatMode == MODE_SAVED || chatMode == MODE_SUGGESTIONS) && 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 || isTopic || chatMode == MODE_SAVED || chatMode == MODE_SUGGESTIONS) && !UserObject.isReplyUser(currentUser)) { openSearchKeyboard = text == null; if (searchItem != null) { searchItem.openSearch(openSearchKeyboard); } } if (searchItem != null) { searchItem.setSearchFieldText(text, false); } getMediaDataController().searchMessagesInChat(searchingQuery = (text == null ? "" : text), dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, !TextUtils.isEmpty(text), searchingReaction); updatePinnedMessageView(true); } public void openHashtagSearch(String hashtag) { openHashtagSearch(hashtag, false); } public void openHashtagSearch(String hashtag, boolean forcePublic) { if (hashtag.isEmpty() || (!hashtag.startsWith("#") && !hashtag.startsWith("$"))) { return; } boolean delay = false; if (savedMessagesHint != null && savedMessagesHint.shown()) { savedMessagesHint.hide(); delay = true; } if (savedMessagesSearchHint != null && savedMessagesSearchHint.shown()) { savedMessagesSearchHint.hide(); delay = true; } if (delay) { AndroidUtilities.runOnUIThread(() -> openHashtagSearch(hashtag), 200); return; } searchingHashtag = hashtag; searchingQuery = searchingHashtag; boolean channelHashtags = hashtag.contains("@"); checkHashtagStories(true); 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 || chatMode == MODE_SAVED || chatMode == MODE_SUGGESTIONS) && 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 (actionBarSearchTags != null && actionBarSearchTags.shown()) { actionBarSearchTags.show(false); } if (searchUserButton != null) { searchUserButton.setVisibility(View.GONE); } if (channelHashtags || forcePublic || ChatObject.isChannelAndNotMegaGroup(currentChat) && ChatObject.isPublic(currentChat) && searchingHashtag != null) { defaultSearchPage = 2; } else { defaultSearchPage = 0; } openSearchKeyboard = false; if (searchType == SEARCH_CHANNEL_POSTS) { HashtagSearchController.getInstance(currentAccount).clearSearchResults(SEARCH_CHANNEL_POSTS); } else { HashtagSearchController.getInstance(currentAccount).clearSearchResults(); } if (searchViewPager != null) { searchViewPager.clearViews(); } if (searchItem != null) { preventReopenSearchWithText = true; searchItem.openSearch(false); preventReopenSearchWithText = false; } if (searchItem != null) { searchItem.setSearchFieldCaption(null); searchItem.setSearchFieldText(hashtag, false); searchItem.setSearchFieldHint(LocaleController.getString(R.string.SearchHashtagsHint)); } getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, false, searchingUserMessages, searchingChatMessages, false, searchingReaction); updatePinnedMessageView(true); hashtagSearchEmptyView.showProgress(true); showMessagesSearchListView(true); if (hashtagSearchTabs != null) { hashtagSearchTabs.show(!channelHashtags); messagesSearchListContainer.setPadding(0, 0, 0, getHashtagTabsHeight()); updateSearchListEmptyView(); } if ((channelHashtags || forcePublic) && searchingHashtag != null && hashtagSearchTabs != null && hashtagSearchTabs.tabs.getCurrentPosition() != defaultSearchPage) { hashtagSearchTabs.tabs.scrollToTab(defaultSearchPage, defaultSearchPage); } HashtagSearchController.getInstance(currentAccount).putToHistory(searchingHashtag); hashtagHistoryView.update(); View view = searchViewPager.getCurrentView(); if (view instanceof ChatActivityContainer) { ((ChatActivityContainer) view).chatActivity.updateSearchingHashtag(searchingHashtag); } } boolean preventReopenSearchWithText = false; private void openSearchWithUser(TLRPC.User user) { boolean delay = false; if (savedMessagesHint != null && savedMessagesHint.shown()) { savedMessagesHint.hide(); delay = true; } if (savedMessagesSearchHint != null && savedMessagesSearchHint.shown()) { savedMessagesSearchHint.hide(); delay = true; } if (delay) { AndroidUtilities.runOnUIThread(() -> openSearchWithUser(user), 200); return; } 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 (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 (searchCalendarButton != null) { searchCalendarButton.setVisibility(View.GONE); } if (searchUserButton != null) { searchUserButton.setVisibility(View.GONE); } } if (searchItem != null) { preventReopenSearchWithText = true; searchItem.openSearch(openSearchKeyboard = false); preventReopenSearchWithText = false; } searchUserMessages(user, null); updatePinnedMessageView(true); } private void openSearchWithChat(TLRPC.Chat chat) { boolean delay = false; if (savedMessagesHint != null && savedMessagesHint.shown()) { savedMessagesHint.hide(); delay = true; } if (savedMessagesSearchHint != null && savedMessagesSearchHint.shown()) { savedMessagesSearchHint.hide(); delay = true; } if (delay) { AndroidUtilities.runOnUIThread(() -> openSearchWithChat(chat), 200); return; } 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 (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 (searchCalendarButton != null) { searchCalendarButton.setVisibility(View.GONE); } if (searchUserButton != null) { searchUserButton.setVisibility(View.GONE); } } if (searchItem != null) { preventReopenSearchWithText = true; searchItem.openSearch(openSearchKeyboard = false); preventReopenSearchWithText = false; } searchUserMessages(null, chat); updatePinnedMessageView(true); } private void updateSearchListEmptyView() { if (searchingHashtag != null) { hashtagSearchEmptyView.subtitle.setText(LocaleController.formatString(R.string.HashtagSearchEmptyViewFilteredSubtitle, searchingHashtag)); messagesSearchListView.setEmptyView(hashtagSearchEmptyView); } else { messagesSearchListView.setEmptyView(null); hashtagSearchEmptyView.setVisibility(View.GONE); } } @Override public void didSelectLocation(TLRPC.MessageMedia location, int locationType, boolean notify, int scheduleDate, long payStars) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(location, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate, 0); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.payStars = payStars; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; getSendMessagesHelper().sendMessage(params); 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 isChannel() { return ChatObject.isChannelAndNotMegaGroup(currentChat); } public boolean canScheduleMessage() { if (chatMode == MODE_QUICK_REPLIES) return false; if (getMessagesController().isMonoForum(getDialogId())) { return false; } if (getMessagesController().isForum(getDialogId()) && !isTopic) { return false; } if (getMessagesController().getSendPaidMessagesStars(getDialogId()) > 0) { return false; } return currentEncryptedChat == null && (bottomChannelButtonsLayout == null || bottomChannelButtonsLayout.getVisibility() != View.VISIBLE) && (!isThreadChat() || isTopic); } public boolean canSendMessage() { return currentEncryptedChat == null && (bottomChannelButtonsLayout == null || bottomChannelButtonsLayout.getVisibility() != View.VISIBLE); } public boolean isInScheduleMode() { return chatMode == MODE_SCHEDULED; } public int getChatMode() { return chatMode; } public boolean isInBotForumMode() { return UserObject.isBotForum(currentUser); } public MessageObject getThreadMessage() { return threadMessageObject; } public MessageObject getReplyMessage() { return replyingMessageObject; } public MessageObject getReplyTopMessage() { return replyingTopMessage; } public ChatActivity.ReplyQuote getReplyQuote() { return replyingQuote; } public long getThreadId() { return threadMessageId; } public long getInlineReturn() { return inlineReturn; } public TLRPC.User getCurrentUser() { return currentUser; } public long getSendMonoForumPeerId() { if (ChatObject.isMonoForum(currentChat) && ChatObject.canManageMonoForum(currentAccount, currentChat)) { long peerId = getThreadId(); if (peerId == 0 && editingMessageObject != null && editingMessageObject.messageOwner != null) { return DialogObject.getPeerDialogId(editingMessageObject.messageOwner.saved_peer_id); } if (peerId == 0 && replyingMessageObject != null && replyingMessageObject.messageOwner != null) { return DialogObject.getPeerDialogId(replyingMessageObject.messageOwner.saved_peer_id); } return peerId; } return 0; } public MessageSuggestionParams getSendMessageSuggestionParams() { return messageSuggestionParams; } public TLRPC.Chat getCurrentChat() { return currentChat; } public TLRPC.Chat getLinkedMonoForumChat() { return currentChat != null ? getMessagesController().getMonoForumLinkedChat(currentChat.id) : null; } 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, int scheduleRepeatPeriod, long effectId, boolean invertMedia, long payStars) { if (checkSlowModeAlert()) { fillEditingMediaWithCaption(caption, null); SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, caption != null ? caption : null, dialog_id, replyingMessageObject, getThreadMessage(), null, notify, scheduleDate, scheduleRepeatPeriod, editingMessageObject, quickReplyShortcut, getQuickReplyId(), effectId, invertMedia, payStars); afterMessageSend(); } } public void sendContact(TLRPC.User user, boolean notify, int scheduleDate, long effectId, boolean invertMedia, long payStars) { if (checkSlowModeAlert()) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(user, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate, 0); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.effect_id = effectId; params.invert_media = invertMedia; params.payStars = payStars; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; getSendMessagesHelper().sendMessage(params); afterMessageSend(); } } public void sendContacts(ArrayList users, String caption, boolean notify, int scheduleDate, long effectId, boolean invertMedia, long payStars) { if (checkSlowModeAlert()) { if (!TextUtils.isEmpty(caption)) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(caption, dialog_id, null, null, null, true, null, null, null, true, 0, 0, null, false); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.effect_id = effectId; params.invert_media = invertMedia; params.payStars = payStars; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; effectId = 0; SendMessagesHelper.getInstance(currentAccount).sendMessage(params); } for (TLRPC.User user : users) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(user, dialog_id, null, null, null, null, notify, scheduleDate, 0); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); params.effect_id = effectId; params.invert_media = invertMedia; params.payStars = payStars; params.monoForumPeer = getSendMonoForumPeerId(); params.suggestionParams = messageSuggestionParams; effectId = 0; getSendMessagesHelper().sendMessage(params); } afterMessageSend(); } } public void sendPoll(TLRPC.TL_messageMediaPoll poll, HashMap params, boolean notify, int scheduleDate, long payStars) { if (checkSlowModeAlert()) { final SendMessagesHelper.SendMessageParams params2 = SendMessagesHelper.SendMessageParams.of(poll, dialog_id, replyingMessageObject, getThreadMessage(), null, params, notify, scheduleDate, 0); params2.quick_reply_shortcut = quickReplyShortcut; params2.quick_reply_shortcut_id = getQuickReplyId(); params2.payStars = payStars; params2.monoForumPeer = getSendMonoForumPeerId(); params2.suggestionParams = messageSuggestionParams; getSendMessagesHelper().sendMessage(params2); afterMessageSend(); } } public void sendTodo(TLRPC.TL_messageMediaToDo todo, boolean notify, int scheduleDate, long payStars) { if (checkSlowModeAlert()) { final SendMessagesHelper.SendMessageParams params2 = SendMessagesHelper.SendMessageParams.of((TLRPC.TL_messageMediaPoll) null, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate, 0); params2.todo = todo; params2.quick_reply_shortcut = quickReplyShortcut; params2.quick_reply_shortcut_id = getQuickReplyId(); params2.payStars = payStars; params2.monoForumPeer = getSendMonoForumPeerId(); params2.suggestionParams = messageSuggestionParams; getSendMessagesHelper().sendMessage(params2); afterMessageSend(); } } public void sendMedia(MediaController.PhotoEntry photoEntry, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, int scheduleRepeatPeriod, boolean forceDocument, long stars) { if (photoEntry == null) { return; } animatorRoundMessageCameraVisibility.setValue(false, true); if (editingMessageObject != null && editingMessageObject.needResendWhenEdit() && !ChatObject.canManageMonoForum(currentAccount, editingMessageObject.getDialogId())) { final MessageSuggestionParams params = messageSuggestionParams != null ? messageSuggestionParams : MessageSuggestionParams.of(editingMessageObject.messageOwner.suggested_post); if (!StarsController.isEnoughAmount(currentAccount, params.amount)) { showSuggestionOfferForEditMessage(params); return; } } if (videoEditedInfo != null && videoEditedInfo.roundVideo) { AndroidUtilities.runOnUIThread(closeInstantCameraAnimation = () -> { closeInstantCameraAnimation = null; runCloseInstantCameraAnimation(); }, 3000); } fillEditingMediaWithCaption(photoEntry.caption, photoEntry.entities); AlertsCreator.ensurePaidMessageConfirmation(currentAccount, getDialogId(), 1, payStars -> { if (editingMessageObject != null && editingMessageObject.needResendWhenEdit()) { MessageSuggestionParams params = messageSuggestionParams != null ? messageSuggestionParams : MessageSuggestionParams.of(editingMessageObject.messageOwner.suggested_post); if (photoEntry.isVideo) { SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, photoEntry.coverPath, photoEntry.coverPhoto, dialog_id, editingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.ttl, null, notify, scheduleDate, scheduleRepeatPeriod, forceDocument, photoEntry.hasSpoiler, photoEntry.caption, quickReplyShortcut, getQuickReplyId(), photoEntry.effectId, payStars, getSendMonoForumPeerId(), params); } else { if (photoEntry.imagePath != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, editingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, null, videoEditedInfo, notify, scheduleDate, scheduleRepeatPeriod, 0, forceDocument, photoEntry.caption, quickReplyShortcut, getQuickReplyId(), photoEntry.effectId, payStars, getSendMonoForumPeerId(), params); } else if (photoEntry.path != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, editingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, null, videoEditedInfo, notify, scheduleDate, scheduleRepeatPeriod, 0, forceDocument, photoEntry.caption, quickReplyShortcut, getQuickReplyId(), photoEntry.effectId, payStars, getSendMonoForumPeerId(), params); } } } else { if (photoEntry.isVideo) { SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, photoEntry.coverPath, photoEntry.coverPhoto, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, scheduleRepeatPeriod, forceDocument, photoEntry.hasSpoiler, photoEntry.caption, quickReplyShortcut, getQuickReplyId(), photoEntry.effectId, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); } else { if (photoEntry.imagePath != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, scheduleRepeatPeriod, 0, forceDocument, photoEntry.caption, quickReplyShortcut, getQuickReplyId(), photoEntry.effectId, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); } else if (photoEntry.path != null) { SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, scheduleRepeatPeriod, 0, forceDocument, photoEntry.caption, quickReplyShortcut, getQuickReplyId(), photoEntry.effectId, payStars, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); } } } afterMessageSend(); }, stars); } private void runCloseInstantCameraAnimation() { if (instantCameraView == null) { return; } final InstantCameraView.InstantViewCameraContainer cameraContainer = instantCameraView.getCameraContainer(); AnimatorSet allAnimators = new AnimatorSet(); allAnimators.playTogether( ObjectAnimator.ofFloat(cameraContainer, View.SCALE_X, 0.5f), ObjectAnimator.ofFloat(cameraContainer, View.SCALE_Y, 0.5f), ObjectAnimator.ofFloat(cameraContainer, View.ALPHA, 0.0f), ObjectAnimator.ofFloat(instantCameraView.getButtonsLayout(), View.ALPHA, 0.0f), ObjectAnimator.ofInt(instantCameraView.getPaint(), AnimationProperties.PAINT_ALPHA, 0), ObjectAnimator.ofFloat(instantCameraView.getMuteImageView(), View.ALPHA, 0.0f) ); allAnimators.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (instantCameraView != null) { instantCameraView.setIsMessageTransition(false); instantCameraView.hideCamera(true); instantCameraView.setVisibility(View.INVISIBLE); } } }); allAnimators.start(); } public void sendAnimatedEmoji(TLRPC.Document emoji, boolean notify, int scheduleDate) { if (emoji == null) { return; } String message = MessageObject.findAnimatedEmojiEmoticon(emoji, null); if (message == null) { return; } ArrayList entities = new ArrayList<>(); TLRPC.TL_messageEntityCustomEmoji entity = new TLRPC.TL_messageEntityCustomEmoji(); entity.document = emoji; entity.document_id = emoji.id; entity.offset = 0; entity.length = message.length(); entities.add(entity); SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(message, dialog_id, replyingMessageObject, getThreadMessage(), null, false, entities, null, null, notify, scheduleDate, 0, null, false); params.quick_reply_shortcut = quickReplyShortcut; params.quick_reply_shortcut_id = getQuickReplyId(); SendMessagesHelper.getInstance(currentAccount).sendMessage(params); 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(R.string.AppName)); String name; if (user != null) { name = ContactsController.formatName(user.first_name, user.last_name); } else { name = ""; } builder.setMessage(LocaleController.formatString(R.string.BotPermissionGameAlert, name)); builder.setPositiveButton(LocaleController.getString(R.string.OK), (dialogInterface, i) -> { showOpenGameAlert(game, messageObject, urlStr, false, uid); MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("askgame_" + uid, false).commit(); }); builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); showDialog(builder.create()); } else { String username = UserObject.getPublicUsername(user); if (!AndroidUtilities.isTablet() && WebviewActivity.supportWebview()) { if (parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 1) == this) { presentFragment(new WebviewActivity(urlStr, user != null && !TextUtils.isEmpty(username) ? username : "", game.title, game.short_name, messageObject)); } } else { WebviewActivity.openGameInBrowser(urlStr, messageObject, getParentActivity(), game.short_name, user != null && username != null ? username : ""); } } } private int commentLoadingGuid; private int commentMessagesLoadingGuid; private int commentRequestId; private int commentMessagesRequestId; private int commentLoadingMessageId; private boolean hideCommentLoading; private long commentLoadingStartedAt; 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 && discussionMessage != null && 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)); } } TLRPC.messages_Messages historyFinal = history; getMessagesStorage().loadMessageAttachPaths(arrayList, () -> { if (!arrayList.isEmpty() && discussionMessage != null) { hideCommentLoading = true; chatListView.invalidateViews(); 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", historyFinal != null); ChatActivity chatActivity = new ChatActivity(args); chatActivity.setThreadMessages(arrayList, originalChat, req.msg_id, discussionMessage.read_inbox_max_id, discussionMessage.read_outbox_max_id, null); 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; hideCommentLoading = false; chatListView.invalidateViews(); }, 200); presentFragment(chatActivity); if (isKeyboardVisible() && !chatActivity.hideKeyboardOnShow()) { if (chatActivity.chatActivityEnterView != null && chatActivity.chatActivityEnterView.getEditField() != null) { chatActivity.chatActivityEnterView.getEditField().requestFocus(); } } }; if (historyFinal != null) { int fnid = 0; if (!historyFinal.messages.isEmpty()) { for (int a = historyFinal.messages.size() - 1; a >= 0; a--) { TLRPC.Message message = historyFinal.messages.get(a); if (message.id > maxReadId && !message.out) { fnid = message.id; break; } } } 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, isTopic, null); }); } else { openCommentsChat.run(); } } else { commentLoadingMessageId = 0; hideCommentLoading = false; chatListView.invalidateViews(); if (fallbackMessage != null) { openOriginalReplyChat(fallbackMessage); } else { if (getParentActivity() != null) { BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(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; hideCommentLoading = false; 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; hideCommentLoading = false; commentLoadingStartedAt = System.currentTimeMillis(); 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)) { MessagesController.showCantOpenAlert(this, LocaleController.getString(R.string.ChannelCantOpenBannedByAdmin)); commentLoadingMessageId = 0; hideCommentLoading = false; 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 openMessageInOriginalDialog(MessageObject messageObject) { Bundle args = new Bundle(); if (messageObject.messageOwner.peer_id.channel_id != 0) { args.putLong("chat_id", messageObject.messageOwner.peer_id.channel_id); } else if (messageObject.messageOwner.peer_id.chat_id != 0) { args.putLong("chat_id", messageObject.messageOwner.peer_id.chat_id); } else if (messageObject.messageOwner.peer_id.user_id != 0) { args.putLong("user_id", messageObject.messageOwner.peer_id.user_id); } args.putInt("message_id", messageObject.getRealId()); args.putBoolean("need_remove_previous_same_chat_activity", false); if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { // presentFragment(DialogsActivity.highlightFoundQuote(new ChatActivity(args), messageObject)); presentFragment(new ChatActivity(args)); } } 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(R.string.OpenUrlTitle)); String format = LocaleController.getString(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(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.setView(linearLayout); builder.setPositiveButton(LocaleController.getString(R.string.Open), (dialogInterface, i) -> { if (!cells[0].isChecked()) { Browser.openUrl(getParentActivity(), url, false); } else { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER, 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.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); } } public void removeMessageWithThanos(MessageObject messageObject) { int index = messages.indexOf(messageObject); if (index == -1) { return; } messages.remove(index); if (chatAdapter != null && !chatAdapter.isFiltered) { chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index, true); } } public void openVCard(TLRPC.User user, String phone, String vcard, String first_name, String last_name) { if (user != null) { Bundle args = new Bundle(); args.putLong("user_id", user.id); args.putBoolean("show_add_to_contacts", true); args.putString("vcard", vcard); args.putString("vcard_phone", phone); args.putString("vcard_first_name", first_name); args.putString("vcard_last_name", last_name); presentFragment(new ProfileActivity(args)); return; } try { File f; if (!TextUtils.isEmpty(vcard)) { f = AndroidUtilities.getSharingDirectory(); f.mkdirs(); f = new File(f, "vcard.vcf"); BufferedWriter writer = new BufferedWriter(new FileWriter(f)); writer.write(vcard); writer.close(); } else { f = null; } showDialog(new PhonebookShareAlert(this, null, user, null, f, PhoneFormat.stripExceptNumbers(phone), 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, boolean forceNoIV) { if (longPress) { if (str.startsWith("@")) { if (cell != null) { cell.resetPressedLink(-1); } didLongPressUsername(cell, url, str.substring(1)); return; } if (url == null) { 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 { try { Uri uri = Uri.parse(formattedUrl); formattedUrl = Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null); } catch (Exception e) { FileLog.e(e, false); } formattedUrl = URLDecoder.decode(formattedUrl.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(R.string.Open)} : new CharSequence[]{LocaleController.getString(R.string.Open), LocaleController.getString(R.string.Copy)}, (dialog, which) -> { if (which == 0) { if (str.startsWith("video?")) { didPressMessageUrl(url, false, messageObject, cell); } else { logSponsoredClicked(messageObject, false, false); openClickableLink(url, str, false, cell, messageObject, true); } } 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); String username = ChatObject.getPublicUsername(currentChat); if (currentChat != null && username != null) { link = "https://t.me/" + username + "/" + messageId + "?t=" + AndroidUtilities.formatTimestamp(finalTimestamp); } } else { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); String username = UserObject.getPublicUsername(user); if (user != null && username != null) { link = "https://t.me/" + username + "/" + messageId + "?t=" + AndroidUtilities.formatTimestamp(finalTimestamp); } } if (link == null) { return; } AndroidUtilities.addToClipboard(link); } else { AndroidUtilities.addToClipboard(str); } createUndoView(); if (undoView == null) { return; } 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 (cell != null) { cell.resetPressedLink(-1); } didLongPressLink(cell, messageObject, url, str); } } else { logSponsoredClicked(messageObject, false, false); String username = Browser.extractUsername(str); if (username != null) { username = username.toLowerCase(); if (ChatObject.hasPublicLink(currentChat, username) || UserObject.hasPublicUsername(currentUser, username)) { if (avatarContainer != null) { avatarContainer.openProfile(false); } else { shakeContent(); } } else if (str.startsWith("@")) { getMessagesController().openByUserName(username, ChatActivity.this, 0, makeProgressForLink(cell, url)); } else { processExternalUrl(0, str, url, cell, false, false); } } else if (str.startsWith("#") || str.startsWith("$")) { if (chatMode == MODE_SCHEDULED || chatMode == MODE_PINNED || chatMode == MODE_SEARCH) { chatActivityDelegate.openHashtagSearch(str); if (chatMode != MODE_SEARCH) { finishFragment(); } } else if (str.contains("@")) { presentFragment(new HashtagActivity(str, resourceProvider)); } else { openHashtagSearch(str); } } else { processExternalUrl(0, str, url, cell, false, false); } } } public void shakeContent() { ViewGroup v = getChatListView(); AndroidUtilities.shakeViewSpring(v, 5); BotWebViewVibrationEffect.APP_ERROR.vibrate(); v = getChatActivityEnterView(); for (int i = 0; i < v.getChildCount(); i++) { AndroidUtilities.shakeViewSpring(v.getChildAt(i), 5); } v = getActionBar(); for (int i = 0; i < v.getChildCount(); i++) { AndroidUtilities.shakeViewSpring(v.getChildAt(i), 5); } } private Browser.Progress makeProgressForLink(ChatMessageCell cell, CharacterStyle span) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); progressDialogCurrent = null; } if (span == null || cell == null || cell.getMessageObject() == null) { return progressDialogCurrent = null; } final int id = cell.getMessageObject().getId(); return progressDialogCurrent = new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = id; progressDialogAtMessageType = PROGRESS_LINK; progressDialogLinkSpan = span; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(() -> { if (progressDialogAtMessageId == id) { resetProgressDialogLoading(); } }, 240); } } }; } private Browser.Progress makeProgressForForward(ChatMessageCell cell) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); progressDialogCurrent = null; } if (cell == null || cell.getMessageObject() == null) { return progressDialogCurrent = null; } final int id = cell.getMessageObject().getId(); return progressDialogCurrent = new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = id; progressDialogAtMessageType = PROGRESS_FORWARD; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(() -> { if (progressDialogAtMessageId == id) { resetProgressDialogLoading(); } }, 240); } } }; } private Browser.Progress makeProgressForBotButton(ChatMessageCell cell, String url) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); progressDialogCurrent = null; } if (url == null || cell == null || cell.getMessageObject() == null) { return progressDialogCurrent = null; } final int id = cell.getMessageObject().getId(); return progressDialogCurrent = new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = id; progressDialogAtMessageType = PROGRESS_BOT_BUTTON; progressDialogBotButtonUrl = url; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(() -> { if (progressDialogAtMessageId == id) { resetProgressDialogLoading(); } }, 240); } } }; } private Browser.Progress makeProgressForPaidMedia(ChatMessageCell cell) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); progressDialogCurrent = null; } if (cell == null || cell.getMessageObject() == null) { return progressDialogCurrent = null; } final int id = cell.getMessageObject().getId(); return progressDialogCurrent = new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = id; progressDialogAtMessageType = PROGRESS_PAID_MEDIA; progressDialogBotButtonUrl = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(() -> { if (progressDialogAtMessageId == id) { resetProgressDialogLoading(); } }, 240); } } }; } private void processExternalUrl(int type, String url, CharacterStyle span, ChatMessageCell cell, boolean forceAlert, boolean forceNoIV) { try { String host = AndroidUtilities.getHostAuthority(url); 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) { boolean forceNotInternalForApps = false; if (span instanceof URLSpanReplacement && (((URLSpanReplacement) span).getTextStyleRun().flags & TextStyleSpan.FLAG_STYLE_TEXT_URL) != 0) { forceNotInternalForApps = true; } AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, !forceNoIV, true, forceNotInternalForApps, makeProgressForLink(cell, span), themeDelegate); } else if (type == 1) { AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, !forceNoIV, false, makeProgressForLink(cell, span), themeDelegate); } } else { if (type == 0) { Browser.openUrl(getParentActivity(), Uri.parse(url), true, !forceNoIV, makeProgressForLink(cell, span)); } else if (type == 1) { Browser.openUrl(getParentActivity(), Uri.parse(url), inlineReturn == 0, !forceNoIV, makeProgressForLink(cell, span)); } else if (type == 2) { Browser.openUrl(getParentActivity(), Uri.parse(url), inlineReturn == 0, !forceNoIV, makeProgressForLink(cell, span)); } } } public void logSponsoredClicked(MessageObject messageObject, boolean media, boolean fullscreen) { if (messageObject == null || !messageObject.isSponsored()) { return; } TLRPC.TL_messages_clickSponsoredMessage req = new TLRPC.TL_messages_clickSponsoredMessage(); req.random_id = messageObject.sponsoredId; req.media = media; req.fullscreen = fullscreen; getConnectionsManager().sendRequest(req, null); } 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 || getDialogId() == UserObject.VERIFY) { ((URLSpanMono) url).copyToClipboard(); UndoView undoView = getUndoView(); if (undoView != null) { undoView.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.getInstance(currentAccount).openChatOrProfileWith(user, null, ChatActivity.this, 0, false); } if (longPress && cell != null) { cell.resetPressedLink(-1); } logSponsoredClicked(messageObject, false, false); } else if (url instanceof URLSpanNoUnderline) { String str = ((URLSpanNoUnderline) url).getURL(); if (str != null && str.startsWith("tel:")) { didPressPhoneNumber(cell, url, str.substring(4)); if (longPress && cell != null) { cell.resetPressedLink(-1); } } else 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(ChatActivity.this, 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()); } if (messageObject == null) { return; } 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); } if (!messageObject.isVoice()) { showDialog(new AudioPlayerAlert(getContext(), themeDelegate)); } } else if (str.startsWith("card:")) { didLongPressCard(cell, url, str.substring(5)); cell.resetPressedLink(-1); } else { openClickableLink(url, str, longPress, cell, messageObject, false); } } else { final String urlFinal = ((URLSpan) url).getURL(); if (urlFinal != null && urlFinal.startsWith("tel:")) { didPressPhoneNumber(cell, url, urlFinal.substring(4)); } else if (longPress) { didLongPressLink(cell, messageObject, url, urlFinal); if (cell != null) { cell.resetPressedLink(-1); } } else { logSponsoredClicked(messageObject, false, false); boolean forceAlert = url instanceof URLSpanReplacement; if (url instanceof URLSpanReplacement && (urlFinal == null || !urlFinal.startsWith("mailto:")) || AndroidUtilities.shouldShowUrlInAlert(urlFinal)) { if (openLinkInternally(urlFinal, cell, url, 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))) { if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(messageObject) != null) { return; } ChatActivity.this.createArticleViewer(false).open(messageObject); return; } } if (openLinkInternally(urlFinal, cell, url, messageObject != null ? messageObject.getId() : 0)) { return; } } if (Browser.urlMustNotHaveConfirmation(urlFinal)) { forceAlert = false; } processExternalUrl(2, urlFinal, url, cell, forceAlert, false); } } } 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(this, 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 == MessageObject.TYPE_PHOTO)) { 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 == MessageObject.TYPE_PHOTO) { arrayList.add(0, m); } } PhotoViewer.getInstance().openPhoto(arrayList, arrayList.indexOf(message), dialog_id, 0, getTopicId(),photoViewerProvider); } else { PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, message.type != 0 ? getTopicId() : 0, photoViewerProvider); } hideHints(false); MediaController.getInstance().resetGoingToShowMessageObject(); } private void updateMessageListAccessibilityVisibility() { if (currentEncryptedChat != null) { return; } 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 == null) { return; } if (!object.isSponsored() || object.viewsReloaded) { return; } object.viewsReloaded = true; TLRPC.TL_messages_viewSponsoredMessage req = new TLRPC.TL_messages_viewSponsoredMessage(); req.random_id = object.sponsoredId; getConnectionsManager().sendRequest(req, null); getMessagesController().markSponsoredAsRead(dialog_id, object); } @Override public boolean canBeginSlide() { if (chatMode == MODE_QUICK_REPLIES && (messages.isEmpty() || threadMessageId == 0)) { return false; } return swipeBackEnabled && chatActivityEnterView.swipeToBackEnabled() && pullingDownOffset == 0 && (quickShareSelectorOverlay == null || !quickShareSelectorOverlay.isActive()); } @Override public boolean isSwipeBackEnabled(MotionEvent event) { if (chatMode == MODE_QUICK_REPLIES && (messages.isEmpty() || threadMessageId == 0)) { return false; } return swipeBackEnabled && (forwardingPreviewView == null || !forwardingPreviewView.isShowing()) && (quickShareSelectorOverlay == null || !quickShareSelectorOverlay.isActive()); } public class ChatActivityAdapter extends RecyclerAnimationScrollHelper.AnimatableAdapter { private Context mContext; private boolean isBot; private int rowCount; private int hintRow = -5; private int botInfoRow = -5; private int botInfoEmptyRow = -5; private int userInfoRow = -5; private int loadingUpRow = -5; private int loadingDownRow = -5; private int userPhotoTimeRow = -5; private int userNameTimeRow = -5; private int freeSpaceRow = -5; public int messagesStartRow; private int messagesEndRow; public ArrayList getMessages() { if (isFrozen) { return frozenMessages; } else if (isFiltered) { return filteredMessages; } else { return ChatActivity.this.messages; } } public boolean isFrozen; public ArrayList frozenMessages = new ArrayList<>(); public boolean isFiltered; public boolean filteredEndReached; public ArrayList filteredMessages = 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 prevUserInfoRow = userInfoRow; int prevHintRow = hintRow; int prevLoadingUpRow = loadingUpRow; int prevLoadingDownRow = loadingDownRow; int prevMessagesStartRow = messagesStartRow; int prevMessagesEndRow = messagesEndRow; int prevUserPhotoTimeRow = userPhotoTimeRow; int prevUserNameTimeRow = userNameTimeRow; updateRowsInternal(); if (prevRowCount != rowCount || prevBotInfoRow != botInfoRow || prevLoadingUpRow != loadingUpRow || prevLoadingDownRow != loadingDownRow || prevMessagesStartRow != messagesStartRow || prevMessagesEndRow != messagesEndRow || prevHintRow != hintRow || prevUserInfoRow != userInfoRow || prevUserPhotoTimeRow != userPhotoTimeRow || prevUserNameTimeRow != userNameTimeRow ) { notifyDataSetChanged(false); } } private void updateRowsInternal() { rowCount = 0; final ArrayList messages; if (isFrozen) { messages = frozenMessages; } else if (isFiltered) { messages = filteredMessages; } else { messages = ChatActivity.this.messages; } if (chatMode == MODE_SAVED && isInsideContainer) { hintRow = rowCount++; } else { hintRow = -5; } botInfoRow = -5; userInfoRow = -5; userPhotoTimeRow = -5; userNameTimeRow = -5; freeSpaceRow = -5; if (UserObject.isBotForum(currentUser)) { // freeSpaceRow = rowCount++; } if (!messages.isEmpty()) { if (!isFiltered && (!forwardEndReached[0] || mergeDialogId != 0 && !forwardEndReached[1]) && !hideForwardEndReached) { loadingDownRow = rowCount++; } else { loadingDownRow = -5; } messagesStartRow = rowCount; rowCount += messages.size(); messagesEndRow = rowCount; if (currentUser != null && !UserObject.isBot(currentUser) && !UserObject.isReplyUser(currentUser) && !UserInfoCell.isEmpty(getMessagesController().getPeerSettings(currentUser.id)) && !MessagesController.isSupportUser(currentUser) && chatMode == MODE_DEFAULT && endReached[0]) { final TLRPC.PeerSettings peerSettings = getMessagesController().getPeerSettings(currentUser.id); if (peerSettings.name_change_date != 0 && peerSettings.photo_change_date != 0) { if (peerSettings.name_change_date < peerSettings.photo_change_date) { userNameTimeRow = rowCount++; userPhotoTimeRow = rowCount++; } else { userPhotoTimeRow = rowCount++; userNameTimeRow = rowCount++; } } else { if (peerSettings.name_change_date != 0) { userNameTimeRow = rowCount++; } if (peerSettings.photo_change_date != 0) { userPhotoTimeRow = rowCount++; } } userInfoRow = rowCount++; } else if ((UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && chatMode == MODE_DEFAULT) && endReached[0]) { botInfoRow = rowCount++; } if (chatMode == MODE_QUICK_REPLIES && !QuickRepliesController.isSpecial(quickReplyShortcut)) { hintRow = rowCount++; } if (isFiltered ? !filteredEndReached : (!endReached[0] || mergeDialogId != 0 && !endReached[1]) && !(DISABLE_PROGRESS_VIEW && !AndroidUtilities.isTablet() && !isComments && currentUser == null)) { loadingUpRow = rowCount++; } else { loadingUpRow = -5; } } else { loadingUpRow = -5; loadingDownRow = -5; messagesStartRow = 0; messagesEndRow = 0; if (currentUser != null && !UserObject.isBot(currentUser) && !UserObject.isReplyUser(currentUser) && !UserInfoCell.isEmpty(getMessagesController().getPeerSettings(currentUser.id)) && !MessagesController.isSupportUser(currentUser) && chatMode == MODE_DEFAULT) { userInfoRow = rowCount++; } else if (UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && chatMode == MODE_DEFAULT) { botInfoRow = rowCount++; } } } @Override public int getItemCount() { botInfoEmptyRow = -5; if (isClearingHistory()) { 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 rowCount; } @Override public long getItemId(int position) { if (isClearingHistory()) { if (position == botInfoEmptyRow) { return 1; } } final ArrayList messages; if (isFrozen) { messages = frozenMessages; } else if (isFiltered) { messages = filteredMessages; } else { messages = 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; } else if (position == hintRow) { return 4; } else if (position == userInfoRow) { return 6; } else if (position == userPhotoTimeRow) { return 7; } else if (position == userNameTimeRow) { return 8; } else if (position == freeSpaceRow) { return 9; } return 5; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = null; if (viewType == 0) { ArrayList chatMessagesCache = chatMessageCellsCache.get(currentAccount); if (chatMessagesCache != null && !chatMessagesCache.isEmpty()) { view = chatMessagesCache.get(0); chatMessagesCache.remove(0); } else { view = new ChatMessageCell(mContext, currentAccount, true, sharedResources, themeDelegate); } ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setResourcesProvider(themeDelegate); chatMessageCell.shouldCheckVisibleOnScreen = false; chatMessageCell.setDelegate(new ChatMessageCellDelegate()); chatMessageCell.draftAnimationsPool = botDraftAnimationsPool; 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, String slug, boolean animateConfetti) { if (slug != null) { initGiftProgressDialog(cell); PremiumPreviewGiftLinkBottomSheet.show(slug, progressDialogCurrent); } else { showDialog(new PremiumPreviewBottomSheet(ChatActivity.this, currentAccount, getCurrentUser(), new GiftPremiumBottomSheet.GiftTier(giftOption, null), null, themeDelegate) .setAnimateConfetti(animateConfetti) .setOutboundGift(cell.getMessageObject().isOut())); } } @Override public void didPressReaction(ChatActionCell cell, TLRPC.ReactionCount reaction, boolean longpress, float x, float y) { ChatActivity.this.didPressReaction(cell, reaction, longpress, x, y); } @Override public void forceUpdate(ChatActionCell cell, boolean anchorScroll) { if (cell == null) return; MessageObject messageObject = cell.getMessageObject(); if (messageObject == null) return; messageObject.forceUpdate = true; int top = 0; int position = RecyclerListView.NO_POSITION; if (chatListView != null && chatLayoutManager != null && !chatLayoutManager.hasPendingScrollPosition()) { for (int i = chatListView.getChildCount() - 1; i >= 0; i--) { View v = chatListView.getChildAt(i); final int vposition = chatListView.getChildAdapterPosition(v); if (vposition < 0) continue; if (v instanceof ChatMessageCell) { if (((ChatMessageCell) v).getCurrentMessagesGroup() != null) { continue; } position = vposition; top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { position = vposition; top = getScrollingOffsetForView(v); break; } } } updateMessageAnimatedInternal(messageObject, false); if (anchorScroll && position >= 0) { chatLayoutManager.scrollToPositionWithOffset(position, top); } } @Override public void didOpenPremiumGiftChannel(ChatActionCell cell, String slug, boolean animateConfetti) { initGiftProgressDialog(cell); GiftInfoBottomSheet.show(getBaseFragment(), slug, progressDialogCurrent); } private void initGiftProgressDialog(ChatActionCell cell) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_GIFT; progressDialogLinkSpan = null; cell.getMessageObject().flickerLoading = true; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(() -> { ChatActivity.this.resetProgressDialogLoading(); cell.getMessageObject().flickerLoading = false; cell.invalidate(); }, 250); } } }; } @Override public void needShowEffectOverlay(ChatActionCell cell, TLRPC.Document document, TLRPC.VideoSize videoSize) { emojiAnimationsOverlay.showAnimationForActionCell(cell, document, videoSize); } @Override public void didClickButton(ChatActionCell cell) { if (cell == null) return; MessageObject message = cell.getMessageObject(); if (message == null) return; if (message.type == MessageObject.TYPE_ACTION_WALLPAPER && !cell.getMessageObject().isOutOwner() && cell.getMessageObject().isWallpaperForBoth() && cell.getMessageObject().isCurrentWallpaper()) { AlertDialog d = new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(LocaleController.getString(R.string.RemoveWallpaperTitle)) .setMessage(LocaleController.getString(R.string.RemoveWallpaperMessage)) .setPositiveButton(LocaleController.getString(R.string.Remove), (w, di) -> { ChatThemeController.getInstance(currentAccount).clearWallpaper(dialog_id, true, true); }) .setNegativeButton(LocaleController.getString(R.string.Cancel), null) .create(); showDialog(d); TextView button = (TextView) d.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(getThemedColor(Theme.key_text_RedBold)); } } } @Override public void didClickImage(ChatActionCell cell) { MessageObject message = cell.getMessageObject(); PhotoViewer.getInstance().setParentActivity(ChatActivity.this, themeDelegate); TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, 640); TLRPC.VideoSize videoSize = null; TLRPC.VideoSize emojiMarkup = null; if (cell.getMessageObject().type == MessageObject.TYPE_STORY_MENTION) { getOrCreateStoryViewer().openFor(ChatActivity.this, chatListView, cell); return; } if (cell.getMessageObject().type == MessageObject.TYPE_ACTION_WALLPAPER) { MessagesController messagesController = MessagesController.getInstance(currentAccount); if (cell.showingCancelButton() && message.getId() < 0 && messagesController.uploadingWallpaper != null && TextUtils.equals(message.messageOwner.action.wallpaper.uploadingImage, messagesController.uploadingWallpaper)) { messagesController.cancelUploadWallpaper(); removeMessageObject(message); return; } if (cell.hasButton()) { ThemePreviewActivity.showFor(ChatActivity.this, message); } else { showChatThemeBottomSheet(); } return; } if (message.messageOwner.action.photo.video_sizes != null && !message.messageOwner.action.photo.video_sizes.isEmpty()) { videoSize = FileLoader.getClosestVideoSizeWithSize(message.messageOwner.action.photo.video_sizes, 1000); emojiMarkup = FileLoader.getEmojiMarkup(message.messageOwner.action.photo.video_sizes); } if (cell.getMessageObject().type == MessageObject.TYPE_SUGGEST_PHOTO && !message.isOutOwner()) { if (message.settingAvatar) { return; } if (emojiMarkup != null) { PhotoUtilities.showAvatartConstructorForUpdateUserPhoto(ChatActivity.this, emojiMarkup); return; } final ArrayList photos = new ArrayList<>(); ImageLocation.getForPhoto(videoSize, message.messageOwner.action.photo); File file = videoSize == null ? getFileLoader().getPathToAttach(message.messageOwner.action.photo) : getFileLoader().getPathToAttach(videoSize); File file2 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), file.getName()); if (!file.exists()) { if (file2.exists()) { file = file2; } else { //TODO photo not downloaded yet return; } } final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); entry.caption = chatActivityEnterView.getFieldText(); entry.isVideo = videoSize != null; photos.add(entry); PhotoViewer.getInstance().openPhotoForSelect(photos, 0, PhotoViewer.SELECT_TYPE_AVATAR, false, new PhotoViewer.EmptyPhotoViewerProvider() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview, boolean closing) { return photoViewerProvider.getPlaceForPhoto(message, fileLocation, index, needPreview, false); } @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, int scheduleRepeatPeriod, boolean forceDocument) { message.settingAvatar = true; if (entry.imagePath != null || entry.isVideo) { PhotoUtilities.setImageAsAvatar(entry, ChatActivity.this, () -> { message.settingAvatar = false; }); } else { TLRPC.TL_photos_updateProfilePhoto req = new TLRPC.TL_photos_updateProfilePhoto(); req.id = new TLRPC.TL_inputPhoto(); req.id.id = message.messageOwner.action.photo.id; req.id.access_hash = message.messageOwner.action.photo.access_hash; req.id.file_reference = message.messageOwner.action.photo.file_reference; getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_photos_photo) { TLRPC.TL_photos_photo photos_photo = (TLRPC.TL_photos_photo) response; getMessagesController().putUsers(photos_photo.users, false); TLRPC.User user = getMessagesController().getUser(getUserConfig().clientUserId); if (photos_photo.photo instanceof TLRPC.TL_photo) { if (user != null) { PhotoUtilities.applyPhotoToUser(message.messageOwner.action.photo, user, false); getUserConfig().setCurrentUser(user); getUserConfig().saveConfig(true); CharSequence title = AndroidUtilities.replaceTags(LocaleController.getString(R.string.ApplyAvatarHintTitle)); CharSequence subtitle = AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.ApplyAvatarHint), () -> { Bundle args = new Bundle(); args.putLong("user_id", UserConfig.getInstance(currentAccount).clientUserId); presentFragment(new ProfileActivity(args)); }); BulletinFactory.of(ChatActivity.this).createUsersBulletin(Collections.singletonList(user), title, subtitle, null).show(); } } } message.settingAvatar = false; })); } } }, null); if (entry.isVideo) { PhotoViewer.getInstance().setTitle(LocaleController.getString(R.string.SuggestedVideo)); } else { PhotoViewer.getInstance().setTitle(LocaleController.getString(R.string.SuggestedPhoto)); } ImageUpdater.AvatarFor avatarFor = new ImageUpdater.AvatarFor(getUserConfig().getCurrentUser(), ImageUpdater.TYPE_SET_PHOTO_FOR_USER); avatarFor.isVideo = videoSize != null; avatarFor.fromObject = getMessagesController().getUser(dialog_id); PhotoViewer.getInstance().setAvatarFor(avatarFor); } else if (videoSize != null) { ImageLocation imageLocation = ImageLocation.getForPhoto(videoSize, message.messageOwner.action.photo); PhotoViewer.getInstance().openPhoto(videoSize.location, imageLocation, photoViewerProvider); if (cell.getMessageObject().type == MessageObject.TYPE_SUGGEST_PHOTO) { PhotoViewer.getInstance().setTitle(LocaleController.getString(R.string.SuggestedVideo)); } } else if (photoSize != null) { ImageLocation imageLocation = ImageLocation.getForPhoto(photoSize, message.messageOwner.action.photo); PhotoViewer.getInstance().openPhoto(photoSize.location, imageLocation, photoViewerProvider); if (cell.getMessageObject().type == MessageObject.TYPE_SUGGEST_PHOTO) { PhotoViewer.getInstance().setTitle(LocaleController.getString(R.string.SuggestedPhoto)); } } else { PhotoViewer.getInstance().openPhoto(message, null, 0, 0, 0, photoViewerProvider); } } @Override public BaseFragment getBaseFragment() { return ChatActivity.this; } @Override public long getTopicId() { return ChatActivity.this.getTopicId(); } @Override public boolean didLongPress(ChatActionCell cell, float x, float y) { if (inPreviewMode) { return false; } return createMenu(cell, false, false, x, y, true); } @Override public void onTopicClick(ChatActionCell cell) { if (cell == null) return; final MessageObject msg = cell.getMessageObject(); if (msg == null) return; if (topicsTabs == null) return; topicsTabs.selectTopic(msg.getMonoForumTopicId(), true); } @Override public void needOpenUserProfile(long uid) { openUserProfile(uid); } @Override public void didPressReplyMessage(ChatActionCell cell, int id) { Runnable scroll = () -> { MessageObject messageObject = cell.getMessageObject(); scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0); }; if (chatAdapter.isFiltered) { setFilterMessages(false, true, true); AndroidUtilities.runOnUIThread(scroll, 80); } else { scroll.run(); } } @Override public void didPressTaskLink(ChatActionCell cell, int id, int taskId) { Runnable scroll = () -> { MessageObject messageObject = cell.getMessageObject(); scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, taskId, null); }; if (chatAdapter.isFiltered) { setFilterMessages(false, true, true); AndroidUtilities.runOnUIThread(scroll, 80); } else { scroll.run(); } } @Override public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { if (getParentActivity() == null || bottomChannelButtonsLayout.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) && !(button instanceof TLRPC.TL_keyboardButtonRequestPeer) && !(button instanceof TLRPC.TL_keyboardButtonCopy)) { return; } chatActivityEnterView.didPressedBotButton(button, messageObject, messageObject); } @Override public boolean canDrawOutboundsContent() { return false; } }); } 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, null, null, false, false); } }); } else if (viewType == 4) { view = new ChatLoadingCell(mContext, contentView, themeDelegate); } else if (viewType == 6) { view = new UserInfoCell(mContext, currentAccount, themeDelegate); } else if (viewType == 7) { view = new ChatActionCell(mContext, false, themeDelegate); } else if (viewType == 8) { view = new View(mContext) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); } }; view.setBackgroundColor(0xFF00FF00); } 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(R.string.RepliesChatInfo)); } else if (currentUser != null && currentUser.id == UserObject.VERIFY) { helpView.setText(false, LocaleController.getString(R.string.VerifyChatInfo)); } else { TL_bots.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); } updateBotHelpCellClick(helpView); } else if (position == freeSpaceRow) { } else if (position == userInfoRow) { UserInfoCell infoView = (UserInfoCell) holder.itemView; final long dialogId = currentEncryptedChat != null ? currentEncryptedChat.user_id : getDialogId(); infoView.set(dialogId, getMessagesController().getPeerSettings(dialogId)); } else if (position == loadingDownRow || position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; loadingCell.setProgressVisible(loadsCount > 1); } else if (position == userNameTimeRow) { final TLRPC.PeerSettings settings = getMessagesController().getPeerSettings(getDialogId()); if (settings == null) return; ChatActionCell actionCell = (ChatActionCell) holder.itemView; actionCell.setCustomText(LocaleController.formatString(R.string.ContactInfoUserUpdatedName, LocaleController.formatRelativeDate(getConnectionsManager().getCurrentTime() - settings.name_change_date))); } else if (position == userPhotoTimeRow) { final TLRPC.PeerSettings settings = getMessagesController().getPeerSettings(getDialogId()); if (settings == null) return; ChatActionCell actionCell = (ChatActionCell) holder.itemView; actionCell.setCustomText(LocaleController.formatString(R.string.ContactInfoUserUpdatedPhoto, LocaleController.formatRelativeDate(getConnectionsManager().getCurrentTime() - settings.photo_change_date))); } else if (position == hintRow) { ChatActionCell actionCell = (ChatActionCell) holder.itemView; createHint2MessageObject(); actionCell.setMessageObject(hint2MessageObject); if (chatMode == MODE_SAVED) { actionCell.setCustomText(LocaleController.getString(R.string.SavedMessagesProfileHint)); } else if (chatMode == MODE_QUICK_REPLIES) { actionCell.setCustomText(LocaleController.getString(R.string.BusinessRepliesHint)); } actionCell.setAlpha(1.0f); actionCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } else if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { messages = frozenMessages; } else if (isFiltered) { messages = filteredMessages; } else { messages = 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) || (chatMode == MODE_SEARCH); messageCell.setSponsoredMessageVisible(true, false); messageCell.isBotForum = UserObject.isBotForum(currentUser); messageCell.isReportChat = isReport(); messageCell.isSavedChat = chatMode == MODE_SAVED; messageCell.isSavedPreviewChat = chatMode == MODE_SAVED && isInsideContainer; messageCell.isBot = currentUser != null && currentUser.bot; messageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; messageCell.isForum = ChatObject.isForum(currentChat); messageCell.isMonoForum = ChatObject.isMonoForum(currentChat); messageCell.isForumGeneral = ChatObject.isForum(currentChat) && isTopic && getTopicId() == 1; messageCell.isThreadChat = (threadMessageId != 0 || messageCell.isForum && isTopic) && !messageCell.isMonoForum; 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; if (chatMode == MODE_SEARCH && searchType == SEARCH_MY_MESSAGES) { messageCell.isRepliesChat = UserObject.isReplyUser(message.getDialogId()); } else { messageCell.isRepliesChat = UserObject.isReplyUser(currentUser); } messageCell.isPinnedChat = chatMode == MODE_PINNED; messageCell.isAllChats = isAllChats(); messageCell.isSideMenued = isSideMenued(); messageCell.isSideMenuEnabled = isSideMenuEnabled(); messageCell.sideMenuAlpha = getSideMenuAlpha(); messageCell.sideMenuWidth = getSideMenuWidth(); boolean pinnedBottom = false; boolean pinnedBottomByGroup = false; boolean pinnedTop = false; boolean pinnedTopByGroup = false; if (message.isSponsored()) { AndroidUtilities.doOnPreDraw(messageCell, () -> { }); } int prevPosition; int prevPrevPosition = position + 2;; int nextPosition; if (groupedMessages != null) { MessageObject.GroupedMessagePosition pos = groupedMessages.getPosition(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) { if (groupedMessages.reversed) { prevPosition = position - groupedMessages.posArray.size() + groupedMessages.posArray.indexOf(pos); } else { prevPosition = position + groupedMessages.posArray.indexOf(pos) + 1; } } else { pinnedTop = true; pinnedTopByGroup = true; prevPosition = -100; } if ((pos.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { if (groupedMessages.reversed) { nextPosition = position + groupedMessages.posArray.indexOf(pos) + 1; } else { 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); int prevPrevType = getItemViewType(prevPrevPosition); 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 (nextMessage.messageOwner != null && nextMessage.messageOwner.paid_message_stars > 0) { pinnedBottom = false; } else 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(); } } else if (chatMode == MODE_SEARCH) { pinnedBottom = MessageObject.getPeerId(message.messageOwner.peer_id) == MessageObject.getPeerId(nextMessage.messageOwner.peer_id); } } } final boolean firstInChat; if (prevPosition - messagesStartRow >= 0 && prevPosition - messagesStartRow < messages.size()) { MessageObject prevMessage = messages.get(prevPosition - messagesStartRow); if (prevMessage != null && prevMessage.isDateObject) { prevMessage = null; if (prevPosition + 1 - messagesStartRow >= 0 && prevPosition + 1 - messagesStartRow < messages.size()) { prevMessage = messages.get(prevPosition + 1 - messagesStartRow); } } firstInChat = prevMessage == null || prevMessage.getTopicId() != message.getTopicId(); } else { firstInChat = true; } final boolean lastInChatList = position == messagesStartRow; 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; } if (pinnedTop && isForumInViewAsMessagesMode()) { long topicId = message.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, message.messageOwner, true) : message.replyToForumTopic.id; long prevTopicId = prevMessage.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, prevMessage.messageOwner, true) : prevMessage.replyToForumTopic.id; if (topicId != prevTopicId) { pinnedTop = false; } } } else if (UserObject.isUserSelf(currentUser) || UserObject.isReplyUser(currentUser)) { if (message.isPrivateForward() || prevMessage.isPrivateForward()) { pinnedTop = false; } else { pinnedTop = prevMessage.getSenderId() == message.getSenderId(); } } else if (chatMode == MODE_SEARCH) { pinnedTop = MessageObject.getPeerId(message.messageOwner.peer_id) == MessageObject.getPeerId(prevMessage.messageOwner.peer_id); } } } 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; } } if (!pinnedTopByGroup && message.messageOwner != null && message.messageOwner.paid_message_stars > 0) { pinnedTop = false; } message.updateTranslation(false); if (groupedMessages != null) { for (int i = 0; i < groupedMessages.messages.size(); ++i) { groupedMessages.messages.get(i).updateTranslation(false); } } if (reversed) { if (groupedMessages != null) { pinnedTop = false; pinnedBottom = false; } else { boolean wasPinnedTop = pinnedTop; pinnedTop = pinnedBottom; pinnedBottom = wasPinnedTop; } } messageCell.setShowTopic(true); messageCell.setMessageObject(message, groupedMessages, pinnedBottom, pinnedTop, firstInChat, lastInChatList); messageCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && message.getId() == highlightMessageId); if (messageCell.isHighlighted() && highlightMessageQuote != null) { final long now = System.currentTimeMillis(); messageCell.setHighlightedText(highlightMessageQuote, true, highlightMessageQuoteOffset, highlightMessageQuoteFirst || now - highlightMessageQuoteFirstTime < 200); if (highlightMessageQuoteFirst) { highlightMessageQuoteFirstTime = now; } highlightMessageQuoteFirst = false; } else if (messageCell.isHighlighted() && highlightTaskId != null) { messageCell.setHighlightedTask(highlightTaskId); } else if (chatMode == MODE_SEARCH && searchingHashtag != null && searchingQuery != null) { messageCell.setHighlightedText(searchingQuery); } 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 != null && instantCameraView.getTextureView() != null) { applyAnimation = true; if (closeInstantCameraAnimation != null) { AndroidUtilities.cancelRunOnUIThread(closeInstantCameraAnimation); closeInstantCameraAnimation = null; } 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.getPaddingTop() - messageCell.getTranslationY(); final InstantCameraView.InstantViewCameraContainer cameraContainer = instantCameraView.getCameraContainer(); cameraContainer.setPivotX(0.0f); cameraContainer.setPivotY(0.0f); AnimatorSet animatorSet = new AnimatorSet(); cameraContainer.setImageReceiver(imageReceiver); 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.getButtonsLayout(), 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(300); if (instantCameraView != null) { 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) { if (instantCameraView != null) { instantCameraView.setIsMessageTransition(false); instantCameraView.hideCamera(true); instantCameraView.setVisibility(View.INVISIBLE); } } }); animatorSet.start(); } }); allAnimators.start(); return true; } }); } else if (message.isAnyKindOfSticker() && !message.isAnimatedEmojiStickers() || message.sendAnimationData != null && message.sendAnimationData.fromPreview) { applyAnimation = true; if (message.sendAnimationData.fromPreview && chatActivityEnterView != null && chatActivityEnterView.messageSendPreview != null) { final int actionBarBottom = actionBar.getVisibility() == View.VISIBLE ? (int) actionBar.getTranslationY() + actionBar.getMeasuredHeight() + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0) + (hashtagSearchTabs != null ? hashtagSearchTabs.getCurrentHeight() : 0) + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0) : 0; final float clipTop = actionBarBottom + paddingTopHeight; final float clipBottom = fragmentView == null ? 0 : fragmentView.getHeight(); chatActivityEnterView.messageSendPreview.dismissInto(messageCell, clipTop, clipBottom); chatActivityEnterView.messageSendPreview = null; } else { 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; if (sendAnimationData.fromPreview) { scale = 1f; } else { 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; } }; AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(sendAnimationData, param1, scale, 1.0f), ObjectAnimator.ofFloat(sendAnimationData, new AnimationProperties.FloatProperty("progress") { @Override public void setValue(MessageObject.SendAnimationData object, float value) { object.progress = value; if (fragmentView != null) { fragmentView.invalidate(); } } @Override public Float get(MessageObject.SendAnimationData object) { return object.progress; } }, 0, 1) ); ObjectAnimator o = ObjectAnimator.ofFloat(sendAnimationData, param2, sendAnimationData.x, position[0] + (sendAnimationData.fromPreview ? 0 : imageReceiver.getCenterX())); allAnimators.playTogether(o, animatorSet); allAnimators.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); allAnimators.setDuration(460); 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); } } if (messageCell.makeVisibleAfterChange) { messageCell.makeVisibleAfterChange = false; messageCell.setVisibility(View.VISIBLE); } showBotMessageHint(messageCell, false); } else if (view instanceof ChatActionCell) { final boolean firstInChat; if (message != null && message.isDateObject) { firstInChat = false; } else if (position + 1 - messagesStartRow >= 0 && position + 1 - messagesStartRow < messages.size()) { MessageObject prevMessage = messages.get(position + 1 - messagesStartRow); if (prevMessage != null && prevMessage.isDateObject) { prevMessage = null; if (position + 2 - messagesStartRow >= 0 && position + 2 - messagesStartRow < messages.size()) { prevMessage = messages.get(position + 2 - messagesStartRow); } } firstInChat = prevMessage == null || message != null && prevMessage.getTopicId() != message.getTopicId(); } else { firstInChat = false; } ChatActionCell actionCell = (ChatActionCell) view; actionCell.isAllChats = isAllChats(); actionCell.isSideMenued = isSideMenued(); actionCell.isSideMenuEnabled = isSideMenuEnabled(); actionCell.sideMenuAlpha = getSideMenuAlpha(); actionCell.sideMenuWidth = getSideMenuWidth(); actionCell.isForum = ChatObject.isForum(currentChat); actionCell.isMonoForum = ChatObject.isMonoForum(currentChat); final boolean force = actionCell.firstInChat != firstInChat; actionCell.firstInChat = firstInChat; actionCell.setMessageObject(message, force); actionCell.setAlpha(1.0f); actionCell.setShowTopic(true); actionCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); } else if (view instanceof ChatUnreadCell) { ChatUnreadCell unreadCell = (ChatUnreadCell) view; unreadCell.setText(LocaleController.getString(R.string.UnreadMessages)); unreadCell.getTextView().setTranslationX(getSideMenuWidth() / 2f); if (createUnreadMessageAfterId != 0) { createUnreadMessageAfterId = 0; } } } } @Override public int getItemViewType(int position) { if (isClearingHistory()) { if (position == botInfoEmptyRow) { return 3; } } if (position == hintRow) { return 1; } if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { messages = frozenMessages; } else if (isFiltered) { messages = filteredMessages; } else { messages = ChatActivity.this.messages; } return messages.get(position - messagesStartRow).contentType; } else if (position == botInfoRow) { return 3; } else if (position == userInfoRow) { return 6; } else if (position == userNameTimeRow || position == userPhotoTimeRow) { return 7; } else if (position == freeSpaceRow) { return 8; } return 4; } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { if (holder.itemView instanceof ChatMessageCell || holder.itemView instanceof ChatActionCell) { invalidateMessagesVisiblePart(); } if (holder.itemView instanceof ChatMessageCell) { final ChatMessageCell messageCell = (ChatMessageCell) holder.itemView; final MessageObject message = messageCell.getMessageObject(); messageCell.isAllChats = isAllChats(); messageCell.isSideMenued = isSideMenued(); messageCell.isSideMenuEnabled = isSideMenuEnabled(); messageCell.sideMenuAlpha = getSideMenuAlpha(); messageCell.sideMenuWidth = getSideMenuWidth(); 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); } } } if (message.updateTranslation(false)) { messageCell.setMessageObject(message, messageCell.getCurrentMessagesGroup(), messageCell.isPinnedBottom(), messageCell.isPinnedTop(), messageCell.isFirstInChat(), messageCell.isLastInChatList()); } else { MessageObject.GroupedMessages group = messageCell.getCurrentMessagesGroup(); if (group != null) { for (int i = 0; i < group.messages.size(); ++i) { group.messages.get(i).updateTranslation(); } } } boolean selected = false; boolean disableSelection = false; if (actionBar.isActionModeShowed() || isReport()) { highlightMessageQuoteFirst = false; highlightMessageQuoteFirstTime = 0; highlightMessageQuote = null; 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 (chatMode == MODE_SEARCH && searchingHashtag != null && searchingQuery != null) { messageCell.setHighlightedText(searchingQuery); } else 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() != null && messageCell.getMessageObject().getId() == highlightMessageId || messageCell.getCurrentMessagesGroup() != null && messageCell.getCurrentMessagesGroup().contains(highlightMessageId))); if (messageCell.isHighlighted() && highlightMessageQuote != null) { final long now = System.currentTimeMillis(); if (!messageCell.setHighlightedText(highlightMessageQuote, true, highlightMessageQuoteOffset, highlightMessageQuoteFirst || now - highlightMessageQuoteFirstTime < 200) && showNoQuoteAlert) { showNoQuoteFound(); } showNoQuoteAlert = false; if (highlightMessageQuoteFirst) { highlightMessageQuoteFirstTime = now; } highlightMessageQuoteFirst = false; } else if (messageCell.isHighlighted() && highlightTaskId != null) { messageCell.setHighlightedTask(highlightTaskId); } if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } } } else if (holder.itemView instanceof ChatActionCell) { final ChatActionCell actionCell = (ChatActionCell) holder.itemView; actionCell.isAllChats = isAllChats(); actionCell.isSideMenued = isSideMenued(); actionCell.isSideMenuEnabled = isSideMenuEnabled(); actionCell.sideMenuAlpha = getSideMenuAlpha(); actionCell.sideMenuWidth = getSideMenuWidth(); } else if (holder.itemView instanceof ChatUnreadCell) { ((ChatUnreadCell) holder.itemView).getTextView().setTranslationX(getSideMenuWidth() / 2f); } int position = holder.getAdapterPosition(); if (position >= messagesStartRow && position < messagesEndRow) { final ArrayList messages; if (isFrozen) { messages = frozenMessages; } else if (isFiltered) { messages = filteredMessages; } else { messages = 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 { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); } 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 || isFiltered) { 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 = getScrollingOffsetForView(child); } 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, boolean replace) { 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(), cell.isFirstInChat(), cell.isLastInChatList()); return cell; } } } } final ArrayList messages; if (isFrozen) { messages = frozenMessages; } else if (isFiltered) { messages = filteredMessages; } else { messages = ChatActivity.this.messages; } int index = messages.indexOf(messageObject); if (index == -1) { return null; } if (replace) { messageObject.stableId = lastStableId++; notifyDataSetChanged(true); } else { updateRowAtPosition(messagesStartRow + index); } 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); } boolean hideSkeletons = false; for (int i = messages.size() - 1; i >= 0; i--) { MessageObject message = messages.get(i); if (message.isDateObject) { continue; } if (message.messageOwner != null && (message.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate || message.messageOwner.action instanceof TLRPC.TL_messageActionChannelCreate)) { hideSkeletons = true; } break; } if ((endReached[0] && (mergeDialogId == 0 || endReached[1])) || hideSkeletons) { checkDispatchHideSkeletons(fragmentBeginToShow); } } @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); } } public void notifyItemRemoved(int position, boolean thanos) { if (BuildVars.LOGS_ENABLED) { FileLog.d("notify item removed " + position + (thanos ? " with thanos effect" : "")); } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { chatListView.setItemAnimator(chatListItemAnimator); } if (thanos && chatListItemAnimator != null && chatListView.getItemAnimator() == chatListItemAnimator) { chatListItemAnimator.prepareThanos(chatListView.findViewHolderForAdapterPosition(position)); } 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; } } boolean searchWas; private class SearchItemListener extends ActionBarMenuItem.ActionBarMenuItemSearchListener { @Override public boolean canCollapseSearch() { if (hashtagHistoryView.isShowing()) { return true; } if (searchingHashtag != null && hashtagSearchTabs != null) { ChatActivity currentChatActivity = ChatActivity.this; View currentPage = searchViewPager.getCurrentView(); if (currentPage instanceof ChatActivityContainer) { currentChatActivity = ((ChatActivityContainer) currentPage).chatActivity; } if (currentChatActivity.messagesSearchListContainer.getTag() == null) { currentChatActivity.showMessagesSearchListView(true); return false; } else if (hashtagSearchTabs.tabs.getCurrentPosition() != defaultSearchPage) { hashtagSearchTabs.tabs.scrollToTab(defaultSearchPage, defaultSearchPage); return false; } } else { if (messagesSearchListContainer.getTag() != null) { showMessagesSearchListView(false); return false; } } return true; } @Override public void onSearchFilterCleared(FiltersView.MediaFilterData filterData) { super.onSearchFilterCleared(filterData); if (actionBarSearchTags != null) { actionBarSearchTags.clear(); } searchingReaction = null; updateSearchUpDownButtonVisibility(true); updatePagedownButtonVisibility(true); setFilterMessages(false); } @Override public void onSearchCollapse() { searching = false; updatePagedownButtonVisibility(true); updateSearchUpDownButtonVisibility(true); if (searchCalendarButton != null) { 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); checkUi_botMenuPosition(); searchingUserMessages = null; searchingChatMessages = null; searchingHashtag = null; searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString(R.string.SavedTagSearchHint) : LocaleController.getString(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); checkEditTextItemMenu(); } 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.canSendPlain(currentChat))) { if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } 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 (searchViewPager != null) { if (hashtagSearchTabs.tabs.getCurrentPosition() != 0) { hashtagSearchTabs.tabs.scrollToTab(0, 0); requestClearSearchPages = true; } else { searchViewPager.clearViews(); } } if (chatMode == MODE_SAVED || chatMode == MODE_SUGGESTIONS || threadMessageId == 0 && !UserObject.isReplyUser(currentUser) || threadMessageObject != null && threadMessageObject.getRepliesCount() < 10) { searchItem.setVisibility(View.GONE); } searchItemVisible = false; getMediaDataController().clearFoundMessageObjects(); if (searchType == SEARCH_CHANNEL_POSTS) { HashtagSearchController.getInstance(currentAccount).clearSearchResults(SEARCH_CHANNEL_POSTS); } else { HashtagSearchController.getInstance(currentAccount).clearSearchResults(); } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } removeSelectedMessageHighlight(); updateBottomOverlay(); updatePinnedMessageView(true); updateVisibleRows(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(searchAnimationProgress, 0f); valueAnimator.addUpdateListener(valueAnimator1 -> setSearchAnimationProgress((float) valueAnimator1.getAnimatedValue())); valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); valueAnimator.setDuration(320); valueAnimator.start(); messagesSearchListContainer.setAlpha(0.0f); messagesSearchListContainer.setVisibility(View.GONE); messagesSearchListContainer.setTag(null); updateSearchListEmptyView(); searchingReaction = null; updateSearchUpDownButtonVisibility(true); updatePagedownButtonVisibility(true); if (actionBarSearchTags != null) { actionBarSearchTags.clear(); actionBarSearchTags.show(false); } if (hashtagSearchTabs != null) { hashtagSearchTabs.show(false); } setFilterMessages(false); hashtagHistoryView.show(false); } @Override public void onSearchExpand() { searching = true; updatePagedownButtonVisibility(true); updateSearchUpDownButtonVisibility(true); if ((threadMessageId != 0 && chatMode != MODE_SAVED || UserObject.isReplyUser(currentUser)) && !preventReopenSearchWithText) { openSearchWithText(null); } if (openSearchKeyboard) { saveKeyboardPositionBeforeTransition(); if (!isInsideContainer) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } AndroidUtilities.runOnUIThread(() -> { searchWas = false; searchItem.getSearchField().requestFocus(); AndroidUtilities.showKeyboard(searchItem.getSearchField()); removeKeyboardPositionBeforeTransition(); }, 500); hideSendButtonHints(); } whiteActionBar = searchingHashtag != null || getDialogId() == getUserConfig().getClientUserId(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(searchAnimationProgress, 1f); valueAnimator.addUpdateListener(valueAnimator1 -> setSearchAnimationProgress((float) valueAnimator1.getAnimatedValue())); valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); valueAnimator.setDuration(320); valueAnimator.start(); if (actionBarSearchTags != null) { actionBarSearchTags.show(!isInsideContainer && actionBarSearchTags.hasFilters() && searchingHashtag == null); } if (searchingHashtag != null && hashtagSearchTabs != null && hashtagSearchTabs.tabs.getCurrentPosition() != defaultSearchPage) { hashtagSearchTabs.tabs.scrollToTab(defaultSearchPage, defaultSearchPage); } } private float searchAnimationProgress; private boolean whiteActionBar; public void setSearchAnimationProgress(float progress) { searchAnimationProgress = progress; if (whiteActionBar) { int color1 = getThemedColor(Theme.key_actionBarDefaultIcon); actionBar.setItemsColor(ColorUtils.blendARGB(color1, getThemedColor(Theme.key_actionBarActionModeDefaultIcon), searchAnimationProgress), false); actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), true); color1 = getThemedColor(Theme.key_actionBarDefaultSelector); int color2 = getThemedColor(Theme.key_actionBarActionModeDefaultSelector); actionBar.setItemsBackgroundColor(ColorUtils.blendARGB(color1, color2, searchAnimationProgress), false); actionBar.setBackgroundColor(ColorUtils.blendARGB(getThemedColor(Theme.key_actionBarDefault), getThemedColor(Theme.key_actionBarActionModeDefault), searchAnimationProgress)); actionBar.setSearchTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearch), getThemedColor(Theme.key_windowBackgroundWhiteBlackText), searchAnimationProgress), false); actionBar.setSearchTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearchPlaceholder), getThemedColor(Theme.key_windowBackgroundWhiteGrayText), searchAnimationProgress), true); actionBar.setSearchCursorColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSearch), getThemedColor(Theme.key_windowBackgroundWhiteBlueText), searchAnimationProgress)); if (!isInsideContainer && getParentActivity() != null) { AndroidUtilities.setLightStatusBar(getParentActivity().getWindow(), isLightStatusBar()); } } if (fragmentView != null) { fragmentView.invalidate(); } } @Override public void onSearchPressed(EditText editText) { searchWas = true; updateSearchButtons(0, 0, -1); boolean hashtags = false; boolean channelHashtags = false; searchingQuery = editText != null ? editText.getText().toString() : searchingQuery; if (!TextUtils.isEmpty(searchingQuery) && (searchingQuery.startsWith("$") || searchingQuery.startsWith("#"))) { hashtags = true; if (searchingQuery.contains("@")) { presentFragment(new HashtagActivity(searchingQuery, resourceProvider)); return; } if (searchingHashtag == null) { searchingHashtag = searchingQuery; whiteActionBar = true; ValueAnimator valueAnimator = ValueAnimator.ofFloat(searchAnimationProgress, 1f); valueAnimator.addUpdateListener(valueAnimator1 -> setSearchAnimationProgress((float) valueAnimator1.getAnimatedValue())); valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); valueAnimator.setDuration(320); valueAnimator.start(); if (actionBarSearchTags != null) { actionBarSearchTags.show(!isInsideContainer && actionBarSearchTags.hasFilters() && searchingHashtag == null); } } searchingHashtag = searchingQuery; checkHashtagStories(true); HashtagSearchController.getInstance(currentAccount).putToHistory(searchingHashtag); hashtagHistoryView.update(); View view = searchViewPager.getCurrentView(); if (searchType == SEARCH_CHANNEL_POSTS) { HashtagSearchController.getInstance(currentAccount).clearSearchResults(SEARCH_CHANNEL_POSTS); } else { HashtagSearchController.getInstance(currentAccount).clearSearchResults(); } if (view instanceof ChatActivityContainer) { ((ChatActivityContainer) view).chatActivity.updateSearchingHashtag(searchingHashtag); } updateSearchListEmptyView(); hashtagSearchEmptyView.showProgress(true); showMessagesSearchListView(true); } else { searchingHashtag = null; if (hashtagSearchTabs != null) { hashtagSearchTabs.show(false); messagesSearchListContainer.setPadding(0, 0, 0, getHashtagTabsHeight()); updateSearchListEmptyView(); } if (hashtagSearchTabs != null && hashtagSearchTabs.tabs.getCurrentPosition() != 0) { hashtagSearchTabs.tabs.scrollToTab(0, 0); } } if (hashtagSearchTabs != null) { hashtagSearchTabs.show(hashtags && !channelHashtags); } if (channelHashtags && searchingHashtag != null && hashtagSearchTabs != null && hashtagSearchTabs.tabs.getCurrentPosition() != defaultSearchPage) { hashtagSearchTabs.tabs.scrollToTab(defaultSearchPage, defaultSearchPage); } getMediaDataController().searchMessagesInChat(searchingQuery, dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); } @Override public void onTextChanged(EditText editText) { if (searchingHashtag == null) { showMessagesSearchListView(false); } createSearchContainer(); 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(R.string.SearchFrom))) { searchUserButton.callOnClick(); } if (searchingHashtag != null) { boolean show = editText.length() == 0; if (show != hashtagHistoryView.isShowing()) { hashtagHistoryView.show(show); updateBottomOverlay(); } } } @Override public boolean canClearCaption() { return searchingHashtag == null; } @Override public void onCaptionCleared() { createSearchContainer(); if (searchingUserMessages != null || searchingChatMessages != null) { if (searchUserButton != null) { searchUserButton.callOnClick(); } } else { if (searchingForUser) { mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchingForUser = false; searchItem.setSearchFieldText("", true); } searchItem.setSearchFieldHint(isSupportedTags() ? LocaleController.getString(R.string.SavedTagSearchHint) : LocaleController.getString(R.string.Search)); searchCalendarButton.setVisibility(View.VISIBLE); if (searchUserButton != null) { searchUserButton.setVisibility(View.VISIBLE); } searchingUserMessages = null; searchingChatMessages = null; } } @Override public boolean forceShowClear() { return searchingForUser; } @Override public boolean showClearForCaption() { return searchingHashtag == null; } } private SearchItemListener searchItemListener; private SearchItemListener getSearchItemListener() { if (searchItemListener == null) { searchItemListener = new SearchItemListener(); } return searchItemListener; } private boolean isSupportedTags() { return getUserConfig().getClientUserId() == getDialogId() && !getMessagesController().getSavedMessagesController().unsupported && getUserConfig().isPremium(); } private ChatMessageCellDelegate chatMessageCellDelegate; private ChatMessageCellDelegate getChatMessageCellDelegate() { if (chatMessageCellDelegate == null) { chatMessageCellDelegate = new ChatMessageCellDelegate(); } return chatMessageCellDelegate; } private class ChatMessageCellDelegate implements ChatMessageCell.ChatMessageCellDelegate { @Override public boolean isReplyOrSelf() { return UserObject.isReplyUser(currentUser) || UserObject.isUserSelf(currentUser); } @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(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, boolean delayed) { 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; } boolean inProgress = !hideCommentLoading && message.getId() == commentLoadingMessageId; if (delayed) { return inProgress && System.currentTimeMillis() - commentLoadingStartedAt > 1000; } return inProgress; } @Override public void didPressEffect(ChatMessageCell cell) { emojiAnimationsOverlay.onTapItem(cell, ChatActivity.this, true); chatListView.cancelClickRunnables(false); } @Override public void didPressFactCheckWhat(ChatMessageCell cell, int cx, int cy) { if (factCheckHint != null) { factCheckHint.hide(); } if (cell == null || getContext() == null) return; MessageObject messageObject = cell.getMessageObject(); if (messageObject == null) return; TLRPC.TL_factCheck factCheck = messageObject.getFactCheck(); if (factCheck == null || factCheck.country == null) return; String country; try { country = new Locale("", factCheck.country).getDisplayCountry(LocaleController.getInstance().getCurrentLocale()); } catch (Exception e) { FileLog.e(e); country = factCheck.country; } factCheckHint = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM) .setMultilineText(true) .setTextAlign(Layout.Alignment.ALIGN_NORMAL) .setDuration(-1) .setHideByTouch(true) .useScale(true) .setRounding(12); final HintView2 thisHint = factCheckHint; thisHint.setOnHiddenListener(() -> { contentView.removeView(thisHint); if (thisHint == factCheckHint) { factCheckHint = null; } }); factCheckHint.setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.FactCheckToast, country))); contentView.addView(factCheckHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 520, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); contentView.post(() -> { if (factCheckHint == null) { return; } int[] loc = new int[2]; cell.getLocationInWindow(loc); factCheckHint.setTranslationY(loc[1] - factCheckHint.getTop() - dp(520) + cy); factCheckHint.setJointPx(0, -dp(16) + loc[0] + cx); factCheckHint.show(); }); } @Override public void didPressFactCheck(ChatMessageCell cell) { if (cell == null) return; MessageObject messageObject = cell.getPrimaryMessageObject(); if (messageObject == null) return; messageObject.factCheckExpanded = !messageObject.factCheckExpanded; messageObject.forceUpdate = true; int top = 0; int position = RecyclerListView.NO_POSITION; if (chatListView != null && chatLayoutManager != null && !chatLayoutManager.hasPendingScrollPosition()) { for (int i = chatListView.getChildCount() - 1; i >= 0; i--) { View v = chatListView.getChildAt(i); final int vposition = chatListView.getChildAdapterPosition(v); if (vposition < 0) continue; if (v instanceof ChatMessageCell) { if (((ChatMessageCell) v).getCurrentMessagesGroup() != null) { continue; } position = vposition; top = getScrollingOffsetForView(v); break; } else if (v instanceof ChatActionCell) { position = vposition; top = getScrollingOffsetForView(v); break; } } } updateMessageAnimatedInternal(messageObject, false); if (factCheckHint != null) { factCheckHint.hide(); } if (position >= 0 && cell.getCurrentMessagesGroup() == null) { chatLayoutManager.scrollToPositionWithOffset(position, top); } } @Override public void forceUpdate(ChatMessageCell cell, boolean anchorScroll) { forceUpdate(cell, anchorScroll, false); } public void forceUpdate(ChatMessageCell cell, boolean anchorScroll, boolean scrollByTop) { if (cell == null) return; MessageObject messageObject = cell.getPrimaryMessageObject(); if (messageObject == null) return; messageObject.forceUpdate = true; int top = 0, bottom = 0; int position = RecyclerListView.NO_POSITION; if (chatListView != null && chatLayoutManager != null && !chatLayoutManager.hasPendingScrollPosition()) { for (int i = chatListView.getChildCount() - 1; i >= 0; i--) { View v = chatListView.getChildAt(i); final int vposition = chatListView.getChildAdapterPosition(v); if (vposition < 0) continue; if (v instanceof ChatMessageCell) { if (((ChatMessageCell) v).getCurrentMessagesGroup() != null) { continue; } position = vposition; top = getScrollingOffsetForView(v); bottom = 0; break; } else if (v instanceof ChatActionCell) { position = vposition; top = getScrollingOffsetForView(v); bottom = 0; break; } } } if (anchorScroll && position >= 0 && cell.getCurrentMessagesGroup() == null) { if (scrollByTop) { chatLayoutManager.scrollToPositionWithOffset(chatListView.getChildAdapterPosition(cell), cell.getTop() - (int) chatListViewPaddingTop, false); } else { chatLayoutManager.scrollToPositionWithOffset(position, top); } } updateMessageAnimatedInternal(messageObject, false); } @Override public void didQuickShareStart(ChatMessageCell cell, float x, float y) { if (getParentActivity() == null) { return; } if (quickShareSelectorOverlay == null) { quickShareSelectorOverlay = new QuickShareSelectorOverlayLayout(getContext()); contentView.addView(quickShareSelectorOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP)); } quickShareSelectorOverlay.open(cell); } @Override public void didQuickShareMove(ChatMessageCell cell, float x, float y) { if (quickShareSelectorOverlay != null) { quickShareSelectorOverlay.onTouchMoveEvent(cell, x, y); } } @Override public void didQuickShareEnd(ChatMessageCell cell, float x, float y) { if (quickShareSelectorOverlay == null) { return; } quickShareSelectorOverlay.close(cell, sendMessageFromQuickShare(cell)); } private Bulletin sendMessageFromQuickShare(ChatMessageCell cell) { if (quickShareSelectorOverlay == null) { return null; } final MessageObject messageObject = quickShareSelectorOverlay.getSelectedMessageObject(cell); final long did = quickShareSelectorOverlay.getSelectedDialogId(cell); if (messageObject == null || did == 0) { return null; } if (AlertsCreator.checkSlowMode(getContext(), currentAccount, did, false)) { return null; } 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); } final boolean isSavedMessages = did == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId; final ArrayList finalArrayList = arrayList; Runnable delayedRunnalble = () -> { int result = SendMessagesHelper.getInstance(currentAccount).sendMessage(finalArrayList, did, false, false, true, 0, 0, null, -1, 0, getSendMonoForumPeerId(), getSendMessageSuggestionParams()); AlertsCreator.showSendMediaAlert(result, ChatActivity.this, null); }; if (isSavedMessages) { delayedRunnalble.run(); delayedRunnalble = null; } final Bulletin bulletin = BulletinFactory.createForwardedBulletin(getContext(), ChatActivity.this, null, 1, did, 1, getThemedColor(Theme.key_undo_background), getThemedColor(Theme.key_undo_infoColor), Bulletin.DURATION_PROLONG, null, delayedRunnalble ); return bulletin.allowBlur().show(bulletin.getLayout() instanceof Bulletin.LottieLayoutWithReactions); } @Override public void didPressSideButton(ChatMessageCell cell) { if (getParentActivity() == null) { return; } if (topicsTabs != null && threadMessageId == 0 && (cell.isForum || cell.isMonoForum)) { topicsTabs.selectTopic(cell.getMessageObject().getTopicId(), true); return; } if (getMessagesController().isFrozen()) { AccountFrozenAlert.show(currentAccount); return; } if (chatActivityEnterView != null) { chatActivityEnterView.closeKeyboard(); } MessageObject messageObject = cell.getMessageObject(); if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageObject.getId()); finishFragment(); } else if (chatMode == MODE_SAVED || (chatMode == MODE_SEARCH && searchType == SEARCH_PUBLIC_POSTS) || (UserObject.isReplyUser(currentUser) || UserObject.isUserSelf(currentUser)) && messageObject.messageOwner.fwd_from != null && 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 if (chatMode == MODE_SEARCH && searchType == SEARCH_PUBLIC_POSTS) { openMessageInOriginalDialog(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); } final boolean includeStory = getMessagesController().storiesEnabled() && StoryEntry.canRepostMessage(messageObject); showDialog(new ShareAlert(getContext(), ChatActivity.this, arrayList, null, null, ChatObject.isChannel(currentChat), null, null, false, false, includeStory, null, themeDelegate) { { includeStoryFromMessage = includeStory; } @Override public void dismissInternal() { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); super.dismissInternal(); if (chatActivityEnterView.getVisibility() == View.VISIBLE) { fragmentView.requestLayout(); } } @Override protected void onShareStory(View cell) { StoryRecorder.SourceView sourceView = null; if (cell instanceof ShareDialogCell) { sourceView = StoryRecorder.SourceView.fromShareCell((ShareDialogCell) cell); } final ArrayList messageObjects = new ArrayList<>(); MessageObject.GroupedMessages groupedMessages = messageObject.getGroupId() != 0 ? groupedMessagesMap.get(messageObject.getGroupId()) : null; if (groupedMessages != null) { messageObjects.addAll(groupedMessages.messages); } else { messageObjects.add(messageObject); } StoryRecorder editor = StoryRecorder.getInstance(getParentActivity(), currentAccount); editor.setOnPrepareCloseListener((t, close, sent, did) -> { if (sent) { AndroidUtilities.runOnUIThread(() -> { String chatTitle = ""; if (did < 0) { TLRPC.Chat chat = getMessagesController().getChat(-did); if (chat != null) { chatTitle = chat.title; } } BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.contact_check, AndroidUtilities.replaceTags( TextUtils.isEmpty(chatTitle) ? LocaleController.getString(R.string.RepostedToProfile) : LocaleController.formatString(R.string.RepostedToChannelProfile, chatTitle) )).show(); }); dismiss(); editor.replaceSourceView(null); } else { StoryRecorder.SourceView sourceView2 = null; if (cell instanceof ShareDialogCell && cell.isAttachedToWindow()) { sourceView2 = StoryRecorder.SourceView.fromShareCell((ShareDialogCell) cell); } editor.replaceSourceView(sourceView2); } AndroidUtilities.runOnUIThread(close); }); editor.openRepost(sourceView, StoryEntry.repostMessage(messageObjects)); } @Override protected void onSend(LongSparseArray dids, int count, TLRPC.TL_forumTopic topic, boolean showToast) { createUndoView(); if (undoView == null || !showToast) { return; } if (dids.size() == 1) { if (dids.valueAt(0).id != getUserConfig().getClientUserId() || !BulletinFactory.of(ChatActivity.this).showForwardedBulletinWithTag(dids.valueAt(0).id, count)) { undoView.showWithAction(dids.valueAt(0).id, UndoView.ACTION_FWD_MESSAGES, count, topic, null, null); } } else { undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, count, dids.size(), null, null); } } }); AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); fragmentView.requestLayout(); } } @Override public boolean needPlayMessage(ChatMessageCell cell, MessageObject messageObject, boolean muted) { if (messageObject.isVoiceOnce() || messageObject.isRoundOnce()) { if (secretVoicePlayer != null && secretVoicePlayer.isShown()) return false; try { AudioManager audioManager = (AudioManager) ApplicationLoader.applicationContext.getSystemService(Context.AUDIO_SERVICE); int stream = AudioManager.STREAM_MUSIC; int volume = audioManager.getStreamVolume(stream); if (volume == 0) { audioManager.adjustStreamVolume(stream, volume, AudioManager.FLAG_SHOW_UI); if (!messageObject.isOutOwner()) { BulletinFactory.of(ChatActivity.this).createImageBulletin(R.drawable.tooltip_sound, LocaleController.getString(R.string.VoiceOnceTurnOnSound)).show(true); return false; } } } catch (Exception ignore) {} secretVoicePlayer = new SecretVoicePlayer(getContext()); secretVoicePlayer.setCell( cell, !messageObject.isOutOwner() ? sendSecretMessageRead(messageObject, true) : null, !messageObject.isOutOwner() ? sendSecretMediaDelete(messageObject) : null ); showDialog(secretVoicePlayer); return false; } else if (messageObject.isVoice() || messageObject.isRoundVideo()) { boolean result = MediaController.getInstance().playMessage(messageObject, muted); MediaController.getInstance().setVoiceMessagesPlaylist(result ? createVoiceMessagesPlaylist(messageObject, false) : null, false); return result; } else if (messageObject.isMusic()) { return MediaController.getInstance().setPlaylist(chatAdapter.getMessages(), messageObject, mergeDialogId, !chatAdapter.isFiltered, null); } return false; } @Override public void videoTimerReached() { showNoSoundHint(); } @Override public void didPressTime(ChatMessageCell cell) { createUndoView(); if (undoView == null) { return; } undoView.showWithAction(dialog_id, UndoView.ACTION_IMPORT_INFO, null); } @Override public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY, boolean asForward) { if (chat == null) { return; } if (actionBar.isActionModeShowed() || isReport()) { processRowSelect(cell, true, touchX, touchY); return; } if (!asForward && chat != null && chat.signature_profiles) { MessageObject msg = cell.getMessageObject(); if (msg != null && msg.getDialogId() != UserObject.REPLY_BOT) { long did = DialogObject.getPeerDialogId(msg.messageOwner.from_id); openUserProfile(did); return; } } openChat(cell, chat, postId, asForward); } @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 == MessageObject.TYPE_PHONE_CALL) { if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionConferenceCall) { final TLRPC.TL_messageActionConferenceCall action = (TLRPC.TL_messageActionConferenceCall) messageObject.messageOwner.action; final HashSet participants = new HashSet<>(); participants.add(getDialogId()); for (TLRPC.Peer peer : action.other_participants) { participants.add(DialogObject.getPeerDialogId(peer)); } final TLRPC.TL_inputGroupCallInviteMessage inputGroupCall = new TLRPC.TL_inputGroupCallInviteMessage(); inputGroupCall.msg_id = messageObject.getId(); final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER); final TL_phone.getGroupCall req = new TL_phone.getGroupCall(); req.call = inputGroupCall; req.limit = getMessagesController().conferenceCallSizeLimit; final int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { progressDialog.dismiss(); if (res instanceof TL_phone.groupCall) { final TL_phone.groupCall r = (TL_phone.groupCall) res; getMessagesController().putUsers(r.users, false); getMessagesController().putChats(r.chats, false); if (r.participants.isEmpty()) { showDialog(new CreateGroupCallSheet(getContext(), participants)); } else { VoIPHelper.joinConference(getParentActivity(), currentAccount, inputGroupCall, messageObject.messageOwner.action.video, r.call); } } else if (err != null && "GROUPCALL_INVALID".equalsIgnoreCase(err.text)) { showDialog(new CreateGroupCallSheet(getContext(), participants)); } else if (err != null) { BulletinFactory.of(ChatActivity.this).showForError(err); } })); progressDialog.setOnCancelListener(di -> getConnectionsManager().cancelRequest(reqId, true)); progressDialog.showDelayed(600); } else 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(), false); } } @Override public void didPressSponsoredClose(ChatMessageCell cell) { selectedObject = cell.getMessageObject(); hideAds(); } @Override public void didPressSummarize(ChatMessageCell cell, boolean byReply) { final MessageObject msg = cell.getMessageObject(); msg.messageOwner.summarizedOpen = !msg.messageOwner.summarizedOpen; final boolean opened = msg.messageOwner.summarizedOpen; msg.updateTranslation(true); getMessagesStorage().updateMessageCustomParams(msg.getDialogId(), msg.messageOwner); getMessagesController().getTranslateController().checkTranslation(msg, true); forceUpdate(cell, true, true); } @Override public void didPressSponsoredInfo(ChatMessageCell cell, float x, float y) { createMenu(cell, true, false, x, y, false, false); } @Override public void didPressUserStatus(ChatMessageCell cell, TLRPC.User user, TLRPC.Document document, String giftSlug) { if (cell == null) { return; } if (!TextUtils.isEmpty(giftSlug)) { Browser.openUrl(getContext(), "https://" + getMessagesController().linkPrefix + "/nft/" + giftSlug); return; } PremiumPreviewBottomSheet premiumPreviewBottomSheet = new PremiumPreviewBottomSheet(ChatActivity.this, currentAccount, user, themeDelegate); int[] coords = new int[2]; cell.getLocationOnScreen(coords); premiumPreviewBottomSheet.startEnterFromX = cell.getNameStatusX(); premiumPreviewBottomSheet.startEnterFromY = cell.getNameStatusY(); premiumPreviewBottomSheet.startEnterFromScale = cell.getScaleX(); premiumPreviewBottomSheet.startEnterFromX1 = cell.getLeft(); premiumPreviewBottomSheet.startEnterFromY1 = cell.getTop(); premiumPreviewBottomSheet.startEnterFromView = cell; int colorId = UserObject.getColorId(user); if (colorId < 7) { premiumPreviewBottomSheet.accentColor = getThemedColor(Theme.keys_avatar_nameInMessage[colorId]); } else { final MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; final MessagesController.PeerColor peerColor = peerColors != null ? peerColors.getColor(colorId) : null; premiumPreviewBottomSheet.accentColor = peerColor != null ? peerColor.getColor1() : null; } if (cell.currentNameStatusDrawable != null && cell.currentNameStatusDrawable.getDrawable() instanceof AnimatedEmojiDrawable) { premiumPreviewBottomSheet.startEnterFromScale *= 0.95f; if (document != null) { BackupImageView icon = new BackupImageView(getContext()); String filter = "160_160"; ImageLocation mediaLocation; String mediaFilter; SvgHelper.SvgDrawable thumbDrawable = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if ("video/webm".equals(document.mime_type)) { mediaLocation = ImageLocation.getForDocument(document); mediaFilter = filter + "_" + ImageLoader.AUTOPLAY_FILTER; if (thumbDrawable != null) { thumbDrawable.overrideWidthAndHeight(512, 512); } } else { if (thumbDrawable != null && MessageObject.isAnimatedStickerDocument(document, false)) { thumbDrawable.overrideWidthAndHeight(512, 512); } mediaLocation = ImageLocation.getForDocument(document); mediaFilter = filter; } icon.setLayerNum(7); icon.setRoundRadius(AndroidUtilities.dp(4)); icon.setImage(mediaLocation, mediaFilter, ImageLocation.getForDocument(thumb, document), "140_140", thumbDrawable, document); if (MessageObject.isTextColorEmoji(document)) { icon.setColorFilter(new PorterDuffColorFilter(premiumPreviewBottomSheet.accentColor != null ? premiumPreviewBottomSheet.accentColor : getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN)); premiumPreviewBottomSheet.statusStickerSet = MessageObject.getInputStickerSet(document); } else { premiumPreviewBottomSheet.statusStickerSet = MessageObject.getInputStickerSet(document); } premiumPreviewBottomSheet.overrideTitleIcon = icon; premiumPreviewBottomSheet.isEmojiStatus = true; } } showDialog(premiumPreviewBottomSheet); } @Override public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY, boolean asForward) { if (actionBar.isActionModeShowed() || isReport()) { processRowSelect(cell, true, touchX, touchY); return; } if (cell != null && cell.getMessageObject() != null && cell.getMessageObject().isSponsored()) { didPressInstantButton(cell, 10); return; } openProfile(user, ChatObject.isForum(currentChat) || isThreadChat()); } @Override public boolean didLongPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { if (isAvatarPreviewerEnabled()) { final boolean enableMention = currentChat != null && (bottomChannelButtonsLayout == null || bottomChannelButtonsLayout.getVisibility() != View.VISIBLE) && (bottomOverlay == null || bottomOverlay.getVisibility() != View.VISIBLE); final boolean enableSearchMessages = currentChat != null && (threadMessageId == 0 || isTopic) && (!ChatObject.isChannel(currentChat) || currentChat.megagroup); final AvatarPreviewer.MenuItem[] menuItems = new AvatarPreviewer.MenuItem[2 + (enableMention ? 1 : 0) + (enableSearchMessages ? 1 : 0)]; int a = 0; menuItems[a++] = AvatarPreviewer.MenuItem.OPEN_PROFILE; menuItems[a++] = AvatarPreviewer.MenuItem.SEND_MESSAGE; if (enableMention) { menuItems[a++] = AvatarPreviewer.MenuItem.MENTION; } if (enableSearchMessages) { menuItems[a++] = AvatarPreviewer.MenuItem.SEARCH_MESSAGES; } final TLRPC.UserFull userFull = getMessagesController().getUserFull(user.id); AvatarPreviewer.Data data; if (userFull != null) { data = AvatarPreviewer.Data.of(user, userFull, menuItems); if (!AvatarPreviewer.canPreview(data)) { data = AvatarPreviewer.Data.of(user, classGuid, menuItems); } } else { data = AvatarPreviewer.Data.of(user, classGuid, menuItems); } if (AvatarPreviewer.canPreview(data)) { AvatarPreviewer.getInstance().show((ViewGroup) fragmentView, themeDelegate, data, item -> { switch (item) { case SEND_MESSAGE: openDialog(cell, user); break; case OPEN_PROFILE: openProfile(user); break; case MENTION: appendMention(user); break; case SEARCH_MESSAGES: openSearchWithUser(user); break; } }); return true; } else { ItemOptions.makeOptions(ChatActivity.this, cell) .add(R.drawable.msg_openprofile, getString(R.string.OpenProfile), () -> { openProfile(user); }) .add(R.drawable.msg_discussion, getString(R.string.SendMessage), () -> { openDialog(cell, user); }) .addIf(enableMention, R.drawable.msg_mention, getString(R.string.Mention), () -> { appendMention(user); }) .addIf(enableSearchMessages, R.drawable.msg_search, getString(R.string.AvatarPreviewSearchMessages), () -> { openSearchWithUser(user); }) .setDrawScrim(false) .setGravity(Gravity.LEFT) .forceBottom(true) .translate(0, -dp(48)) .show(); return true; } } return false; } private void appendMention(TLRPC.Chat chat) { 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(' '); } String username = ChatObject.getPublicUsername(chat); if (username != null) { sb.append("@").append(username).append(" "); } else { return; } chatActivityEnterView.setFieldText(sb); AndroidUtilities.runOnUIThread(() -> chatActivityEnterView.openKeyboard(), 200); } } 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(' '); } String username = UserObject.getPublicUsername(user); if (username != null) { sb.append("@").append(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()) { final boolean enableMention = !TextUtils.isEmpty(ChatObject.getPublicUsername(chat)) && currentChat != null && (bottomChannelButtonsLayout == null || bottomChannelButtonsLayout.getVisibility() != View.VISIBLE) && (bottomOverlay == null || bottomOverlay.getVisibility() != View.VISIBLE); final boolean enableSearchMessages = currentChat != null && (threadMessageId == 0 || isTopic) && (!ChatObject.isChannel(currentChat) || currentChat.megagroup); final boolean openChannel = currentChat == null || currentChat.id != chat.id || isThreadChat(); final AvatarPreviewer.MenuItem[] menuItems = new AvatarPreviewer.MenuItem[1 + (openChannel ? 1 : 0) + (enableMention ? 1 : 0) + (enableSearchMessages ? 1 : 0)]; int a = 0; menuItems[a++] = AvatarPreviewer.MenuItem.OPEN_PROFILE; if (openChannel) { menuItems[a++] = chat.broadcast ? AvatarPreviewer.MenuItem.OPEN_CHANNEL : AvatarPreviewer.MenuItem.OPEN_GROUP; } if (enableMention) { menuItems[a++] = AvatarPreviewer.MenuItem.MENTION; } if (enableSearchMessages) { menuItems[a++] = AvatarPreviewer.MenuItem.SEARCH_MESSAGES; } 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, themeDelegate, data, item -> { switch (item) { case OPEN_PROFILE: openProfile(chat); break; case MENTION: appendMention(chat); break; case SEARCH_MESSAGES: openSearchWithChat(chat); break; case OPEN_GROUP: case OPEN_CHANNEL: openChat(cell, chat, 0, false); break; } }); return true; } else { ItemOptions.makeOptions(ChatActivity.this, cell) .add(R.drawable.msg_openprofile, getString(R.string.OpenProfile), () -> { openProfile(chat); }) .addIf(openChannel, chat.broadcast ? R.drawable.msg_channel : R.drawable.msg_discussion, getString(chat.broadcast ? R.string.OpenChannel2 : R.string.OpenGroup2), () -> { openChat(cell, chat, 0, false); }) .addIf(enableMention, R.drawable.msg_mention, getString(R.string.Mention), () -> { appendMention(chat); }) .addIf(enableSearchMessages, R.drawable.msg_search, getString(R.string.AvatarPreviewSearchMessages), () -> { openSearchWithChat(chat); }) .setDrawScrim(false) .setGravity(Gravity.LEFT) .forceBottom(true) .translate(0, -dp(48)) .show(); return true; } } return false; } private void openProfile(TLRPC.User user) { openProfile(user, false); } private void openProfile(TLRPC.User user, boolean expandPhoto) { if (user != null) { if (user.id == UserObject.VERIFY) return; if (user.photo == null || user.photo instanceof TLRPC.TL_userProfilePhotoEmpty) { expandPhoto = false; } Bundle args = new Bundle(); args.putLong("user_id", user.id); args.putBoolean("expandPhoto", expandPhoto); 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) { openProfile(chat, false); } private void openProfile(TLRPC.Chat chat, boolean expandPhoto) { if (chat != null) { Bundle args = new Bundle(); args.putLong("chat_id", chat.id); args.putBoolean("expandPhoto", expandPhoto); 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, boolean asForward) { if (currentChat != null && chat.id == currentChat.id) { if (avatarContainer != null && postId == 0) { avatarContainer.openProfile(false); } else if (cell.getMessageObject() != null) { scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, false, 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); } Browser.Progress progress = asForward ? makeProgressForForward(cell) : null; if (getMessagesController().checkCanOpenChat(args, ChatActivity.this, cell.getMessageObject(), progress)) { ChatActivity chatActivity = new ChatActivity(args); if (progress != null && postId != 0) { AndroidUtilities.runOnUIThread(() -> { progress.onCancel(getMessagesController().ensureMessagesLoaded(-chat.id, postId, new MessagesController.MessagesLoadedCallback() { @Override public void onMessagesLoaded(boolean fromCache) { progress.end(); presentFragment(chatActivity); } @Override public void onError() { progress.end(); presentFragment(chatActivity); } })); }, 5000); progress.init(); } else { presentFragment(chatActivity); } } } } private boolean isAvatarPreviewerEnabled() { return UserObject.isUserSelf(currentUser) || (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)); } @Override public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { if (chatMode == MODE_QUICK_REPLIES) return; if (getParentActivity() == null || bottomChannelButtonsLayout.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) && !(button instanceof TLRPC.TL_keyboardButtonRequestPeer) && !(button instanceof TLRPC.TL_keyboardButtonCopy)) { return; } chatActivityEnterView.didPressedBotButton(button, cell.getMessageObject(), cell.getMessageObject(), makeProgressForBotButton(cell, button instanceof TLRPC.TL_keyboardButtonUrl ? button.url : null)); } @Override public void didPressCustomBotButton(ChatMessageCell cell, BotInlineKeyboard.ButtonCustom button) { final MessageObject messageObject = cell.getMessageObject(); if (messageObject == null) { return; } final TLRPC.Message message = messageObject.messageOwner; if (message == null) { return; } if (button.id == BotInlineKeyboard.ButtonCustom.SUGGESTION_DECLINE) { AlertsCreator.showDeclineSuggestedPostDialog(ChatActivity.this, DialogObject.getPeerDialogId(message.from_id), true, reason -> { getMessagesController().rejectSuggestedMessage(DialogObject.getPeerDialogId(message.peer_id), message.id, reason); }); } else if (button.id == BotInlineKeyboard.ButtonCustom.SUGGESTION_ACCEPT) { if (message.suggested_post != null) { final boolean isDirectAdmin = ChatObject.canManageMonoForum(currentAccount, currentChat); final boolean canPostMessages = isDirectAdmin && ChatObject.canUserDoChannelDirectAdminAction(currentAccount, currentChat, ChatObject.ACTION_POST); final Runnable onLoad = () -> { final SpannableStringBuilder ssb = new SpannableStringBuilder(); ssb.append(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.SuggestedMessageAcceptInfo, getMessagesController().getPeerName(DialogObject.getPeerDialogId(message.from_id))))); ssb.append("\n\n"); AmountUtils.Amount amount = AmountUtils.Amount.ofSafe(message.suggested_post.price); final int permille = amount.currency == AmountUtils.Currency.TON ? getMessagesController().config.tonSuggestedPostCommissionPermille.get(): getMessagesController().config.starsSuggestedPostCommissionPermille.get(); if (isDirectAdmin) { amount = AmountUtils.Amount.fromNano(amount.asNano() / 1000 * permille, amount.currency); } if (message.suggested_post.schedule_date == 0) { if (isDirectAdmin) { ssb.append(AndroidUtilities.replaceTags(LocaleController.formatString( R.string.SuggestedMessageAcceptInfoAnytimeAdmin2, amount.formatAsDecimalSpaced(), percents(permille) ))); } else { ssb.append(AndroidUtilities.replaceTags(LocaleController.formatString( R.string.SuggestedMessageAcceptInfoAnytimeUser2, amount.formatAsDecimalSpaced() ))); } } else { if (isDirectAdmin) { ssb.append(AndroidUtilities.replaceTags(LocaleController.formatString( R.string.SuggestedMessageAcceptInfoAdmin2, amount.formatAsDecimalSpaced(), MessageSuggestionOfferSheet.formatDateTime(message.suggested_post.schedule_date), percents(permille) ))); } else { ssb.append(AndroidUtilities.replaceTags(LocaleController.formatString( R.string.SuggestedMessageAcceptInfoUser2, amount.formatAsDecimalSpaced(), MessageSuggestionOfferSheet.formatDateTime(message.suggested_post.schedule_date) ))); } } ssb.append(' '); ssb.append(AndroidUtilities.replaceTags(LocaleController.formatString( R.string.SuggestedMessageAcceptInfo3, MessagesController.getInstance(currentAccount).config.starsSuggestedPostAgeMin.get(TimeUnit.HOURS) ))); final Bulletin[] bulletin = new Bulletin[1]; final DialogInterface.OnDismissListener onDismiss = d -> { if (bulletin[0] != null) { bulletin[0].hide(); } }; final AlertDialog[] dialog = new AlertDialog[1]; dialog[0] = AlertsCreator.showSimpleConfirmAlert(ChatActivity.this, LocaleController.getString(R.string.SuggestedPostAcceptTitle), ssb, LocaleController.getString(message.suggested_post.schedule_date == 0 ? R.string.Next : R.string.SuggestedPostPublish ), false, () -> { if (message.suggested_post.schedule_date == 0) { dialog[0].setOnDismissListener(null); AlertsCreator.createSuggestedMessageDatePickerDialog(getContext(), 0, (notify, scheduleDate, scheduleRepeatPeriod) -> { if (notify) { getMessagesController().approveSuggestedMessage( DialogObject.getPeerDialogId(messageObject.messageOwner.peer_id), messageObject.messageOwner.id, scheduleDate ); } }, getResourceProvider(), AlertsCreator.SUGGEST_DATE_PICKER_MODE_ACCEPT).show().setOnDismissListener(onDismiss); } else { getMessagesController().approveSuggestedMessage( DialogObject.getPeerDialogId(messageObject.messageOwner.peer_id), messageObject.messageOwner.id, 0 ); } }); dialog[0].setOnDismissListener(onDismiss); if (isDirectAdmin && amount.currency == AmountUtils.Currency.STARS) { bulletin[0] = BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourceProvider) .createSimpleBulletin(R.raw.info, getString(R.string.SuggestedMessageAcceptStarsDisclaimer), 10) .setDuration(60_000) .show(true); } }; checkStarsNeedSheet(onLoad, AmountUtils.Amount.of(message.suggested_post != null ? message.suggested_post.price : null), !isDirectAdmin); } } else if (button.id == BotInlineKeyboard.ButtonCustom.SUGGESTION_EDIT) { createMenu(cell, true, false, cell.getLastTouchX(), cell.getLastTouchY(), true, false, true); } else if (button.id == BotInlineKeyboard.ButtonCustom.OPEN_MESSAGE_THREAD) { topicsTabs.selectTopic(messageObject.getTopicId(), true); } } @Override public void needShowPremiumFeatures(String source) { presentFragment(new PremiumPreviewFragment(source)); } @Override public void needShowPremiumBulletin(int type) { if (type == 0) { checkTopUndoView(); if (topUndoView == null) { return; } topUndoView.showWithAction(0, UndoView.ACTION_PREMIUM_TRANSCRIPTION, null, () -> { new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT, true).show(); getMessagesController().pressTranscribeButton(); }); try { topUndoView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {} } else if (type == 1) { String until = LocaleController.formatDateTime(getMessagesController().transcribeAudioTrialCooldownUntil, true); CharSequence text = getMessagesController().transcribeAudioTrialCooldownUntil > 0 ? AndroidUtilities.replaceTags(LocaleController.formatPluralString("TranscriptionTrialLeftUntil", TranscribeButton.getTranscribeTrialCount(currentAccount), until)) : AndroidUtilities.replaceTags(LocaleController.formatPluralString("TranscriptionTrialLeft", TranscribeButton.getTranscribeTrialCount(currentAccount))); BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.transcribe, text, 6).show(true); try { fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {} } else if (type == 2 || type == 3) { String until = LocaleController.formatDateTime(getMessagesController().transcribeAudioTrialCooldownUntil, true); BulletinFactory.of(ChatActivity.this).createSimpleBulletin( R.raw.transcribe, new SpannableStringBuilder().append( AndroidUtilities.replaceTags(LocaleController.formatPluralString("TranscriptionTrialEnd", getMessagesController().transcribeAudioTrialWeeklyNumber)) ).append(" ").append( type == 2 ? AndroidUtilities.replaceSingleTag(LocaleController.getString(R.string.TranscriptionTrialEndBuy), () -> { new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT, true).show(); getMessagesController().pressTranscribeButton(); }) : getMessagesController().transcribeAudioTrialCooldownUntil <= 0 ? "" : AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TranscriptionTrialEndWaitOrBuy, until), () -> { new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT, true).show(); getMessagesController().pressTranscribeButton(); }) ), 6, 7000 ).show(true); BotWebViewVibrationEffect.APP_ERROR.vibrate(); } } @Override public void didLongPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { if (chatMode == MODE_QUICK_REPLIES) return; if (getParentActivity() == null || bottomChannelButtonsLayout.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) && !(button instanceof TLRPC.TL_keyboardButtonCopy)) { return; } if (button instanceof TLRPC.TL_keyboardButtonCopy) { didLongPressCopyButton(((TLRPC.TL_keyboardButtonCopy) button).copy_text); return; } if (button instanceof TLRPC.TL_keyboardButtonUrl) { openClickableLink(null, button.url, true, cell, cell.getMessageObject(), false); try { cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } catch (Exception ignore) {} } } @Override public void didPressReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction, boolean longpress, float x, float y) { ChatActivity.this.didPressReaction(cell, reaction, longpress, x, y); } @Override public boolean didLongPressToDoButton(ChatMessageCell cell, TLRPC.TodoItem task) { if (getParentActivity() == null || getContext() == null) { return false; } if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); } if (videoConversionTimeHint != null && videoConversionTimeHint.shown()) { videoConversionTimeHint.hide(); } final MessageObject messageObject = cell.getPrimaryMessageObject(); final TLRPC.MessageMedia _media = MessageObject.getMedia(messageObject); if (messageObject == null) return false; if (!(_media instanceof TLRPC.TL_messageMediaToDo)) return false; final TLRPC.TL_messageMediaToDo media = (TLRPC.TL_messageMediaToDo) _media; if (true) { selectedObject = messageObject; selectedObjectGroup = null; TodoItemMenu menu = new TodoItemMenu(getContext(), getResourceProvider()); menu.setCell(ChatActivity.this, cell, task.id); ArrayList icons = new ArrayList<>(); ArrayList items = new ArrayList<>(); final ArrayList options = new ArrayList<>(); fillMessageMenu(messageObject, icons, items, options); menu.setupMessageOptions(ChatActivity.this, icons, items, options, ChatActivity.this::processSelectedOption); menu.setOnDismissListener(() -> { selectedObject = null; selectedObjectGroup = null; }); menu.show(); return true; } 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)); } private final Path path = new Path(); @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); path.rewind(); path.addRoundRect(dp(8), dp(8), getWidth() - dp(8), getHeight() - dp(8), dp(6), dp(6), Path.Direction.CW); canvas.clipPath(path); super.dispatchDraw(canvas); canvas.restore(); } }; scrimPopupContainerLayout.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), 0, getResourceProvider(), 0); scrimPopupContainerLayout.addView(popupLayout); boolean showCompletion = false; TLRPC.TodoCompletion completion = null; for (int i = 0; i < media.completions.size(); ++i) { final TLRPC.TodoCompletion c = media.completions.get(i); if (c.id == task.id) { completion = c; break; } } if (completion != null) { showCompletion = true; final long dialogId = DialogObject.getPeerDialogId(completion.completed_by); final TLObject obj = getMessagesController().getUserOrChat(dialogId); final FrameLayout userButton = new FrameLayout(getContext()); userButton.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_listSelector), 6, 0)); final BackupImageView imageView = new BackupImageView(getContext()); imageView.setRoundRadius(dp(17)); AvatarDrawable avatarDrawable = new AvatarDrawable(); avatarDrawable.setInfo(obj); imageView.setForUserOrChat(obj, avatarDrawable); userButton.addView(imageView, LayoutHelper.createFrame(34, 34, Gravity.LEFT | Gravity.CENTER_VERTICAL, 13, 0, 0, 0)); final TextView titleText = new TextView(getContext()); titleText.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); titleText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); titleText.setEllipsize(TextUtils.TruncateAt.END); titleText.setSingleLine(true); if (obj instanceof TLRPC.User) { titleText.setText(UserObject.getUserName((TLRPC.User) obj)); } else if (obj instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) obj; titleText.setText(chat.title); } userButton.addView(titleText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.TOP, 59, 6, 16, 0)); final TextView subtitleText = new TextView(getContext()); subtitleText.setTextColor(getThemedColor(Theme.key_dialogTextGray2)); subtitleText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); subtitleText.setText(AndroidUtilities.replaceArrows(LocaleController.formatTodoCompletedDate(completion.date), false, dp(1), dp(.66f))); userButton.addView(subtitleText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.TOP, 59, 27, 16, 0)); userButton.setOnClickListener(v -> { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } presentFragment(ProfileActivity.of(dialogId)); }); popupLayout.addView(userButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52)); } if (ChatObject.isChannel(currentChat) && !ChatObject.isMonoForum(currentChat)) { if (showCompletion) { ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), getResourceProvider()); gap.setTag(R.id.fit_width_tag, 1); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); showCompletion = false; } ActionBarMenuSubItem copyLink = new ActionBarMenuSubItem(getParentActivity(), false, false); copyLink.setTextAndIcon(LocaleController.getString(R.string.CopyLink), R.drawable.msg_link); copyLink.setMinimumWidth(160); copyLink.setOnClickListener(view -> { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } final TLRPC.TL_channels_exportMessageLink req = new TLRPC.TL_channels_exportMessageLink(); req.id = messageObject.getId(); req.channel = MessagesController.getInputChannel(currentChat); req.thread = isReplyChatComment() || isTopic; getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response != null) { TLRPC.TL_exportedMessageLink exportedMessageLink = (TLRPC.TL_exportedMessageLink) response; try { if (AndroidUtilities.addToClipboard(exportedMessageLink.link + "?task=" + task.id)) { BulletinFactory.of(ChatActivity.this).createCopyLinkBulletin().show(); } } catch (Exception e) { FileLog.e(e); } } })); }); popupLayout.addView(copyLink); } if (messageObject.canEditMessage(currentChat) && media.todo.list.size() > 1) { if (showCompletion) { ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), getResourceProvider()); gap.setTag(R.id.fit_width_tag, 1); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); showCompletion = false; } ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getContext(), false, false); deleteItem.setTextAndIcon(getString(R.string.TodoDeleteItem), R.drawable.msg_delete); deleteItem.setMinimumWidth(160); deleteItem.setOnClickListener(view -> { if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } for (int i = 0; i < media.todo.list.size(); ++i) { final TLRPC.TodoItem item = media.todo.list.get(i); if (item.id == task.id) { media.todo.list.remove(i); i--; } } for (int i = 0; i < media.completions.size(); ++i) { final TLRPC.TodoCompletion c = media.completions.get(i); if (c.id == task.id) { media.completions.remove(i); if (media.completions.isEmpty()) { media.flags &=~ 1; } i--; } } messageObject.messageOwner.media = media; getSendMessagesHelper().editMessage(messageObject, null, null, null, null, null, null, false, false, null); updateVisibleRows(); }); popupLayout.addView(deleteItem); } 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); if (popupLayout.getChildCount() <= 0) { return false; } final int index = cell.getTodoIndex(task.id); float bottom = cell.getPollButtonBottom(index); float left = cell.getBackgroundDrawableLeft(); int[] loc = new int[2]; cell.getLocationInWindow(loc); boolean forceBottom = false; 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() != 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 > dp(20)) { totalHeight += keyboardHeight; } int popupX = (int) (left + dp(4)); popupX = Math.max(dp(6), Math.min(chatListView.getMeasuredWidth() - dp(6) - scrimPopupContainerLayout.getMeasuredWidth(), popupX)); if (AndroidUtilities.isTablet()) { int[] location = new int[2]; fragmentView.getLocationInWindow(location); popupX += location[0]; } int popupY; if (height < totalHeight) { float cellY = chatListView.getY() + cell.getY(); if (isInsideContainer) { int[] location = new int[2]; cell.getLocationInWindow(location); cellY = location[1]; } if (height < totalHeight / 2f && cellY + cell.getPollButtonTop(index) > totalHeight / 2f && !forceBottom) { scrimViewReactionOffset = -(height - dp(12)); popupY = (int) (cellY + cell.getPollButtonTop(index) - height); } else { scrimViewReactionOffset = 0; popupY = (int) (cellY + cell.getPollButtonBottom(index)); } } else { scrimViewReactionOffset = 0; popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } if (scrimPopupContainerLayout.getVisibility() != View.VISIBLE) { scrimViewReactionOffset = 0; } scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, scrimPopupX = popupX, scrimPopupY = popupY); chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); scrimViewReaction = null; scrimViewTask = task.id; scrimViewReactionAnimated = false; dimBehindView(cell, false, true); hideHints(false); if (topUndoView != null) { topUndoView.hide(true, 1); } if (undoView != null) { undoView.hide(true, 1); } if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } return true; } @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(chatInputViewsContainer); 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 boolean didPressToDoButton(ChatMessageCell cell, TLRPC.TodoItem task, boolean enable) { if (cell.getMessageObject().isForwarded()) { final long fromId = DialogObject.getPeerDialogId(cell.getMessageObject().getFromPeer()); BulletinFactory.of(ChatActivity.this) .createSimpleBulletin(R.raw.passcode_lock_close, AndroidUtilities.replaceTags(formatString(R.string.TodoCompleteForbiddenForward, DialogObject.getName(currentAccount, fromId)))) .show(true); return false; } else if (!cell.getMessageObject().canCompleteTodo()) { final long fromId = DialogObject.getPeerDialogId(cell.getMessageObject().getFromPeer()); BulletinFactory.of(ChatActivity.this) .createSimpleBulletin(R.raw.passcode_lock_close, AndroidUtilities.replaceTags(formatString(R.string.TodoCompleteForbidden, DialogObject.getName(currentAccount, fromId)))) .show(true); return false; } else if (!getUserConfig().isPremium()) { BulletinFactory.of(ChatActivity.this) .createSimpleBulletin(R.raw.star_premium_2, AndroidUtilities.premiumText(getString(R.string.TodoPremiumRequired), () -> { showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_TODO, false)); })) .show(true); return false; } else { long send_as = ChatObject.getSendAsPeerId(currentChat, chatInfo, true); getSendMessagesHelper().toggleTodo(send_as, cell.getMessageObject(), task, enable, null); return true; } } @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, false); startMultiselect(chatListView.getChildAdapterPosition(cell)); } @Override public boolean canPerformActions() { return actionBar != null && !actionBar.isActionModeShowed() && !isReport() && !inPreviewMode; } @Override public boolean canPerformReply() { return !isReport() && !inPreviewMode; } @Override public void didPressUrl(ChatMessageCell cell, final CharacterStyle url, boolean longPress) { didPressMessageUrl(url, longPress, cell.getMessageObject(), cell); } @Override public void didPressCodeCopy(ChatMessageCell cell, MessageObject.TextLayoutBlock block) { if (block == null || block.textLayout == null || block.textLayout.getText() == null) { return; } String string = block.textLayout.getText().toString(); SpannableString code = new SpannableString(string); code.setSpan(new CodeHighlighting.Span(false, 0, null, block.language, string), 0, code.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); AndroidUtilities.addToClipboard(code); BulletinFactory.of(ChatActivity.this).createCopyBulletin(LocaleController.getString(R.string.CodeCopied)).show(); } @Override public void didPressMoreChannelRecommendations(ChatMessageCell cell) { if (getUserConfig().isPremium()) { Bundle args = new Bundle(); args.putLong("dialog_id", dialog_id); args.putInt("start_from", SharedMediaLayout.TAB_RECOMMENDED_CHANNELS); presentFragment(new MediaActivity(args, avatarContainer.getSharedMediaPreloader())); } else { BulletinFactory.of(ChatActivity.this).createSimpleBulletin( R.raw.star_premium_2, AndroidUtilities.replaceSingleTag(formatPluralStringComma("UnlockSimilarChannelsPremium", getMessagesController().recommendedChannelsLimitPremium), () -> { presentFragment(new PremiumPreviewFragment("similar_channels")); }) ).show(); } } @Override public void didPressChannelRecommendation(ChatMessageCell cell, TLObject peer, boolean longPress) { if (getContext() == null || peer == null || parentLayout != null && parentLayout.isInPreviewMode()) { return; } Bundle args = new Bundle(); if (peer instanceof TLRPC.Chat) { args.putLong("chat_id", ((TLRPC.Chat) peer).id); } else if (peer instanceof TLRPC.User) { args.putLong("user_id", ((TLRPC.User) peer).id); } else { return; } if (longPress && peer instanceof TLRPC.Chat) { final TLRPC.Chat chat = (TLRPC.Chat) peer; ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext(), R.drawable.popup_fixed_alert, getResourceProvider(), ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_SHOWN_FROM_BOTTOM); previewMenu.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); ActionBarMenuSubItem openChannel = new ActionBarMenuSubItem(getParentActivity(), false, false); openChannel.setTextAndIcon(LocaleController.getString(R.string.OpenChannel2), R.drawable.msg_channel); openChannel.setMinimumWidth(160); openChannel.setOnClickListener(view -> { if (parentLayout != null) { parentLayout.expandPreviewFragment(); } }); previewMenu.addView(openChannel); ActionBarMenuSubItem joinChannel = new ActionBarMenuSubItem(getParentActivity(), false, false); joinChannel.setTextAndIcon(LocaleController.getString(R.string.ProfileJoinChannel), R.drawable.msg_addbot); joinChannel.setMinimumWidth(160); joinChannel.setOnClickListener(view -> { finishPreviewFragment(); chat.left = false; if (cell != null && cell.channelRecommendationsCell != null) { getNotificationCenter().postNotificationName(NotificationCenter.channelRecommendationsLoaded, cell.channelRecommendationsCell.chatId); } getMessagesController().addUserToChat(chat.id, getUserConfig().getCurrentUser(), 0, null, ChatActivity.this, () -> { BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.contact_check, LocaleController.formatString(R.string.YouJoinedChannel, chat == null ? "" : chat.title)).show(true); }); }); previewMenu.addView(joinChannel); ChatActivity chatActivity = new ChatActivity(args); chatActivity.allowExpandPreviewByClick = true; presentFragmentAsPreviewWithMenu(chatActivity, previewMenu); checkShowBlur(true); } else { presentFragment(new ChatActivity(args)); } } @Override public void didPressChannelRecommendationsClose(ChatMessageCell cell) { MessageObject msg = cell.getMessageObject(); if (msg != null && msg.type == MessageObject.TYPE_JOINED_CHANNEL) { msg.toggleChannelRecommendations(); msg.forceUpdate = true; cell.forceResetMessageObject(); cell.requestLayout(); chatAdapter.updateRowWithMessageObject(msg, false, false); } } @Override public boolean didPressAnimatedEmoji(ChatMessageCell cell, AnimatedEmojiSpan span) { if (getMessagesController().premiumFeaturesBlocked() || span == null || span.standard) { return false; } final long documentId = span.getDocumentId(); final TLRPC.Document document = span.document == null ? AnimatedEmojiDrawable.findDocument(currentAccount, documentId) : span.document; if (document == null) return false; final TLRPC.InputStickerSet inputStickerSet = MessageObject.getInputStickerSet(document); if (inputStickerSet == null) return false; final TLRPC.TL_messages_stickerSet cachedSet = MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSet(inputStickerSet, true); // if (cachedSet == null || cachedSet.set == null) { // final boolean[] cancelled = new boolean[1]; // final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER); // progressDialog.showDelayed(200); // progressDialog.setCanCancel(true); // progressDialog.setOnCancelListener(d -> cancelled[0] = true); // MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSet(inputStickerSet, null, false, set -> { // if (cancelled[0]) return; // ArrayList inputSets = new ArrayList<>(1); // inputSets.add(inputStickerSet); // EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); // alert.setCalcMandatoryInsets(isKeyboardVisible()); // showDialog(alert); // }); // } else { final ArrayList inputSets = new ArrayList<>(1); inputSets.add(inputStickerSet); final EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); alert.setPreviewEmoji(document); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); // } // Bulletin bulletin = BulletinFactory.of(ChatActivity.this).createContainsEmojiBulletin(document, BulletinFactory.CONTAINS_EMOJI_IN_MESSAGE, set -> { // ArrayList inputSets = new ArrayList<>(1); // inputSets.add(set); // EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); // alert.setCalcMandatoryInsets(isKeyboardVisible()); // showDialog(alert); // }); // if (bulletin != null) { // bulletin.show(); // return true; // } return true; } @Override public void didPressTopicButton(ChatMessageCell cell) { MessageObject message = cell.getMessageObject(); if (message != null) { long topicId = MessageObject.getTopicId(message.currentAccount, message.messageOwner, true); if (topicId != 0) { TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, topicId); if (topic != null) { ForumUtilities.openTopic(ChatActivity.this, currentChat.id, topic, message.getId()); } } } } @Override public boolean shouldShowTopicButton(ChatMessageCell cell) { return ChatObject.isForum(currentChat) && !isTopic; } @Override public void didPressDialogButton(ChatMessageCell cell) { openMessageInOriginalDialog(cell.getMessageObject()); } @Override public boolean shouldShowDialogButton(ChatMessageCell cell) { return chatMode == MODE_SEARCH && searchType == SEARCH_MY_MESSAGES; } @Override public void didPressExtendedMediaPreview(ChatMessageCell cell, TLRPC.KeyboardButton button) { getSendMessagesHelper().sendCallback(true, cell.getMessageObject(), button, ChatActivity.this); } @Override public void needOpenWebView(MessageObject message, String url, String title, String description, String originalUrl, int w, int h) { try { EmbedBottomSheet.show(ChatActivity.this, message, photoViewerProvider, title, description, originalUrl, url, w, h, isKeyboardVisible()); } catch (Throwable e) { FileLog.e(e); } } @Override public void didPressWebPage(ChatMessageCell cell, TLRPC.WebPage webpage, String url, boolean safe) { if (url == null) { return; } Uri uri = Uri.parse(url); if (uri == null) { return; } if (!safe && Browser.isTelegraphUrl(url, false)) { safe = true; } if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; if (!safe && !Browser.isInternalUri(uri, null)) { AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, true, true, !safe, progressDialogCurrent, themeDelegate); } else { Browser.openUrl(getContext(), uri, true, true, false, progressDialogCurrent, null, false, true, false); } } @Override public void didPressReplyMessage(ChatMessageCell cell, int id, float x, float y, boolean longpress) { if (!canPerformActions()) { if (!longpress) { if (actionBar.isActionModeShowed() || isReport()) { if (textSelectionHelper.isSelected(cell.getMessageObject())) { return; } processRowSelect(cell, !cell.isInsideBackground(x, y), x, y); } return; } } if (UserObject.isReplyUser(currentUser)) { didPressSideButton(cell); return; } MessageObject messageObject = cell.getMessageObject(); if (messageObject == null) return; if (messageObject.isReplyToStory() && messageObject.messageOwner.replyStory != null) { if (messageObject.messageOwner.replyStory instanceof TL_stories.TL_storyItemDeleted) { BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.story_bomb1, LocaleController.getString(R.string.StoryNotFound)).show(); } else { TL_stories.StoryItem storyItem = messageObject.messageOwner.replyStory; storyItem.dialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer); storyItem.messageId = messageObject.getId(); storyItem.messageType = 3; StoriesUtilities.applyViewedUser(storyItem, currentUser); getOrCreateStoryViewer().open(getContext(), storyItem, StoriesListPlaceProvider.of(chatListView)); } } else { String quote = null; int quoteOffset = -1; Integer task_id = null; if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.flags & 2048) != 0) { task_id = messageObject.messageOwner.reply_to.todo_item_id; } else if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote) { quote = messageObject.messageOwner.reply_to.quote_text; if ((messageObject.messageOwner.reply_to.flags & 1024) != 0) { quoteOffset = messageObject.messageOwner.reply_to.quote_offset; } } long did = dialog_id; boolean couldBeDifferentTopic = false; if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null) { if (messageObject.messageOwner.reply_to.reply_to_peer_id != null) { if (!(messageObject.messageOwner.reply_to.reply_to_peer_id instanceof TLRPC.TL_peerUser)) { did = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_to_peer_id); couldBeDifferentTopic = true; } else if (DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_to_peer_id) != dialog_id) { did = Long.MAX_VALUE; } } else if (messageObject.messageOwner.reply_to.reply_from != null) { did = Long.MAX_VALUE; if (messageObject.messageOwner.reply_to.reply_from.from_id != null) { if (!(messageObject.messageOwner.reply_to.reply_from.from_id instanceof TLRPC.TL_peerUser)) { did = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_from.from_id); } } else if (messageObject.messageOwner.reply_to.reply_from.saved_from_peer != null) { did = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_from.saved_from_peer); } } } TLRPC.Chat chat = null; if (did < 0) { chat = getMessagesController().getChat(-did); } if (did == Long.MAX_VALUE || did != dialog_id && chat != null && !ChatObject.isPublic(chat) && (chat.left || chat.kicked)) { if (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) && messageObject.replyTextEllipsized && !messageObject.replyTextRevealed && !messageObject.shouldDrawWithoutBackground()) { messageObject.replyTextRevealed = true; updateMessageAnimated(messageObject, true); } else { int str; if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote) { if (chat != null && chat.megagroup) { str = R.string.QuotePrivateGroup; } else if (ChatObject.isChannel(chat)) { str = R.string.QuotePrivateChannel; } else { str = R.string.QuotePrivate; } } else { if (chat != null && chat.megagroup) { str = R.string.ReplyPrivateGroup; } else if (ChatObject.isChannel(chat)) { str = R.string.ReplyPrivateChannel; } else { str = R.string.ReplyPrivate; } } BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.error, LocaleController.getString(str)).show(true); } return; } if ((did != dialog_id || ChatObject.isForum(currentChat) && couldBeDifferentTopic) && did != Long.MAX_VALUE || chatMode == MODE_SAVED && (messageObject.replyMessageObject == null || messageObject.replyMessageObject.getSavedDialogId() != getTopicId())) { if (LaunchActivity.instance != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(); progressDialogCurrent = null; } LaunchActivity.instance.openMessage(did, id, quote, progressDialogCurrent = new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = messageObject.getId(); progressDialogAtMessageType = PROGRESS_REPLY; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }, messageObject.getId(), quoteOffset, task_id); } } else if (chatMode == MODE_PINNED || chatMode == MODE_SCHEDULED) { chatActivityDelegate.openReplyMessage(id); finishFragment(); } else { if (task_id != null) { highlightTaskId = task_id; } else if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote) { highlightMessageQuoteFirst = true; highlightMessageQuote = messageObject.messageOwner.reply_to.quote_text; highlightMessageQuoteOffset = quoteOffset; showNoQuoteAlert = true; } final Integer finalTaskId = task_id; Runnable scroll = () -> { scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, finalTaskId, () -> { progressDialogAtMessageId = messageObject.getId(); progressDialogAtMessageType = PROGRESS_REPLY; }); }; if (chatAdapter.isFiltered) { setFilterMessages(searchingFiltered = false, true, false); updateSearchButtons(getMediaDataController().getMask(), getMediaDataController().getSearchPosition(), getMediaDataController().getSearchCount()); AndroidUtilities.runOnUIThread(scroll, 80); } else { scroll.run(); } } } } @Override public boolean isProgressLoading(ChatMessageCell cell, int type) { return progressDialogAtMessageId != 0 && cell.getMessageObject() != null && progressDialogAtMessageId == cell.getMessageObject().getId() && progressDialogAtMessageType == type; } @Override public CharacterStyle getProgressLoadingLink(ChatMessageCell cell) { if (cell.getMessageObject() != null && progressDialogAtMessageId != 0 && progressDialogAtMessageId == cell.getMessageObject().getId() && progressDialogAtMessageType == PROGRESS_LINK) { return progressDialogLinkSpan; } return null; } @Override public String getProgressLoadingBotButtonUrl(ChatMessageCell cell) { if (cell.getMessageObject() != null && progressDialogAtMessageId != 0 && progressDialogAtMessageId == cell.getMessageObject().getId() && progressDialogAtMessageType == PROGRESS_BOT_BUTTON) { return progressDialogBotButtonUrl; } return null; } @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 (bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.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 didPressBoostCounter(ChatMessageCell cell) { getNotificationCenter().postNotificationName(NotificationCenter.openBoostForUsersDialog, dialog_id, cell); } @Override public void didStartVideoStream(MessageObject message) { if (message.isVideo()) { sendSecretMessageRead(message, true); } } @Override public void needReloadPolls() { invalidateMessagesVisiblePart(); } @Override public void didPressGroupImage(ChatMessageCell cell, ImageReceiver imageReceiver, TLRPC.MessageExtendedMedia media, float x, float y) { final MessageObject message = cell.getMessageObject(); if (media instanceof TLRPC.TL_messageExtendedMediaPreview) { final Browser.Progress progress = makeProgressForPaidMedia(cell); Runnable cancel = StarsController.getInstance(currentAccount).pay(message, progress::end); if (cancel != null) { progress.onCancel(cancel); progress.init(); } return; } final TLRPC.Message omsg = message.messageOwner; if (!(message.messageOwner.media instanceof TLRPC.TL_messageMediaPaidMedia)) return; TLRPC.TL_messageMediaPaidMedia paidMedia = (TLRPC.TL_messageMediaPaidMedia) message.messageOwner.media; ArrayList messages = new ArrayList<>(); int index = -1; for (int i = 0; i < paidMedia.extended_media.size(); ++i) { TLRPC.MessageExtendedMedia extMedia = paidMedia.extended_media.get(i); if (extMedia instanceof TLRPC.TL_messageExtendedMedia) { TLRPC.TL_messageExtendedMedia emedia = (TLRPC.TL_messageExtendedMedia) extMedia; if (emedia == media) { index = messages.size(); } TLRPC.TL_message msg = new TLRPC.TL_message(); msg.id = omsg.id; msg.from_id = omsg.from_id; msg.from_boosts_applied = omsg.from_boosts_applied; msg.peer_id = omsg.peer_id; msg.saved_peer_id = omsg.saved_peer_id; msg.date = omsg.date; msg.expire_date = omsg.expire_date; msg.action = omsg.action; msg.message = omsg.message; msg.flags = omsg.flags; msg.flags2 = omsg.flags2; msg.mentioned = omsg.mentioned; msg.media_unread = omsg.media_unread; msg.out = omsg.out; msg.unread = omsg.unread; msg.entities = omsg.entities; msg.via_bot_name = omsg.via_bot_name; msg.reply_markup = omsg.reply_markup; msg.views = omsg.views; msg.forwards = omsg.forwards; msg.replies = omsg.replies; msg.edit_date = omsg.edit_date; msg.silent = omsg.silent; msg.post = omsg.post; msg.from_scheduled = omsg.from_scheduled; msg.legacy = omsg.legacy; msg.edit_hide = omsg.edit_hide; msg.pinned = omsg.pinned; msg.fwd_from = omsg.fwd_from; msg.via_bot_id = omsg.via_bot_id; msg.via_business_bot_id = omsg.via_business_bot_id; msg.reply_to = omsg.reply_to; msg.post_author = omsg.post_author; msg.grouped_id = omsg.grouped_id; msg.reactions = omsg.reactions; msg.restriction_reason = omsg.restriction_reason; msg.ttl_period = omsg.ttl_period; msg.quick_reply_shortcut_id = omsg.quick_reply_shortcut_id; msg.effect = omsg.effect; msg.noforwards = omsg.noforwards; msg.invert_media = omsg.invert_media; msg.offline = omsg.offline; msg.factcheck = omsg.factcheck; msg.send_state = omsg.send_state; msg.fwd_msg_id = omsg.fwd_msg_id; if (!TextUtils.isEmpty(emedia.attachPath)) { msg.attachPath = emedia.attachPath; } else if (paidMedia.extended_media.size() == 1) { msg.attachPath = omsg.attachPath; } msg.params = omsg.params; msg.random_id = omsg.random_id; msg.local_id = omsg.local_id; msg.dialog_id = omsg.dialog_id; msg.ttl = omsg.ttl; msg.destroyTime = omsg.destroyTime; msg.destroyTimeMillis = omsg.destroyTimeMillis; msg.layer = omsg.layer; msg.seq_in = omsg.seq_in; msg.seq_out = omsg.seq_out; msg.with_my_score = omsg.with_my_score; msg.replyMessage = omsg.replyMessage; msg.reqId = omsg.reqId; msg.realId = omsg.realId; msg.stickerVerified = omsg.stickerVerified; msg.isThreadMessage = omsg.isThreadMessage; msg.voiceTranscription = omsg.voiceTranscription; msg.voiceTranscriptionOpen = omsg.voiceTranscriptionOpen; msg.voiceTranscriptionRated = omsg.voiceTranscriptionRated; msg.voiceTranscriptionFinal = omsg.voiceTranscriptionFinal; msg.voiceTranscriptionForce = omsg.voiceTranscriptionForce; msg.voiceTranscriptionId = omsg.voiceTranscriptionId; msg.premiumEffectWasPlayed = omsg.premiumEffectWasPlayed; msg.originalLanguage = omsg.originalLanguage; msg.translatedToLanguage = omsg.translatedToLanguage; msg.translatedText = omsg.translatedText; msg.replyStory = omsg.replyStory; msg.media = emedia.media; msg.quick_reply_shortcut = omsg.quick_reply_shortcut; msg.noforwards = true; MessageObject msgObj = new MessageObject(message.currentAccount, msg, false, true); messages.add(msgObj); } } if (index <= -1 || messages.isEmpty()) return; PhotoViewer.getInstance().setParentActivity(ChatActivity.this, themeDelegate); PhotoViewer.getInstance().openPhoto(messages, index, getDialogId(), 0, 0, photoViewerPaidMediaProvider); } @Override public void didPressImage(ChatMessageCell cell, float x, float y, boolean fullPreview) { MessageObject message = cell.getMessageObject(); if (message.type == MessageObject.TYPE_STORY) { if (message.messageOwner.media.storyItem != null && !(message.messageOwner.media.storyItem instanceof TL_stories.TL_storyItemDeleted)) { TL_stories.StoryItem storyItem = message.messageOwner.media.storyItem; storyItem.dialogId = DialogObject.getPeerDialogId(message.messageOwner.media.peer); storyItem.messageId = message.getId(); storyItem.messageType = 2; StoriesUtilities.applyViewedUser(storyItem, currentUser); getOrCreateStoryViewer().open(getContext(), message.messageOwner.media.storyItem, StoriesListPlaceProvider.of(chatListView)); } return; } else if (message.isVideo()) { if (DownloadController.getInstance(currentAccount).canDownloadMedia(message.messageOwner) == 1) { message.putInDownloadsStore = true; } } else { message.putInDownloadsStore = true; } if (message.isSendError()) { createMenu(cell, false, false, x, y, false); return; } else if (message.isSending()) { return; } if (fullPreview && message != null && message.messageOwner != null && message.messageOwner.media != null && message.messageOwner.media.webpage != null && !TextUtils.isEmpty(message.messageOwner.media.webpage.url)) { final String url = message.messageOwner.media.webpage.url; final String host = AndroidUtilities.getHostAuthority(url); if (!openLinkInternally(url, cell, null, message.getId(), PROGRESS_INSTANT)) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; Browser.openUrl(getParentActivity(), Uri.parse(url), true, false, false, progressDialogCurrent, null, false, true, false); } return; } if (message.isDice()) { getMessagesController().loadStakeDiceInfo(available -> { if (available) { StakedDiceSheet.showStakeToast(ChatActivity.this, message.getDiceValue(), message.getStakedDiceAmount(), stake -> { if (checkSlowModeAlert()) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(message.getDiceEmoji(), dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, 0, null, false); params.quick_reply_shortcut_id = getQuickReplyId(); params.quick_reply_shortcut = quickReplyShortcut; params.dice_stake = stake; getSendMessagesHelper().sendMessage(params); } }); } else { createUndoView(); if (undoView == null) return; undoView.showWithAction(0, chatActivityEnterView.getVisibility() == View.VISIBLE && bottomOverlay.getVisibility() != View.VISIBLE ? UndoView.ACTION_DICE_INFO : UndoView.ACTION_DICE_NO_SEND_INFO, message.getDiceEmoji(), null, () -> { if (checkSlowModeAlert()) { SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(message.getDiceEmoji(), dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, 0, null, false); params.quick_reply_shortcut_id = getQuickReplyId(); params.quick_reply_shortcut = quickReplyShortcut; getSendMessagesHelper().sendMessage(params); } }); } }); } 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 openAction = sendSecretMessageRead(message, false); Runnable closeAction = sendSecretMediaDelete(message); cell.invalidate(); SecretMediaViewer.getInstance().setParentActivity(getParentActivity()); SecretMediaViewer.getInstance().openMedia(message, photoViewerProvider, openAction, closeAction); } else if (MessageObject.isAnimatedEmoji(message.getDocument()) && MessageObject.getInputStickerSet(message.getDocument()) != null) { final ArrayList inputSets = new ArrayList<>(1); inputSets.add(MessageObject.getInputStickerSet(message.getDocument())); final 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, bottomChannelButtonsLayout.getVisibility() != View.VISIBLE && (currentChat == null || ChatObject.canSendStickers(currentChat)) ? chatActivityEnterView : null, themeDelegate, false); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } else if (message.isVideo() || message.type == MessageObject.TYPE_PHOTO || message.type == MessageObject.TYPE_TEXT && !message.isWebpageDocument() || message.isGif()) { if (message.isSponsored()) { if (message.isGif() || message.isPhoto()) { logSponsoredClicked(message, true, false); if (message.sponsoredUrl != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; Browser.openUrl(getContext(), Uri.parse(message.sponsoredUrl), true, false, false, progressDialogCurrent, null, false, getMessagesController().sponsoredLinksInappAllow, false); } return; } else if (message.isVideo()) { logSponsoredClicked(message, true, false); } } if (message.getDuration() > 0 && message.getVideoStartsTimestamp() > 0 && !message.openedInViewer) { final int timestamp = message.getVideoStartsTimestamp(); message.forceSeekTo = (float) (timestamp / message.getDuration()); } openPhotoViewerForMessage(cell, message); } else if (message.type == MessageObject.TYPE_VIDEO) { 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 == MessageObject.TYPE_GEO) { 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 == MessageObject.TYPE_FILE || message.type == MessageObject.TYPE_TEXT) { 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(ChatActivity.this, themeDelegate); PhotoViewer.getInstance().openPhoto(message, ChatActivity.this, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, message.type != 0 ? getTopicId() : 0, photoViewerProvider); handled = true; } if (!handled) { try { AndroidUtilities.openForView(message, getParentActivity(), themeDelegate, false); } catch (Exception e) { FileLog.e(e); alertUserOpenError(message); } } } } @Override public void didPressInstantButton(ChatMessageCell cell, int type) { MessageObject messageObject = cell.getMessageObject(); if (type == 19) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; BoostDialogs.openGiveAwayStatusDialog(messageObject, progressDialogCurrent, getContext(), getResourceProvider()); } else if (type == 21) { if (ApplicationLoader.isStandaloneBuild()) { if (LaunchActivity.instance != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; LaunchActivity.instance.checkAppUpdate(true, progressDialogCurrent); } } else if (BuildVars.isHuaweiStoreApp()) { Browser.openUrl(getContext(), BuildVars.HUAWEI_STORE_URL); } else { Browser.openUrl(getContext(), BuildVars.PLAYSTORE_APP_URL); } } else if (type == 8) { PollVotesAlert.showForPoll(ChatActivity.this, messageObject); } else if (type == 0) { if (messageObject.messageOwner.media != null && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(messageObject) != null) { return; } ChatActivity.this.createArticleViewer(false).open(messageObject); } } else if (type == ChatMessageCell.INSTANT_BUTTON_TYPE_CONTACT_VIEW) { 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.phone_number, messageObject.messageOwner.media.vcard, messageObject.messageOwner.media.first_name, messageObject.messageOwner.media.last_name); } else if (type == ChatMessageCell.INSTANT_BUTTON_TYPE_CONTACT_SEND_MESSAGE) { long uid = messageObject.messageOwner.media.user_id; Bundle args = new Bundle(); args.putLong("user_id", uid); presentFragment(new ChatActivity(args)); } else if (type == ChatMessageCell.INSTANT_BUTTON_TYPE_CONTACT_ADD) { long uid = messageObject.messageOwner.media.user_id; TLRPC.User user = null; if (uid != 0) { user = MessagesController.getInstance(currentAccount).getUser(uid); } if (user != null) { String phone; if (!TextUtils.isEmpty(messageObject.vCardData)) { phone = messageObject.vCardData.toString(); } else { if (!TextUtils.isEmpty(user.phone)) { phone = PhoneFormat.getInstance().format("+" + user.phone); } else { phone = MessageObject.getMedia(messageObject.messageOwner).phone_number; if (!TextUtils.isEmpty(phone)) { phone = PhoneFormat.getInstance().format((String) phone); } else { phone = LocaleController.getString(R.string.NumberUnknown); } } } Bundle args = new Bundle(); args.putLong("user_id", user.id); args.putString("phone", phone); args.putBoolean("addContact", true); presentFragment(new ContactAddActivity(args)); } } else if (type == ChatMessageCell.INSTANT_BUTTON_TYPE_STICKER_SET || type == ChatMessageCell.INSTANT_BUTTON_TYPE_EMOJI_SET) { final boolean emoji = type == ChatMessageCell.INSTANT_BUTTON_TYPE_EMOJI_SET; TLRPC.WebPage webPage = null; if (webPage == null && messageObject.messageOwner != null && messageObject.messageOwner.media != null) { webPage = messageObject.messageOwner.media.webpage; } if (webPage == null || webPage.url == null) return; Pattern pattern = Pattern.compile("^https?\\:\\/\\/t\\.me\\/add(?:emoji|stickers)\\/(.+)$"); Matcher m = pattern.matcher(webPage.url); if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; if (m.matches() && m.groupCount() > 1 && m.group(1) != null) { String setname = m.group(1); TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccount).getStickerSetByName(setname); if (set == null) { progressDialogCurrent.init(); TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); TLRPC.TL_inputStickerSetShortName input = new TLRPC.TL_inputStickerSetShortName(); input.short_name = setname; req.stickerset = input; int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { progressDialogCurrent.end(); if (res instanceof TLRPC.TL_messages_stickerSet) { MediaDataController.getInstance(currentAccount).putStickerSet((TLRPC.TL_messages_stickerSet) res, false); if (getParentActivity() == null || getContext() == null) return; final TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); inputStickerSet.access_hash = ((TLRPC.TL_messages_stickerSet) res).set.access_hash; inputStickerSet.id = ((TLRPC.TL_messages_stickerSet) res).set.id; if (emoji) { final ArrayList inputSets = new ArrayList<>(1); inputSets.add(inputStickerSet); final EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } else { final StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate, false); alert.setCalcMandatoryInsets(isKeyboardVisible()); showDialog(alert); } } else { BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.error, getString(emoji ? R.string.AddEmojiNotFound : R.string.AddStickersNotFound)).show(true); } })); progressDialogCurrent.onCancel(() -> ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true)); return; } } Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, false, progressDialogCurrent, null, false, true, false); } else { if (messageObject.isSponsored()) { logSponsoredClicked(messageObject, false, false); if (messageObject.sponsoredUrl != null) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; Browser.openUrl(getContext(), Uri.parse(messageObject.sponsoredUrl), true, false, false, progressDialogCurrent, null, false, getMessagesController().sponsoredLinksInappAllow, false); } } else { TLRPC.WebPage webPage = messageObject.getStoryMentionWebpage(); if (webPage == null && messageObject.messageOwner != null && messageObject.messageOwner.media != null) { webPage = messageObject.messageOwner.media.webpage; } if (webPage == null) { return; } if (webPage.attributes != null) { for (int i = 0; i < webPage.attributes.size(); ++i) { if (webPage.attributes.get(i) instanceof TLRPC.TL_webPageAttributeStory) { TLRPC.TL_webPageAttributeStory story = (TLRPC.TL_webPageAttributeStory) webPage.attributes.get(i); if (story.storyItem != null) { story.storyItem.dialogId = DialogObject.getPeerDialogId(story.peer); story.storyItem.messageId = messageObject.getId(); story.storyItem.messageType = 1; getOrCreateStoryViewer().open(getContext(), story.storyItem, StoriesListPlaceProvider.of(chatListView)); return; } } } } if (!openLinkInternally(webPage.url, cell, null, messageObject.getId(), PROGRESS_INSTANT)) { if (progressDialogCurrent != null) { progressDialogCurrent.cancel(true); } progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { @Override public void init() { progressDialogAtMessageId = cell.getMessageObject().getId(); progressDialogAtMessageType = PROGRESS_INSTANT; progressDialogLinkSpan = null; cell.invalidate(); } @Override public void end(boolean replaced) { if (!replaced) { AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } } }; Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, false, progressDialogCurrent, null, false, true, false); } } } } @Override public void didPressGiveawayChatButton(ChatMessageCell cell, int pressedPos) { if (cell.getMessageObject().messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { final TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) cell.getMessageObject().messageOwner.media; final long channelId = giveaway.channels.get(pressedPos); if (dialog_id != -channelId) { presentFragment(ChatActivity.of(-channelId)); } else { avatarContainer.openProfile(false); } } if (cell.getMessageObject().messageOwner.media instanceof TLRPC.TL_messageMediaGiveawayResults) { TLRPC.TL_messageMediaGiveawayResults giveaway = (TLRPC.TL_messageMediaGiveawayResults) cell.getMessageObject().messageOwner.media; long id = giveaway.winners.get(pressedPos); presentFragment(ProfileActivity.of(id)); } } @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 (UserObject.isBotForum(currentUser)) { return null; } if (ChatObject.isChannel(currentChat) && currentChat.megagroup) { String rank = getMessagesController().getAdminRank(currentChat.id, uid); if (rank != null) { return rank; } } if (forumTopic != null && forumTopic.from_id != null && (forumTopic.from_id.user_id == uid || forumTopic.from_id.channel_id == uid || forumTopic.from_id.chat_id == uid)) { return LocaleController.getString(R.string.TopicCreator); } 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() { startFireworks(); } @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; } @Override public boolean doNotShowLoadingReply(MessageObject msg) { return (msg != null && msg.getDialogId() == UserObject.REPLY_BOT || (chatAdapter != null && chatAdapter.isFiltered)) && chatMode != MODE_SEARCH; } @Override public void didPressAboutRevenueSharingAds() { if (contentView == null || getParentActivity() == null) { return; } RevenueSharingAdsInfoBottomSheet.showAlert(contentView.getContext(), ChatActivity.this, false, resourceProvider); } @Override public void didPressRevealSensitiveContent(ChatMessageCell cell) { if (!getMessagesController().showSensitiveContent()) { final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER); progressDialog.showDelayed(200); getMessagesController().getContentSettings(settings -> { progressDialog.dismissUnless(200); final boolean needsVerification = getMessagesController().config.needAgeVideoVerification.get() && !TextUtils.isEmpty(getMessagesController().verifyAgeBotUsername); final boolean cannotView = !(settings != null && settings.sensitive_can_change) && needsVerification; boolean[] always = new boolean[1]; FrameLayout frameLayout = new FrameLayout(getContext()); if (needsVerification) { always[0] = true; } else if (settings != null && settings.sensitive_can_change) { CheckBoxCell checkbox = new CheckBoxCell(getContext(), 1, getResourceProvider()); checkbox.setBackground(Theme.getSelectorDrawable(false)); checkbox.setText(getString(R.string.MessageShowSensitiveContentAlways), "", always[0], false); checkbox.setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0); frameLayout.addView(checkbox, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); checkbox.setOnClickListener(v -> { CheckBoxCell cell1 = (CheckBoxCell) v; always[0] = !always[0]; cell1.setChecked(always[0], true); }); } final AlertDialog.Builder alert = new AlertDialog.Builder(getContext(), getResourceProvider()) .setTitle(getString(R.string.MessageShowSensitiveContentMediaTitle)) .setMessage(getString(cannotView ? R.string.MessageShowSensitiveContentMediaTextClosed : R.string.MessageShowSensitiveContentMediaText)) .setView(frameLayout).setCustomViewOffset(9) .setNegativeButton(getString(cannotView ? R.string.MessageShowSensitiveContentMediaTextClosedButton : R.string.Cancel), null); if (!cannotView) { alert.setPositiveButton(getString(R.string.MessageShowSensitiveContentButton), (di, w) -> { final Utilities.Callback reveal = (all) -> { if (all) { for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); if (!(child instanceof ChatMessageCell)) continue; ChatMessageCell messageCell = (ChatMessageCell) child; if (messageCell.getMessageObject() != null && messageCell.getMessageObject().isSensitive()) { messageCell.startRevealMedia(); } } } else { if (cell.getMessageObject() != null) { cell.getMessageObject().isSensitiveCached = false; } cell.startRevealMedia(); } }; if (always[0]) { if (needsVerification || settings != null && settings.sensitive_can_change) { ThemeActivity.verifyAge(getContext(), currentAccount, passed -> { if (!passed) { BulletinFactory.of(ChatActivity.this) .createSimpleBulletin(R.raw.error, getString(R.string.AgeVerificationFailedTitle), getString(R.string.AgeVerificationFailedText)) .show(); return; } getMessagesController().setContentSettings(true); BulletinFactory.of(ChatActivity.this) .createSimpleBulletinDetail(R.raw.chats_infotip, AndroidUtilities.replaceArrows(AndroidUtilities.premiumText(getString(R.string.SensitiveContentSettingsToast), () -> { presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC).highlightSensitiveRow()); }), true)) .show(true); reveal.run(true); }, getResourceProvider()); } else { reveal.run(true); } } else { reveal.run(false); } }); } showDialog(alert.create()); }); return; } if (cell.getMessageObject() != null) { cell.getMessageObject().isSensitiveCached = false; } cell.startRevealMedia(); } }; public void openThisProfile() { if (avatarContainer == null) return; avatarContainer.openProfile(true); } private void openUserProfile(long uid) { if (uid < 0) { if (uid == getDialogId()) { avatarContainer.openProfile(true); return; } Bundle args = new Bundle(); args.putLong("chat_id", -uid); if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { presentFragment(new ChatActivity(args)); } } else if (uid != getUserConfig().getClientUserId()) { if (uid == getDialogId()) { avatarContainer.openProfile(true); return; } 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); } else { Bundle args = new Bundle(); args.putLong("user_id", uid); args.putBoolean("my_profile", true); presentFragment(new ProfileActivity(args, null)); } } private boolean openLinkInternally(String urlFinal, ChatMessageCell cell, CharacterStyle span, int fromMessageId) { return openLinkInternally(urlFinal, cell, span, fromMessageId, PROGRESS_LINK); } private boolean openLinkInternally(String urlFinal, ChatMessageCell cell, CharacterStyle span, int fromMessageId, int fromMessageProgressType) { if (currentChat == null || urlFinal == null || chatMode != 0) { return false; } Runnable setupProgressLoading = cell != null && (span != null || fromMessageProgressType != PROGRESS_LINK) ? () -> { progressDialogAtMessageId = fromMessageId; progressDialogAtMessageType = fromMessageProgressType; progressDialogLinkSpan = span; cell.invalidate(); } : null; 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, null, setupProgressLoading); } } return true; } } else if (ChatObject.getPublicUsername(currentChat) != null) { try { if (publicMsgUrlPattern == null) { publicMsgUrlPattern = Pattern.compile("(https://)?t.me/([0-9a-zA-Z_]+)/([0-9]+)/?([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) && ChatObject.hasPublicLink(currentChat, matcher.group(2))) { Uri data = Uri.parse(urlFinal); int threadId = Utilities.parseInt(data.getQueryParameter("thread")); int commentId = Utilities.parseInt(data.getQueryParameter("comment")); Integer taskId = data.getQueryParameter("task") != null ? Utilities.parseInt(data.getQueryParameter("task")) : null; if (threadId != 0 || commentId != 0) { return false; } else { int messageId, topicId; if (matcher.group(4) != null) { topicId = Integer.parseInt(matcher.group(3)); messageId = Integer.parseInt(matcher.group(4)); } else { topicId = 0; messageId = Integer.parseInt(matcher.group(3)); } if (ChatObject.isForum(currentChat) && topicId != getTopicId()) { return false; } 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, taskId, setupProgressLoading); } } 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 (ChatObject.hasPublicLink(currentChat, 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, null, setupProgressLoading); } return true; } } } else { matcher = voiceChatUrlPattern.matcher(urlFinal); try { if (matcher.find(2) && matcher.find(3) && ChatObject.hasPublicLink(currentChat, matcher.group(2))) { 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); } } } catch (Exception e) { FileLog.e(e); } } else { try { if (privateMsgUrlPattern == null) { privateMsgUrlPattern = Pattern.compile("(https://)?t.me/c/([0-9]+)/([0-9]+)/?([0-9]+)?"); } Matcher matcher = privateMsgUrlPattern.matcher(urlFinal); if (matcher.find(2) && matcher.find(3) && matcher.group(4) == null) { 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 topicId = Utilities.parseInt(data.getQueryParameter("topic")); int commentId = Utilities.parseInt(data.getQueryParameter("comment")); int taskId = Utilities.parseInt(data.getQueryParameter("task")); if (threadId != 0 || topicId != 0 || commentId != 0) { return false; } else { if (ChatObject.isForum(currentChat)) { TLRPC.TL_forumTopic requestedForumTopic = getMessagesController().getTopicsController().findTopic(channelId, messageId); if (requestedForumTopic != null) { return forumTopic != null && forumTopic.id == requestedForumTopic.id; } } showScrollToMessageError = true; if (chatMode == MODE_PINNED) { chatActivityDelegate.openReplyMessage(messageId); finishFragment(); } else { scrollToMessageId(messageId, fromMessageId, true, 0, false, 0, taskId, setupProgressLoading); } return true; } } } } catch (Exception e) { FileLog.e(e); } } return false; } @Override public 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 void forceEmptyHistory() { forceHistoryEmpty = true; } public class ChatScrollCallback extends RecyclerAnimationScrollHelper.AnimationCallback { private MessageObject scrollTo; private int position = 0; private boolean bottom = true; private int offset = 0; 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(position, offset, bottom); } 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) { final ChatMessageCell cell = (ChatMessageCell) view; cell.setDelegate(null); ArrayList chatMessagesCache = chatMessageCellsCache.get(currentAccount); if (chatMessagesCache == null) { chatMessageCellsCache.put(currentAccount, chatMessagesCache = new ArrayList<>()); } chatMessagesCache.add(cell); } } } 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 (forceDisallowRedrawThemeDescriptions) { return null; } if (isPauseOnThemePreview) { isPauseOnThemePreview = false; return null; } ThemeDescription.ThemeDescriptionDelegate selectedBackgroundDelegate = () -> { if (blurredBackgroundColorProvider != null) { blurredBackgroundColorProvider.updateColors(); } if (blurredBackgroundColorProviderWhite != null) { blurredBackgroundColorProviderWhite.updateColors(); } 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 (pinnedLineView != null) { pinnedLineView.updateColors(); } if (chatActivityEnterTopView != null && chatActivityEnterTopView.getEditView() != null) { chatActivityEnterTopView.getEditView().updateColors(); } if (headerItem != null) { headerItem.updateColor(); } 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 (topChatPanelView2 != null) { topChatPanelView2.backgroundColor = getThemedColor(Theme.key_chat_topPanelBackground); } if (contentView != null) { contentView.invalidateBlurredViews(); contentView.invalidateBackground(); } if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); } if (suggestEmojiPanel != null) { suggestEmojiPanel.updateColors(); } if (avatarContainer != null && avatarContainer.getTimeItem() != null) { avatarContainer.getTimeItem().invalidate(); } if (translateButton != null) { translateButton.updateColors(); } if (chatInputViewsContainer != null) { chatInputViewsContainer.updateColors(); } if (sideControlsButtonsLayout != null) { sideControlsButtonsLayout.updateColors(); } if (bottomChannelButtonsLayout != null) { bottomChannelButtonsLayout.updateColors(); } invalidateAllGlassAttachedViews(); }; 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(messagesSearchListContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); if (!isReport()) { 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(false)) { 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_botLock), 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_fill_RedNormal)); 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}, 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}, 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_outReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_textSearchSelectionPaint, null, null, Theme.key_chat_inReplyLine)); 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_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, 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(false)) { 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(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_glass_defaultText)); 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_glass_defaultIcon)); 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_glass_defaultIcon)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatActivityEnterView.class}, new String[]{"scheduledButton"}, null, null, null, Theme.key_glass_defaultIcon)); 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_glass_defaultIcon)); 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[]{"suggestButton"}, null, null, null, Theme.key_glass_defaultIcon)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{ChatActivityEnterView.class}, new String[]{"suggestButton"}, null, null, null, Theme.key_listSelector)); // themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"audioSendButton"}, null, null, null, Theme.key_glass_defaultIcon)); // themeDescriptions.add(new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"videoSendButton"}, null, null, null, Theme.key_glass_defaultIcon)); 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, 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[]{"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_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_glass_defaultIcon)); } 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(topChatPanelView2, 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_text_RedBold)); themeDescriptions.add(new ThemeDescription(reportSpamButton, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_chat_addContact)); 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_glass_defaultText)); themeDescriptions.add(new ThemeDescription(replyObjectHintTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_glass_defaultText)); 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_glass_defaultIcon)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_replyPanelName)); 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(bottomOverlayText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_secretChatStatusText)); themeDescriptions.add(new ThemeDescription(bottomOverlayChatText, 0, null, null, null, null, Theme.key_glass_defaultText)); 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_glass_defaultIcon)); 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)); if (mentionContainer != null) { 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(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(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_attachIcon)); 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_attachIcon)); 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_attachIcon)); 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_attachIcon)); 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_attachIcon)); 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_attachIcon)); 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 && chatActivityEnterView.botCommandsMenuContainer != 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; } public void openedInstantly() { fragmentOpened = true; fragmentBeginToShow = true; fragmentTransition = null; contentView.invalidate(); contentView.setSkipBackgroundDrawing(false); toPullingDownTransition = false; fragmentView.setAlpha(1f); avatarContainer.setTranslationY(0); avatarContainer.getAvatarImageView().setScaleX(1f); avatarContainer.getAvatarImageView().setScaleY(1f); avatarContainer.getAvatarImageView().setAlpha(1f); } @Override public AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { if (isOpen && fromPullingDownTransition && getParentLayout() != null && getParentLayout().getFragmentStack().size() > 1) { BaseFragment previousFragment = getParentLayout().getFragmentStack().get(getParentLayout().getFragmentStack().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); } if (previousChat.pinnedMessageView != null) { previousChat.pinnedMessageView.setAlpha(1f - progress); } if (previousChat.topChatPanelView != null) { previousChat.topChatPanelView.setAlpha(1f - progress); } if (previousChat.topChatPanelView2 != null) { previousChat.topChatPanelView2.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); if (previousChat.pinnedMessageView != null) { previousChat.pinnedMessageView.setAlpha(1f); } if (previousChat.topChatPanelView != null) { previousChat.topChatPanelView.setAlpha(1f); } if (previousChat.topChatPanelView2 != null) { previousChat.topChatPanelView2.setAlpha(1f); } } }); fragmentTransition.setDuration(300); fragmentTransition.setInterpolator(CubicBezierInterpolator.DEFAULT); fragmentTransition.playTogether(valueAnimator); AndroidUtilities.runOnUIThread(fragmentTransitionRunnable, 200); return fragmentTransition; } } if (switchFromTopics && getParentLayout() != null && getParentLayout().getFragmentStack().size() > 1) { BaseFragment previousFragment = getParentLayout().getFragmentStack().get(getParentLayout().getFragmentStack().size() - 2); if (!(previousFragment instanceof TopicsFragment)) { return null; } ValueAnimator valueAnimator = isOpen ? ValueAnimator.ofFloat(0f, 1f) : ValueAnimator.ofFloat(1f, 0f); int width = previousFragment.getFragmentView().getWidth(); switchingFromTopicsProgress = isOpen ? 0f : 1f; valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { switchingFromTopicsProgress = (float) animation.getAnimatedValue(); contentView.invalidate(); } }); switchingFromTopics = true; if (actionBar != null) { actionBar.invalidate(); } if (contentView != null) { contentView.invalidate(); } 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; if (isOpen) { switchingFromTopics = false; } actionBar.invalidate(); contentView.invalidate(); AndroidUtilities.runOnUIThread(() -> { NotificationCenter.getInstance(currentAccount).onAnimationFinish(index); }, 32); callback.run(); } }); fragmentTransition.setDuration(150); fragmentTransition.playTogether(valueAnimator); if (isOpen) { AndroidUtilities.runOnUIThread(fragmentTransitionRunnable, 200); } else { fragmentTransition.start(); } 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() { if (currentChat != null) { if (ChatObject.isMegagroup(currentChat)) { if (ChatObject.hasAdminRights(currentChat)) { presentFragment(new GroupColorActivity(getDialogId()).setOnApplied(ChatActivity.this)); } } else { if (ChatObject.canChangeChatInfo(currentChat)) { presentFragment(new ChannelColorActivity(getDialogId()).setOnApplied(ChatActivity.this)); } } return; } 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.getInstance(currentAccount).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 checkThemeEmoticonOrWallpaper() { getNotificationCenter().doOnIdle(() -> { setChatThemeEmoticon(userInfo != null ? userInfo.theme : null); // if (emoticon == null && chatInfo != null) { // emoticon = chatInfo.theme_emoticon; // } }); } private void setChatThemeEmoticon(final TLRPC.ChatTheme theme) { if (themeDelegate == null || parentThemeDelegate != null) { return; } ThemeKey key = ThemeKey.of(theme); ChatThemeController chatThemeController = ChatThemeController.getInstance(currentAccount); chatThemeController.setDialogTheme(dialog_id, theme, false); if (theme instanceof TLRPC.TL_chatThemeUniqueGift) { chatThemeController.putThemeIfNeeded(theme); EmojiThemes theme1 = chatThemeController.getTheme(key); if (theme1 == null) { // unreachable code? theme1 = new EmojiThemes(currentAccount, (TLRPC.TL_chatThemeUniqueGift) theme); theme1.initColors(); theme1.loadPreviewColors(currentAccount); } themeDelegate.setCurrentTheme(theme1, themeDelegate.wallpaper, openAnimationStartTime != 0, null); return; } if (key != null && !key.isEmpty()) { chatThemeController.requestChatTheme(key, result -> { themeDelegate.setCurrentTheme(result, themeDelegate.wallpaper, openAnimationStartTime != 0, null); }); } TLRPC.WallPaper wallPaper = chatThemeController.getDialogWallpaper(dialog_id); themeDelegate.setCurrentTheme(themeDelegate.chatTheme, wallPaper, openAnimationStartTime != 0, null); } @Override public Drawable getThemedDrawable(String drawableKey) { Drawable drawable = themeDelegate.getDrawable(drawableKey); return drawable != null ? drawable : super.getThemedDrawable(drawableKey); } @Override public 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, MessagePreviewView.ResourcesDelegate { private final HashMap currentDrawables = new HashMap<>(); private final HashMap currentPaints = new HashMap<>(); private final Matrix actionMatrix = new Matrix(); private SparseIntArray currentColors = new SparseIntArray(); private SparseIntArray animatingColors; private EmojiThemes chatTheme; private TLRPC.WallPaper wallpaper; 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 AnimatorSet patternAlphaAnimator; Theme.MessageDrawable animatingMessageDrawable; Theme.MessageDrawable animatingMessageMediaDrawable; ThemeDelegate() { isDark = Theme.getActiveTheme().isDark(); boolean setup = false; if (isThemeChangeAvailable(false)) { chatTheme = ChatThemeController.getInstance(currentAccount).getDialogTheme(dialog_id); wallpaper = ChatThemeController.getInstance(currentAccount).getDialogWallpaper(dialog_id); if (chatTheme != null || wallpaper != null) { setup = true; setupChatTheme(chatTheme, wallpaper, false, true); } } if (!setup && ThemeEditorView.getInstance() == null) { Theme.refreshThemeColors(true, true); } else { AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewTheme, false, true, true)); } } @Override public int getColor(int key) { if (animatingColors != null) { int index = animatingColors.indexOfKey(key); if (index >= 0) { return animatingColors.valueAt(index); } } if (chatTheme == null) { return Theme.getColor(key); } int index = currentColors.indexOfKey(key); if (index >= 0) { return currentColors.valueAt(index); } int fallbackKey = Theme.getFallbackKey(key); if (fallbackKey >= 0) { index = currentColors.indexOfKey(fallbackKey); if (index >= 0) { return currentColors.valueAt(index); } } return Theme.getColor(key); } @Override public int getCurrentColor(int key) { return getCurrentColor(key, false); } public int getCurrentColor(int key, boolean ignoreAnimation) { if (chatTheme == null && backgroundDrawable == null) { return Theme.getColor(key); } if (!ignoreAnimation && animatingColors != null) { int index = animatingColors.indexOfKey(key); if (index >= 0) { return animatingColors.valueAt(index); } } if (currentColors != null) { int index = currentColors.indexOfKey(key); if (index >= 0) { return currentColors.valueAt(index); } } return Theme.getColor(key); } @Override public void setAnimatedColor(int key, int color) { if (animatingColors != null) { animatingColors.put(key, color); } } @Override public void applyServiceShaderMatrix(int w, int h, float translationX, float translationY) { if (backgroundDrawable == 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 backgroundDrawable != null ? currentColor : Theme.currentColor; } public boolean isGiftTheme() { EmojiThemes themes = getCurrentTheme(); return themes != null && themes.getThemeGift() != null; } @Override public boolean hasGradientService() { return backgroundDrawable != 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 || backgroundDrawable != null ? currentPaints.get(paintKey) : null; } public boolean isThemeChangeAvailable(boolean canEdit) { return currentEncryptedChat == null && ( (!canEdit /*|| currentChat != null && ChatObject.isChannelAndNotMegaGroup(currentChat) && ChatObject.canChangeChatInfo(currentChat)*/) || currentChat == null && currentUser != null && !currentUser.bot ); } 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, TLRPC.WallPaper newWallpaper, boolean animated, Boolean forceDark) { setCurrentTheme(chatTheme, newWallpaper, animated, forceDark, false); } public void setCurrentTheme(final EmojiThemes chatTheme, TLRPC.WallPaper newWallpaper, boolean animated, Boolean forceDark, boolean force) { if (parentLayout == null || parentThemeDelegate != null) { return; } final EmojiThemes prevTheme = this.chatTheme; boolean newIsDark = forceDark != null ? forceDark : this.isDark;//Theme.getActiveTheme().isDark(); ThemeKey newEmoticon = chatTheme != null ? chatTheme.getThemeKey() : null; ThemeKey oldEmoticon = this.chatTheme != null ? this.chatTheme.getThemeKey() : null; TLRPC.WallPaper oldWallpaper = this.wallpaper; if (!force && (!isThemeChangeAvailable(false) || (ThemeKey.equals(oldEmoticon, newEmoticon) && this.isDark == newIsDark && ChatThemeController.equals(newWallpaper, oldWallpaper)))) { 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 && wallpaper == 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 && backgroundDrawable instanceof MotionBackgroundDrawable) { startServiceBitmap = ((MotionBackgroundDrawable) backgroundDrawable).getBitmap(); final boolean forceRecolorServiceMessages = isGiftTheme() && isDark; if (forceRecolorServiceMessages) { startServiceBitmap = Bitmap.createBitmap(startServiceBitmap); Canvas tmpC = new Canvas(startServiceBitmap); tmpC.drawColor(0xCC222222); } } else if (backgroundDrawable != null) { initServiceMessageColors(backgroundDrawable); } startServiceColor = currentServiceColor; startServiceTextColor = drawServiceGradient ? 0xffffffff : getCurrentColor(Theme.key_chat_serviceText, true); startServiceLinkColor = drawServiceGradient ? 0xffffffff : getCurrentColor(Theme.key_chat_serviceLink, true); startServiceButtonColor = drawServiceGradient ? 0xffffffff : getCurrentColor(Theme.key_chat_serviceLink, true); startServiceIconColor = drawServiceGradient ? 0xffffffff : getCurrentColor(Theme.key_chat_serviceIcon, true); if (chatTheme != null || newWallpaper != null) { int[] colors = AndroidUtilities.calcDrawableColor(backgroundDrawable); currentColor = colors[0]; initDrawables(); initPaints(); } animationSettings.applyTheme = false; if (dialog_id < 0) animationSettings.applyTrulyTheme = false; animationSettings.afterStartDescriptionsAddedRunnable = () -> { setupChatTheme(chatTheme, newWallpaper, animated, true); initServiceMessageColors(backgroundDrawable); //updateBackground(); if (contentView != null) { contentView.invalidateBackground(); } }; 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 SparseIntArray(); animatingMessageDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOut); animatingMessageDrawable.crossfadeFromDrawable = parentLayout.getMessageDrawableOutStart(); animatingMessageMediaDrawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgOutMedia); animatingMessageMediaDrawable.crossfadeFromDrawable = parentLayout.getMessageDrawableOutMediaStart(); 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) { updateBackground(); } animationSettings.afterStartDescriptionsAddedRunnable.run(); } animationSettings.onlyTopFragment = true; animationSettings.resourcesProvider = this; animationSettings.duration = 250; parentLayout.animateThemedValues(animationSettings, null); if (onThemeChange != null) { onThemeChange.run(); } } private void setupChatTheme(EmojiThemes chatTheme, TLRPC.WallPaper wallPaper, boolean withAnimation, boolean createNewResources) { if (parentThemeDelegate != null) return; this.chatTheme = chatTheme; this.wallpaper = wallPaper; Drawable prevDrawable = null; if (fragmentView != null) { prevDrawable = (contentView).getBackgroundImage(); } final MotionBackgroundDrawable prevMotionDrawable = (prevDrawable instanceof MotionBackgroundDrawable) ? (MotionBackgroundDrawable) prevDrawable : null; final int prevPhase = prevMotionDrawable != null ? prevMotionDrawable.getPhase() : 0; if ((chatTheme == null || chatTheme.showAsDefaultStub) && wallPaper == null) { currentColor = Theme.getServiceMessageColor(); } if (chatTheme == null && wallPaper == null) { currentColors = new SparseIntArray(); currentPaints.clear(); currentDrawables.clear(); Drawable wallpaperDrawable = Theme.getCachedWallpaperNonBlocking(); if (wallpaperDrawable instanceof MotionBackgroundDrawable) { ((MotionBackgroundDrawable) wallpaperDrawable).setPhase(prevPhase); } backgroundDrawable = null;//wallpaperDrawable; 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); initServiceMessageColors(backgroundDrawable); } else { if (ApplicationLoader.applicationContext != null) { Theme.createChatResources(ApplicationLoader.applicationContext, false); } if (chatTheme == null) { currentColors = new SparseIntArray(); } else { currentColors = chatTheme.createColors(currentAccount, isDark ? 1 : 0); } if (!TextUtils.isEmpty(ChatThemeController.getWallpaperEmoticon(wallpaper))) { backgroundDrawable = PreviewView.getBackgroundDrawable(backgroundDrawable, currentAccount, wallpaper, isDark); } else if (wallPaper != null) { backgroundDrawable = ChatBackgroundDrawable.getOrCreate(backgroundDrawable, wallPaper, isDark); } else { 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 (chatTheme == null && dialog_id >= 0) { 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); } 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) { int colorKey = Theme.getThemeDrawableColorKey(entry.getKey()); if (colorKey >= 0) { Theme.setDrawableColor(drawable, getColor(colorKey)); } } } 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); } int colorKey = Theme.getThemePaintColorKey(entry.getKey()); if (colorKey >= 0 && !Theme.key_paint_chatActionBackgroundDarken.equals(entry.getKey())) { newPaint.setColor(getColor(colorKey)); } 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; final Rect src = new Rect(), dst = new Rect(); private void initServiceMessageColors(Drawable backgroundDrawable) { if (parentThemeDelegate != null) return; int[] result = AndroidUtilities.calcDrawableColor(backgroundDrawable); int currentServiceMessageColor = result[0]; int serviceColor = getCurrentColor(Theme.key_chat_serviceBackground); int selectedBackgroundColor = getCurrentColor(Theme.key_chat_selectedBackground); int serviceColor2 = serviceColor; if (serviceColor == 0 || wallpaper != null) { serviceColor = currentServiceMessageColor; } currentServiceColor = serviceColor; float dimAmount = 0; if (backgroundDrawable instanceof ChatBackgroundDrawable) { dimAmount = ((ChatBackgroundDrawable) backgroundDrawable).getDimAmount(); backgroundDrawable = ((ChatBackgroundDrawable) backgroundDrawable).getDrawable(false); } drawServiceGradient = (backgroundDrawable instanceof MotionBackgroundDrawable || backgroundDrawable instanceof BitmapDrawable) && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; final boolean forceRecolorServiceMessages = isGiftTheme() && isDark; drawSelectedGradient = drawServiceGradient; if (drawServiceGradient) { if (backgroundDrawable instanceof BitmapDrawable) { Bitmap source = ((BitmapDrawable) backgroundDrawable).getBitmap(); int w, h; if (source.getWidth() > source.getHeight()) { w = 40; h = (int) ((float) w / source.getWidth() * source.getHeight()); } else { h = 40; w = (int) ((float) h / source.getHeight() * source.getWidth()); } serviceBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); serviceCanvas = new Canvas(serviceBitmap); src.set(0, 0, source.getWidth(), source.getHeight()); dst.set(0, 0, serviceBitmap.getWidth(), serviceBitmap.getHeight()); serviceCanvas.drawBitmap(source, src, dst, null); Utilities.blurBitmap(serviceBitmap, 3, 1, serviceBitmap.getWidth(), serviceBitmap.getHeight(), serviceBitmap.getRowBytes()); serviceCanvas.drawColor(ColorUtils.setAlphaComponent(0xff000000, (int) (0xFF * dimAmount))); serviceShader = new BitmapShader(serviceBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); serviceBitmapSource = Bitmap.createBitmap(serviceBitmap); serviceShaderSource = new BitmapShader(serviceBitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { serviceShader.setFilterMode(BitmapShader.FILTER_MODE_LINEAR); serviceShaderSource.setFilterMode(BitmapShader.FILTER_MODE_LINEAR); } useSourceShader = true; } else { serviceBitmap = Bitmap.createBitmap(60, 80, Bitmap.Config.ARGB_8888); serviceBitmapSource = ((MotionBackgroundDrawable) backgroundDrawable).getBitmap(); if (forceRecolorServiceMessages) { serviceBitmapSource = Bitmap.createBitmap(serviceBitmapSource); Canvas tmpC = new Canvas(serviceBitmapSource); tmpC.drawColor(0xCC222222); } serviceCanvas = new Canvas(serviceBitmap); src.set(0, 0, serviceBitmapSource.getWidth(), serviceBitmapSource.getHeight()); dst.set(0, 0, serviceBitmap.getWidth(), serviceBitmap.getHeight()); serviceCanvas.drawBitmap(serviceBitmapSource, src, dst, null); serviceCanvas.drawColor(ColorUtils.setAlphaComponent(0xff000000, (int) (0xFF * dimAmount))); if (forceRecolorServiceMessages) { serviceCanvas.drawColor(0xCC222222); } serviceShader = new BitmapShader(serviceBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); serviceShaderSource = new BitmapShader(serviceBitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { serviceShader.setFilterMode(BitmapShader.FILTER_MODE_LINEAR); serviceShaderSource.setFilterMode(BitmapShader.FILTER_MODE_LINEAR); } useSourceShader = true; } } else { serviceBitmap = null; serviceShader = null; serviceBitmapSource = null; serviceCanvas = null; useSourceShader = false; } Paint actionBackgroundPaint = getPaint(Theme.key_paint_chatActionBackground); Paint actionBackgroundSelectedPaint = getPaint(Theme.key_paint_chatActionBackgroundSelected); Paint msgBackgroundSelectedPaint = getPaint(Theme.key_paint_chatMessageBackgroundSelected); if (actionBackgroundPaint != null) { Paint darkenPaint = currentPaints.get(Theme.key_paint_chatActionBackgroundDarken); if (darkenPaint == null) { currentPaints.put(Theme.key_paint_chatActionBackgroundDarken, darkenPaint = new Paint(Paint.ANTI_ALIAS_FLAG)); darkenPaint.setColor(0); } if (drawServiceGradient) { ColorMatrix colorMatrix = new ColorMatrix(); if (backgroundDrawable instanceof MotionBackgroundDrawable) { float intensity = ((MotionBackgroundDrawable) backgroundDrawable).getIntensity(); if (intensity >= 0) { colorMatrix.setSaturation(1.6f); AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, isDark ? .97f : .92f); AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, isDark ? +.12f : -.06f); } else { colorMatrix.setSaturation(1.1f); AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, isDark ? .4f : .8f); AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, isDark ? +.08f : -.06f); } } else { colorMatrix.setSaturation(1.6f); AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, isDark ? .9f : .84f); AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, isDark ? +.04f : +.06f); } actionBackgroundPaint.setAlpha(0xff); actionBackgroundPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); actionBackgroundPaint.setShader(serviceShaderSource); actionBackgroundPaint.setFilterBitmap(true); actionBackgroundSelectedPaint.setAlpha(0xFF); colorMatrix = new ColorMatrix(colorMatrix); AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.26f); AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, .92f); actionBackgroundSelectedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); actionBackgroundSelectedPaint.setShader(serviceShaderSource); actionBackgroundSelectedPaint.setFilterBitmap(true); darkenPaint.setAlpha(0); } else { actionBackgroundPaint.setColorFilter(null); actionBackgroundPaint.setShader(null); actionBackgroundSelectedPaint.setColorFilter(null); actionBackgroundSelectedPaint.setShader(null); darkenPaint.setAlpha(0x15); } } 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); msgBackgroundSelectedPaint.setFilterBitmap(true); } else { if (selectedBackgroundColor == 0) { 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 : getCurrentColor(Theme.key_chat_serviceText, true); int serviceLinkColor = drawServiceGradient ? 0xffffffff : getCurrentColor(Theme.key_chat_serviceLink, true); int serviceButtonColor = drawServiceGradient ? 0xffffffff : getCurrentColor(Theme.key_chat_serviceLink, true); int serviceIconColor = drawServiceGradient ? 0xffffffff : getCurrentColor(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_botLock), 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; src.set(0, 0, startServiceBitmap.getWidth(), startServiceBitmap.getHeight()); dst.set(0, 0, serviceBitmap.getWidth(), serviceBitmap.getHeight()); serviceCanvas.drawBitmap(startServiceBitmap, src, dst, null); paint.setAlpha((int) (255 * progress)); src.set(0, 0, serviceBitmapSource.getWidth(), serviceBitmapSource.getHeight()); dst.set(0, 0, serviceBitmap.getWidth(), serviceBitmap.getHeight()); serviceCanvas.drawBitmap(serviceBitmapSource, src, dst, paint); if (actionBackgroundPaint != null) { actionBackgroundPaint.setShader(serviceShader); actionBackgroundSelectedPaint.setShader(serviceShader); } if (msgBackgroundSelectedPaint != null) { msgBackgroundSelectedPaint.setShader(serviceShader); } } else { useSourceShader = true; src.set(0, 0, serviceBitmapSource.getWidth(), serviceBitmapSource.getHeight()); dst.set(0, 0, serviceBitmap.getWidth(), serviceBitmap.getHeight()); serviceCanvas.drawBitmap(serviceBitmapSource, src, dst, 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); SparseIntArray currentColors = chatTheme.getPreviewColors(currentAccount, isDark ? 1 : 0); String wallpaperLink = chatTheme.getWallpaperLink(isDark ? 1 : 0); Theme.BackgroundDrawableSettings settings = Theme.createBackgroundDrawable(themeInfo, currentColors, wallpaperLink, prevPhase, false); drawable = settings.wallpaper; drawable = new ColorDrawable(Color.BLACK); } else { int backgroundColor = getColor(Theme.key_chat_wallpaper); int gradientColor1 = getColor(Theme.key_chat_wallpaper_gradient_to1); int gradientColor2 = getColor(Theme.key_chat_wallpaper_gradient_to2); int gradientColor3 = getColor(Theme.key_chat_wallpaper_gradient_to3); MotionBackgroundDrawable motionDrawable = new MotionBackgroundDrawable(); motionDrawable.setPatternBitmap(chatTheme.getWallpaper(isDark ? 1 : 0).settings.intensity); motionDrawable.setGiftDrawable(chatTheme.getEmojiAnimatedSticker()); motionDrawable.setColors(backgroundColor, gradientColor1, gradientColor2, gradientColor3, 0,true); motionDrawable.setPhase(prevPhase); int patternColor = motionDrawable.getPatternColor(); final boolean isDarkTheme = isDark; chatTheme.loadWallpaperGiftPattern(isDark ? 1 : 0, pair -> { if (pair == null) { return; } long themeId = pair.first; Bitmap bitmap = pair.second; if (this.chatTheme != null && themeId == this.chatTheme.getThemeId(isDark ? 1 : 0) && bitmap != null) { motionDrawable.setGiftPatternBitmap(bitmap); } }); chatTheme.loadWallpaper(isDark ? 1 : 0, pair -> { if (pair == null) { return; } long themeId = pair.first; Bitmap bitmap = pair.second.bitmap; if (this.chatTheme != null && themeId == this.chatTheme.getThemeId(isDark ? 1 : 0) && bitmap != null) { if (patternIntensityAnimator != null) { patternIntensityAnimator.cancel(); } int intensity = chatTheme.getWallpaper(isDarkTheme ? 1 : 0).settings.intensity; motionDrawable.setPatternGiftPositions(pair.second.giftPatternPositions); motionDrawable.setGiftPatternRandomSeed(wallpaperRandomSeed); 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; } public TLRPC.WallPaper getCurrentWallpaper() { return wallpaper; } } private void updateBackground() { if (contentView == null || parentThemeDelegate != null) { return; } if (themeDelegate.backgroundDrawable != null && contentView.getBackgroundImage() != null) { return; } if (contentView.getBackgroundImage() == null || AndroidUtilities.isTablet()) { final Drawable drawable = Theme.getCachedWallpaper(); contentView.setBackgroundImage(drawable, Theme.isWallpaperMotion()); } } private void updateBotHelpCellClick(BotHelpCell cell) { final boolean translateButtonEnabled = MessagesController.getInstance(currentAccount).getTranslateController().isContextTranslateEnabled(); if (translateButtonEnabled && LanguageDetector.hasSupport()) { final CharSequence text = cell.getText(); LanguageDetector.detectLanguage(text == null ? "" : text.toString(), lang -> { String toLang = LocaleController.getInstance().getCurrentLocale().getLanguage(); if (lang != null && (!lang.equals(toLang) || lang.equals("und")) && !RestrictedLanguagesSelectActivity.getRestrictedLanguages().contains(lang)) { cell.setOnClickListener(e -> { ActionBarPopupWindow.ActionBarPopupWindowLayout layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext()); Drawable shadowDrawable2 = ContextCompat.getDrawable(getContext(), R.drawable.popup_fixed_alert).mutate(); shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); layout.setBackground(shadowDrawable2); final Runnable[] dismiss = new Runnable[1]; ActionBarMenuSubItem translateButton = new ActionBarMenuSubItem(getContext(), true, true); translateButton.setTextAndIcon(LocaleController.getString(R.string.TranslateMessage), R.drawable.msg_translate); translateButton.setOnClickListener(e2 -> { TranslateAlert2.showAlert(getContext(), this, currentAccount, lang, toLang, text, null, false, null, null); if (dismiss[0] != null) { dismiss[0].run(); } }); layout.addView(translateButton); ActionBarPopupWindow window = new ActionBarPopupWindow(layout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); dismiss[0] = () -> window.dismiss(); window.setPauseNotifications(true); window.setDismissAnimationDuration(220); window.setOutsideTouchable(true); window.setClippingEnabled(true); window.setAnimationStyle(R.style.PopupContextAnimation); window.setFocusable(true); window.showAsDropDown(cell, cell.getWidth() / 2 - AndroidUtilities.dp(90), AndroidUtilities.dp(-16), Gravity.BOTTOM | Gravity.LEFT); }); } else { cell.setClickable(false); } }, err -> { cell.setClickable(false); }); } else { cell.setClickable(false); } } @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 (isReport()) { 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; } if (actionBar == null) { return !Theme.isCurrentThemeDark(); } return AndroidUtilities.computePerceivedBrightness(actionBar.getBackgroundColor()) > 0.721f; } public MessageObject.GroupedMessages getGroup(long id) { return groupedMessagesMap.get(id); } private MessageSkeleton getNewSkeleton(boolean noAvatar) { MessageSkeleton skeleton = new MessageSkeleton(); if (currentChat != null && ChatObject.isChannelAndNotMegaGroup(currentChat)) { skeleton.height = AndroidUtilities.dp(128) + Utilities.fastRandom.nextInt(AndroidUtilities.dp(64)); } else { skeleton.height = AndroidUtilities.dp(64) + Utilities.fastRandom.nextInt(AndroidUtilities.dp(64)); } skeleton.width = (int) Math.min(chatListView.getWidth() * 0.8f - (noAvatar ? 0 : AndroidUtilities.dp(42)), AndroidUtilities.dp(42) + (0.4f + Utilities.fastRandom.nextFloat() * 0.35f) * chatListView.getWidth()); return skeleton; } @Override public SizeNotifierFrameLayout getContentView() { return contentView; } private final static class MessageSkeleton { int width; int height; int lastBottom; } private class RecyclerListViewInternal extends RecyclerListView implements StoriesListPlaceProvider.ClippedView { public RecyclerListViewInternal(Context context, ThemeDelegate themeDelegate) { super(context, themeDelegate); } @Override public void updateClip(int[] clip) { clip[0] = (int) chatListViewPaddingTop - AndroidUtilities.dp(4); clip[1] = chatListView.getMeasuredHeight() - (chatListView.getPaddingBottom() - AndroidUtilities.dp(3)); } } private void updateVisibleWallpaperActions() { if (chatListView != null && chatAdapter != null) { for (int i = 0; i < chatListView.getChildCount(); ++i) { View child = chatListView.getChildAt(i); int position = chatListView.getChildAdapterPosition(child) - chatAdapter.messagesStartRow; if (child instanceof ChatActionCell && position >= 0 && position < messages.size()) { MessageObject msg = messages.get(position); if (msg != null && msg.isWallpaperForBoth()) { ((ChatActionCell) child).setMessageObject(msg, true); } } } } } private void checkLeaveChannelButton() { if (headerItem == null || chatMode == MODE_SAVED) return; if (!headerItem.hasSubItem(delete_chat)) { if (!isTopic) { if (ChatObject.isChannel(currentChat) && !currentChat.creator) { if (!ChatObject.isNotInChat(currentChat)) { if (currentChat.megagroup) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveMegaMenu)); } else { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.LeaveChannelMenu)); } } } else if (!ChatObject.isChannel(currentChat)) { if (currentChat != null) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString(R.string.DeleteAndExit)); } else if (currentUser != null && currentUser.bot) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_text_RedRegular), getThemedColor(Theme.key_text_RedRegular)); } else { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString(R.string.DeleteChatUser)); } } } } } public boolean supportsThanosEffect() { return ThanosEffect.supports() && LiteMode.isEnabled(LiteMode.FLAG_CHAT_THANOS); } public ThanosEffect getChatThanosEffect() { if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_THANOS) || !ThanosEffect.supports()) { return null; } if (chatListThanosEffect == null || chatListThanosEffect.destroyed) { if (getContext() == null || !ThanosEffect.supports() || chatListView == null || contentView == null) { return null; } if (chatListThanosEffect != null) { AndroidUtilities.removeFromParent(chatListThanosEffect); } final ThanosEffect[] thisThanosEffect = new ThanosEffect[1]; final ThanosEffect thanosEffect = new ThanosEffect(getContext(), () -> { if (removingFromParent || thisThanosEffect[0] == null) { return; } ThanosEffect effect = thisThanosEffect[0]; thisThanosEffect[0] = null; if (chatListThanosEffect == effect) { chatListThanosEffect = null; } AndroidUtilities.removeFromParent(effect); }); thisThanosEffect[0] = chatListThanosEffect = thanosEffect; contentView.addView(thanosEffect, 1 + contentView.indexOfChild(chatListView), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } return chatListThanosEffect; } private StarReactionsOverlay starReactionsOverlay; public StarReactionsOverlay getStarReactionsOverlay() { if (starReactionsOverlay == null) { starReactionsOverlay = new StarReactionsOverlay(ChatActivity.this); } FrameLayout starReactionsOverlayParent = getLayoutContainer(); // if (LaunchActivity.instance != null) { // starReactionsOverlayParent = LaunchActivity.instance.frameLayout; // } if (starReactionsOverlayParent == null) { return null; } if (starReactionsOverlay.getParent() != starReactionsOverlayParent) { AndroidUtilities.removeFromParent(starReactionsOverlay); starReactionsOverlayParent.addView(starReactionsOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } else if (starReactionsOverlayParent.indexOfChild(starReactionsOverlay) < starReactionsOverlayParent.indexOfChild(fragmentView)) { starReactionsOverlay.bringToFront(); } return starReactionsOverlay; } private void checkGroupMessagesOrder() { if (!reversed) return; int groupStart = -1; long thisGroupId = 0; for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); long msgGroupId = msg.getGroupIdForUse(); if (thisGroupId != msgGroupId) { if (groupStart >= 0 && thisGroupId != 0 && i - groupStart > 1) { // thisGroup from groupStart to (i - 1) int count = i - groupStart; ArrayList groupMessages = new ArrayList<>(); for (int a = 0; a < count; ++a) { groupMessages.add(messages.remove(groupStart)); } Collections.sort(groupMessages, (a, b) -> b.getId() - a.getId()); messages.addAll(groupStart, groupMessages); } groupStart = i; thisGroupId = msgGroupId; } } if (groupStart >= 0 && thisGroupId != 0 && messages.size() - groupStart > 1) { // thisGroup from groupStart to (messages.size() - 1) int count = messages.size() - groupStart; ArrayList groupMessages = new ArrayList<>(); for (int a = 0; a < count; ++a) { groupMessages.add(messages.remove(groupStart)); } messages.addAll(groupStart, groupMessages); } } private void invalidatePremiumBlocked() { if (getDialogId() == getUserConfig().getClientUserId()) return; if (getUserConfig().isPremium()) return; if (currentUser == null || !currentUser.contact_require_premium) return; if (messages.isEmpty() == (getMessagesController().isUserContactBlocked(getDialogId()) != null)) return; getMessagesController().invalidateUserPremiumBlocked(getDialogId(), classGuid); } public boolean checkCanRemoveRestrictionsByBoosts() { boolean result = ChatObject.isPossibleRemoveChatRestrictionsByBoosts(chatInfo); if (result) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); LimitReachedBottomSheet.openBoostsForRemoveRestrictions(ChatActivity.this, boostsStatus, canApplyBoosts, dialog_id, false); } return result; } public void showPremiumFloodWaitBulletin(final boolean isUpload) { final long now = System.currentTimeMillis(); if (now - ConnectionsManager.lastPremiumFloodWaitShown < 1000L * MessagesController.getInstance(currentAccount).uploadPremiumSpeedupNotifyPeriod) { return; } ConnectionsManager.lastPremiumFloodWaitShown = now; if (UserConfig.getInstance(currentAccount).isPremium() || MessagesController.getInstance(currentAccount).premiumFeaturesBlocked()) { return; } final float n; if (isUpload) { n = MessagesController.getInstance(currentAccount).uploadPremiumSpeedupUpload; } else { n = MessagesController.getInstance(currentAccount).uploadPremiumSpeedupDownload; } SpannableString boldN = new SpannableString(Double.toString(Math.round(n * 10) / 10.0).replaceAll("\\.0$", "")); boldN.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, boldN.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); if (hasStoryViewer()) return; BulletinFactory.of(this).createSimpleBulletin( R.raw.speed_limit, LocaleController.getString(isUpload ? R.string.UploadSpeedLimited : R.string.DownloadSpeedLimited), AndroidUtilities.replaceCharSequence("%d", AndroidUtilities.premiumText(LocaleController.getString(isUpload ? R.string.UploadSpeedLimitedMessage : R.string.DownloadSpeedLimitedMessage), () -> { presentFragment(new PremiumPreviewFragment(isUpload ? "upload_speed" : "download_speed")); }), boldN) ).setDuration(8000).show(true); } public void didLongPressLink(ChatMessageCell cell, MessageObject messageObject, CharacterStyle span, String str) { final ItemOptions options = ItemOptions.makeOptions(ChatActivity.this, cell, true); final ScrimOptions dialog = new ScrimOptions(getContext(), themeDelegate); options.setOnDismiss(dialog::dismissFast); final boolean customTabs = SharedConfig.inappBrowser && !str.startsWith("video?") && !Browser.isInternalUri(Uri.parse(str), null); final boolean isHashtag = str.startsWith("#") || str.startsWith("$"); final boolean isMail = str.startsWith("mailto:"); if (!isMail) { options.add(R.drawable.msg_openin, getString(customTabs && !isHashtag ? R.string.OpenInTelegramBrowser : R.string.Open), () -> { if (str.startsWith("video?")) { didPressMessageUrl(span, false, messageObject, cell); } else if (customTabs && !isHashtag) { Browser.openInTelegramBrowser(getParentActivity(), str, null); } else { logSponsoredClicked(messageObject, false, false); openClickableLink(span, str, false, cell, messageObject, false); } }); } if (customTabs && !isHashtag || isMail) { options.add(R.drawable.msg_language, getString(R.string.OpenInSystemBrowser), () -> { Browser.openInExternalBrowser(getParentActivity(), str, false); }); } TLRPC.MessageMedia media = MessageObject.getMedia(messageObject); if (media instanceof TLRPC.TL_messageMediaWebPage && media.webpage != null && media.webpage.cached_page != null && TextUtils.equals(media.webpage.url, str)) { options.add(R.drawable.menu_instant_view, getString(R.string.OpenInstantView), () -> { if (messageObject.messageOwner.media != null && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { if (LaunchActivity.instance != null && LaunchActivity.instance.getBottomSheetTabs() != null && LaunchActivity.instance.getBottomSheetTabs().tryReopenTab(messageObject) != null) { return; } ChatActivity.this.createArticleViewer(false).open(messageObject); } }); } options.add(R.drawable.msg_copy, getString(isHashtag ? R.string.CopyHashtag : isMail ? R.string.CopyMail : R.string.CopyLink), () -> { 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; } } int timestamp = -1; if (str.startsWith("video?")) { timestamp = Utilities.parseInt(str); } if (DialogObject.isChatDialog(dialogId)) { TLRPC.Chat currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); String username = ChatObject.getPublicUsername(currentChat); if (currentChat != null && username != null) { link = "https://t.me/" + username + "/" + messageId + "?t=" + AndroidUtilities.formatTimestamp(timestamp); } } else { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); String username = UserObject.getPublicUsername(user); if (user != null && username != null) { link = "https://t.me/" + username + "/" + messageId + "?t=" + AndroidUtilities.formatTimestamp(timestamp); } } if (link == null) { return; } AndroidUtilities.addToClipboard(link); } else if (isMail) { AndroidUtilities.addToClipboard(str.substring("mailto:".length())); } else { AndroidUtilities.addToClipboard(str); } createUndoView(); if (undoView == null) { return; } 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); } }); dialog.setItemOptions(options); if (str != null && str.startsWith("mailto:")) { SpannableString s = new SpannableString(str.substring(7)); s.setSpan(span, 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); dialog.setScrim(cell, span, s); } else if (span instanceof URLSpanReplacement) { String formattedUrl = ((URLSpanReplacement) span).getURL(); try { try { Uri uri = Uri.parse(formattedUrl); formattedUrl = Browser.replaceHostname(uri, Browser.IDN_toUnicode(uri.getHost()), null); } catch (Exception e) { FileLog.e(e, false); } formattedUrl = URLDecoder.decode(formattedUrl.replaceAll("\\+", "%2b"), "UTF-8"); } catch (Exception e) { FileLog.e(e); } if (formattedUrl.length() > 204) { formattedUrl = formattedUrl.substring(0, 204) + "…"; } SpannableString s = new SpannableString(formattedUrl); s.setSpan(span, 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); dialog.setScrim(cell, span, s); } else { dialog.setScrim(cell, span, null); } showDialog(dialog); } public void didLongPressCard(ChatMessageCell cell, CharacterStyle link, String card) { final Browser.Progress progress = makeProgressForLink(cell, link); TLRPC.TL_payments_getBankCardData req = new TLRPC.TL_payments_getBankCardData(); req.number = card; int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { progress.end(); final ItemOptions options = ItemOptions.makeOptions(ChatActivity.this, cell, true); final ScrimOptions dialog = new ScrimOptions(getContext(), themeDelegate); options.setOnDismiss(dialog::dismissFast); options.add(R.drawable.msg_copy, getString(R.string.CopyCardNumber), () -> { dialog.dismiss(); AndroidUtilities.addToClipboard(card); BulletinFactory.of(ChatActivity.this).createCopyBulletin(getString(R.string.CardNumberCopied)).show(); }); if (res instanceof TLRPC.TL_payments_bankCardData) { TLRPC.TL_payments_bankCardData i = (TLRPC.TL_payments_bankCardData) res; for (TLRPC.TL_bankCardOpenUrl d : i.open_urls) { options.add(R.drawable.msg_payment_card, d.name, () -> { Browser.openUrl(getContext(), d.url, inlineReturn == 0, false); }); } if (!TextUtils.isEmpty(i.title)) { options.addGap(); options.addText(i.title, 13, dp(200)); } } dialog.setItemOptions(options); dialog.setScrim(cell, link, null); showDialog(dialog); }), null, null, 0, getMessagesController().webFileDatacenterId, ConnectionsManager.ConnectionTypeGeneric, true); progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId, true)); progress.init(); } public void didLongPressUsername(ChatMessageCell cell, CharacterStyle link, String username) { final Browser.Progress progress = makeProgressForLink(cell, link); TLObject cachedObject = getMessagesController().getUserOrChat(username); Utilities.Callback2 open = (obj, selling) -> { progress.end(); boolean isUser = false, isGroup = false, isChannel = false; final long did; if (obj instanceof TLRPC.User) { did = ((TLRPC.User) obj).id; isUser = true; } else if (obj instanceof TLRPC.Chat) { did = -((TLRPC.Chat) obj).id; isChannel = ChatObject.isChannelAndNotMegaGroup((TLRPC.Chat) obj); isGroup = !isChannel; } else did = 0; final ItemOptions options = ItemOptions.makeOptions(ChatActivity.this, cell, true); final ScrimOptions dialog = new ScrimOptions(getContext(), themeDelegate); options.setOnDismiss(dialog::dismissFast); if (did != 0) { options.add(isChannel ? R.drawable.msg_channel : R.drawable.msg_discussion, getString(isChannel ? R.string.ViewChannel : R.string.SendMessage), () -> { presentFragment(ChatActivity.of(did)); }); } options.add(R.drawable.msg_copy, getString(R.string.ProfileCopyUsername), () -> { dialog.dismiss(); AndroidUtilities.addToClipboard("@" + username); BulletinFactory.of(ChatActivity.this).createCopyBulletin(getString(R.string.UsernameCopied)).show(); }); if (selling) { options.add(R.drawable.msg_ton, getString(R.string.BuyUsernameOnFragment), () -> { Browser.openUrl(getContext(), "https://fragment.com/username/" + username); }); } options.addGap(); if (did != 0) { options.addProfile(obj, getString(isUser ? R.string.ViewProfile : (isChannel ? R.string.ViewChannelProfile : R.string.ViewGroupProfile)), () -> { presentFragment(ProfileActivity.of(did)); }); } else { options.addText(getString(R.string.NoUsernameFound2), 13, dp(200)); } dialog.setItemOptions(options); dialog.setScrim(cell, link, null); showDialog(dialog); }; if (true || BuildVars.DEBUG_PRIVATE_VERSION) { TL_account.checkUsername req2 = new TL_account.checkUsername(); req2.username = username; int reqId2 = getConnectionsManager().sendRequest(req2, (res2, err2) -> AndroidUtilities.runOnUIThread(() -> { final boolean selling = err2 != null && "USERNAME_PURCHASE_AVAILABLE".equals(err2.text); if (cachedObject != null || err2 == null && res2 instanceof TLRPC.TL_boolTrue) { open.run(cachedObject, selling); } else { TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); req.username = username; int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { progress.end(); TLObject obj = null; if (res instanceof TLRPC.TL_contacts_resolvedPeer) { TLRPC.TL_contacts_resolvedPeer r = (TLRPC.TL_contacts_resolvedPeer) res; getMessagesController().putUsers(r.users, false); getMessagesController().putChats(r.chats, false); long did = DialogObject.getPeerDialogId(r.peer); if (did >= 0) { obj = getMessagesController().getUser(did); } else if (did < 0) { obj = getMessagesController().getChat(-did); } } open.run(obj, selling); })); progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId, true)); progress.init(); } })); progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId2, true)); progress.init(); } else { if (cachedObject != null) { open.run(cachedObject, false); } else { TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); req.username = username; int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { progress.end(); TLObject obj = null; if (res instanceof TLRPC.TL_contacts_resolvedPeer) { TLRPC.TL_contacts_resolvedPeer r = (TLRPC.TL_contacts_resolvedPeer) res; getMessagesController().putUsers(r.users, false); getMessagesController().putChats(r.chats, false); long did = DialogObject.getPeerDialogId(r.peer); if (did >= 0) { obj = getMessagesController().getUser(did); } else if (did < 0) { obj = getMessagesController().getChat(-did); } } open.run(obj, false); })); progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId, true)); progress.init(); } } } public void didLongPressCopyButton(String text) { BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, themeDelegate); builder.setTitle(text); builder.setTitleMultipleLines(true); builder.setItems(new CharSequence[] { getString(R.string.Copy) }, (dialog, which) -> { AndroidUtilities.addToClipboard(text); BulletinFactory.of(ChatActivity.this).createCopyBulletin(formatString(R.string.ExactTextCopied, text)).show(); }); showDialog(builder.create()); } public void didPressPhoneNumber(ChatMessageCell cell, CharacterStyle link, String phone) { final Browser.Progress progress = makeProgressForLink(cell, link); final TLRPC.TL_contact contact = getContactsController().contactsByPhone.get(PhoneFormat.stripExceptNumbers(phone)); Utilities.Callback open = user -> { TLRPC.UserFull userInfo = user != null ? getMessagesController().getUserFull(user.id) : null; final ItemOptions options = ItemOptions.makeOptions(ChatActivity.this, cell, true); final ScrimOptions dialog = new ScrimOptions(getContext(), themeDelegate); options.setOnDismiss(dialog::dismiss); Utilities.Callback addToContacts = asNew -> { if (getParentActivity() == null) return; Intent intent; if (asNew) { intent = new Intent(ContactsContract.Intents.Insert.ACTION); intent.setType(ContactsContract.RawContacts.CONTENT_TYPE); } else { intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE); } if (user != null) { intent.putExtra(ContactsContract.Intents.Insert.NAME, ContactsController.formatName(user.first_name, user.last_name)); } ArrayList data = new ArrayList<>(); ContentValues row = new ContentValues(); row.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); String thisPhone = phone; if (!thisPhone.startsWith("+")) { TLRPC.User myself = getUserConfig().getCurrentUser(); HashMap> codesMap = new HashMap<>(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(ApplicationLoader.applicationContext.getResources().getAssets().open("countries.txt"))); String line; while ((line = reader.readLine()) != null) { String[] args = line.split(";"); CountrySelectActivity.Country countryWithCode = new CountrySelectActivity.Country(); countryWithCode.name = args[2]; countryWithCode.code = args[0]; countryWithCode.shortname = args[1]; List countryList = codesMap.get(args[0]); if (countryList == null) { codesMap.put(args[0], countryList = new ArrayList<>()); } countryList.add(countryWithCode); } reader.close(); } catch (Exception e) { FileLog.e(e); } boolean foundCountry = false; String myphone = myself.phone; for (int a = 4; a >= 1; a--) { String sub = myphone.substring(0, a); List country = codesMap.get(sub); if (country != null && country.size() > 0) { final String regionCode = country.get(0).code; if (regionCode.endsWith("0") && thisPhone.startsWith("0")) { thisPhone = thisPhone.substring(1); } thisPhone = "+" + regionCode + thisPhone; foundCountry = true; break; } } if (!foundCountry && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { final Context ctx = ApplicationLoader.applicationContext; final String regionCode = (ctx != null) ? ctx.getSystemService(TelephonyManager.class). getSimCountryIso().toUpperCase(Locale.US) : Locale.getDefault().getCountry(); if (regionCode.endsWith("0") && thisPhone.startsWith("0")) { thisPhone = thisPhone.substring(1); } thisPhone = "+" + regionCode + thisPhone; } } row.put(ContactsContract.CommonDataKinds.Phone.NUMBER, thisPhone); row.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); data.add(row); intent.putExtra("finishActivityOnSaveCompleted", true); intent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, data); getParentActivity().startActivity(intent); }; ItemOptions subOptions = options.makeSwipeback(); subOptions.add(R.drawable.ic_ab_back, getString(R.string.Back), options::closeSwipeback); subOptions.addGap(); subOptions.add(R.drawable.msg_addbot, getString(R.string.CreateNewContact), () -> { options.dismiss(); NewContactBottomSheet sheet = new NewContactBottomSheet(this, getContext()).setInitialPhoneNumber(phone, false); sheet.show(); }); subOptions.add(R.drawable.menu_contact_existing, getString(R.string.AddToExistingContact), () -> addToContacts.run(false)); if (contact == null && (user == null || !getContactsController().contactsDict.containsKey(user.id))) { options.add(R.drawable.msg_contact_add, getString(R.string.AddToContacts), () -> options.openSwipeback(subOptions)); options.addGap(); } if (user == null) { options.add(R.drawable.menu_invit_telegram, getString(R.string.InviteToTelegramShort), () -> { if (getParentActivity() == null) return; try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromParts("sms", phone, null)); intent.putExtra("sms_body", ContactsController.getInstance(currentAccount).getInviteText(1)); getParentActivity().startActivityForResult(intent, 500); } catch (Exception e) { FileLog.e(e); } }); options.add(R.drawable.msg_calls_regular, getString(R.string.VoiceCallViaCarrier), () -> { Browser.openUrl(getContext(), "tel:" + phone); }); options.add(R.drawable.msg_copy, getString(R.string.CopyNumber), () -> { AndroidUtilities.addToClipboard(phone); BulletinFactory.of(this).createCopyBulletin(LocaleController.getString(R.string.PhoneCopied)).show(); }); options.addGap(); options.addText(getString(R.string.NumberNotOnTelegram), 13); } else { options.add(R.drawable.msg_discussion, getString(R.string.SendMessage), () -> presentFragment(ChatActivity.of(user.id))); if (!UserObject.isUserSelf(user)) { options.add(R.drawable.msg_calls, getString(R.string.VoiceCallViaTelegram), () -> { VoIPHelper.startCall(user, false, userInfo != null && userInfo.video_calls_available, getParentActivity(), userInfo, getAccountInstance()); }); options.add(R.drawable.msg_videocall, getString(R.string.VideoCallViaTelegram), () -> { VoIPHelper.startCall(user, true, userInfo != null && userInfo.video_calls_available, getParentActivity(), userInfo, getAccountInstance()); }); } options.add(R.drawable.msg_calls_regular, getString(R.string.VoiceCallViaCarrier), () -> { Browser.openUrl(getContext(), "tel:" + phone); }); options.add(R.drawable.msg_copy, getString(R.string.CopyNumber), () -> { AndroidUtilities.addToClipboard(phone); BulletinFactory.of(this).createCopyBulletin(LocaleController.getString(R.string.PhoneCopied)).show(); }); options.addGap(); options.addProfile(user, getString(R.string.ViewProfile), () -> { dialog.dismiss(); presentFragment(ProfileActivity.of(user.id)); }); } dialog.setItemOptions(options); dialog.setScrim(cell, link, null); showDialog(dialog); }; if (contact != null) { TLRPC.User user = getMessagesController().getUser(contact.user_id); if (user != null) { open.run(user); } else { getMessagesStorage().getStorageQueue().postRunnable(() -> { TLRPC.User user2 = getMessagesStorage().getUser(contact.user_id); AndroidUtilities.runOnUIThread(() -> open.run(user2)); }); } } else { TLRPC.TL_contacts_resolvePhone req = new TLRPC.TL_contacts_resolvePhone(); req.phone = PhoneFormat.stripExceptNumbers(phone); int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { progress.end(); TLRPC.User user = null; if (res instanceof TLRPC.TL_contacts_resolvedPeer) { TLRPC.TL_contacts_resolvedPeer r = (TLRPC.TL_contacts_resolvedPeer) res; getMessagesController().putUsers(r.users, false); getMessagesController().putChats(r.chats, false); long did = DialogObject.getPeerDialogId(r.peer); if (did >= 0) { user = getMessagesController().getUser(did); } } open.run(user); })); progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId, true)); progress.init(); } } public class FirstViewPage extends View { private final ArrayList views = new ArrayList<>(); private final ArrayList viewsToMakeVisible = new ArrayList<>(); public FirstViewPage(Context context) { super(context); } private void updateViews() { views.clear(); views.add(topChatPanelView); views.add(topChatPanelView2); views.add(chatListView); views.add(messagesSearchListContainer); views.add(mentionContainer); views.add(floatingDateView); views.add(chatActivityEnterView); views.add(sideControlsButtonsLayout); views.add(chatInputViewsContainer); views.removeAll(Collections.singleton(null)); } @Override public void setTranslationX(float translationX) { super.setTranslationX(translationX); updateViews(); for (View view : views) { if (view != null) { view.setTranslationX(translationX); } } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); for (View view : viewsToMakeVisible) { view.setVisibility(View.VISIBLE); } viewsToMakeVisible.clear(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); updateViews(); for (View view : views) { if (view.getVisibility() == View.VISIBLE) { view.setVisibility(View.GONE); viewsToMakeVisible.add(view); } } } @Override public boolean dispatchTouchEvent(MotionEvent event) { return false; } } private void checkHashtagStories(boolean instant) { if (searchType != SEARCH_PUBLIC_POSTS) return; if (messagesSearchAdapter == null) return; messagesSearchAdapter.searchStories(searchingHashtag, instant); } public float getClipTop() { return chatListView.getY() + ((fragmentTransition == null || (fromPullingDownTransition && !toPullingDownTransition)) && !isInsideContainer ? chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4) : 0); } public float getClipBottom() { return fragmentView.getBottom() - chatListView.getBottom() + ((fragmentTransition == null || (fromPullingDownTransition && !toPullingDownTransition)) && !isInsideContainer ? blurredViewBottomOffset : 0); } private void gotChatInfo() { if (chatInfo != null && chatInfo.paid_reactions_available) { getMessagesController().getPaidReactionsDialogId(); if (!StarsController.getInstance(currentAccount).balanceAvailable()) { StarsController.getInstance(currentAccount).getBalance(); } } if (chatInfo != null && chatInfo.bot_verification != null) { updateTopPanel(true); } if (chatInfo != null) { final boolean giftUpdate = (chatInfo.stargifts_available) != (bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.isButtonVisible(ChatActivityChannelButtonsLayout.BUTTON_GIFT)); final boolean suggestUpdate = (currentChat != null && currentChat.broadcast_messages_allowed && currentChat.linked_monoforum_id != 0) != (bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.isButtonVisible(ChatActivityChannelButtonsLayout.BUTTON_DIRECT)); if (giftUpdate || suggestUpdate) { updateBottomOverlay(true); } } } @Override public boolean allowFinishFragmentInsteadOfRemoveFromStack() { return !inPreviewMode; } public int getHashtagTabsHeight() { ChatActivity chatActivity = parentChatActivity != null ? parentChatActivity : this; if (chatActivity.hashtagSearchTabs == null) return 0; return chatActivity.hashtagSearchTabs.getCurrentHeight(); } public void didPressReaction(View cell, TLRPC.ReactionCount reaction, boolean longpress, float x, float y) { if (getParentActivity() == null || getContext() == null) { return; } if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); } if (videoConversionTimeHint != null && videoConversionTimeHint.shown()) { videoConversionTimeHint.hide(); } MessageObject messageObject; if (cell instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) cell).getPrimaryMessageObject(); } else if (cell instanceof ChatActionCell) { messageObject = ((ChatActionCell) cell).getMessageObject(); } else { return; } if (messageObject == null) return; if (getUserConfig().getClientUserId() == getDialogId() && messageObject.areTags() && !getUserConfig().isPremium()) { if (longpress) return; new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_SAVED_TAGS, true).show(); return; } if (longpress && reaction.reaction instanceof TLRPC.TL_reactionPaid) { cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); ArrayList reactors = null; if (messageObject.messageOwner != null && messageObject.messageOwner.reactions != null) { reactors = messageObject.messageOwner.reactions.top_reactors; } StarsController.getInstance(currentAccount).commitPaidReaction(); TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-StarsController.MessageId.from(messageObject).did); final StarsReactionsSheet sheet = new StarsReactionsSheet(getContext(), currentAccount, dialog_id, ChatActivity.this, messageObject, reactors, chatFull == null || chatFull.paid_reactions_available, false, 0, themeDelegate); sheet.setMessageCell(ChatActivity.this, messageObject.getId(), findMessageCell(messageObject.getId(), true)); sheet.show(); return; } if (longpress || messageObject.areTags() && (isInsideContainer || searchingReaction != null && searchingReaction.isSame(reaction.reaction))) { 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)); } Path path = new Path(); @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); path.rewind(); path.addRoundRect(AndroidUtilities.dp(8), AndroidUtilities.dp(8), getWidth() - AndroidUtilities.dp(8), getHeight() - AndroidUtilities.dp(8), AndroidUtilities.dp(6), AndroidUtilities.dp(6), Path.Direction.CW); canvas.clipPath(path); super.dispatchDraw(canvas); canvas.restore(); } }; scrimPopupContainerLayout.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); final ReactionsLayoutInBubble.VisibleReaction reactionObj = ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction); ReactionsLayoutInBubble.ReactionButton button = null; ReactionsLayoutInBubble reactionsLayoutInBubble; if (cell instanceof ChatMessageCell) { reactionsLayoutInBubble = ((ChatMessageCell) cell).reactionsLayoutInBubble; button = reactionsLayoutInBubble.getReactionButton(reactionObj); } else if (cell instanceof ChatActionCell) { reactionsLayoutInBubble = ((ChatActionCell) cell).reactionsLayoutInBubble; button = reactionsLayoutInBubble.getReactionButton(reactionObj); } else return; if (button == null) { return; } Rect backgroundPaddings = new Rect(); Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); shadowDrawable2.getPadding(backgroundPaddings); scrimPopupContainerLayout.setBackground(shadowDrawable2); float bottom = reactionsLayoutInBubble.y + button.y + AndroidUtilities.dp(28); float left = reactionsLayoutInBubble.x + button.x; int[] loc = new int[2]; cell.getLocationInWindow(loc); boolean forceBottom = false; final boolean tags = getUserConfig().getClientUserId() == getDialogId() && !getMessagesController().getSavedMessagesController().unsupported; if (tags) { MessagesController.getGlobalMainSettings().edit().putInt("savedsearchtaghint", 1).apply(); ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), 0, getResourceProvider(), 0); if (getUserConfig().isPremium()) { ActionBarMenuSubItem editTag = new ActionBarMenuSubItem(getParentActivity(), false, false); editTag.setTextAndIcon(LocaleController.getString(TextUtils.isEmpty(getMessagesController().getSavedTagName(reaction.reaction)) ? R.string.SavedTagLabelTag : R.string.SavedTagRenameTag), R.drawable.menu_tag_rename); editTag.setMinimumWidth(160); editTag.setOnClickListener(view -> { closeMenu(); SearchTagsList.openRenameTagAlert(getContext(), currentAccount, reaction.reaction, themeDelegate, false); }); popupLayout.addView(editTag); } if (!isInsideContainer && (searchingReaction == null || !searchingReaction.isSame(reaction.reaction)) && (chatMode == 0 || chatMode == MODE_SAVED)) { ActionBarMenuSubItem filterByTag = new ActionBarMenuSubItem(getParentActivity(), false, false); filterByTag.setTextAndIcon(LocaleController.getString(R.string.SavedTagFilterByTag), R.drawable.menu_tag_filter); filterByTag.setMinimumWidth(160); filterByTag.setOnClickListener(view -> { closeMenu(); openSearchWithText(""); if (actionBarSearchTags != null) { actionBarSearchTags.setChosen(ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction), true); } }); popupLayout.addView(filterByTag); } ActionBarMenuSubItem removeTag = new ActionBarMenuSubItem(getParentActivity(), false, false); removeTag.setTextAndIcon(LocaleController.getString(R.string.SavedTagRemoveTag), R.drawable.menu_tag_delete); removeTag.setMinimumWidth(160); removeTag.setOnClickListener(view -> { pressedReaction(cell, reaction, 0, 0); }); removeTag.setColors(Theme.getColor(Theme.key_color_red), Theme.getColor(Theme.key_color_red)); popupLayout.addView(removeTag); scrimPopupContainerLayout.addView(popupLayout); } else if (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.reactions != null && messageObject.messageOwner.reactions.can_see_list || dialog_id >= 0) { if (reaction.reaction instanceof TLRPC.TL_reactionCustomEmoji) { button.stopAnimation(); } scrimPopupContainerLayout.addView(new ReactedUsersListView(getParentActivity(), themeDelegate, currentAccount, messageObject, reaction, false, false) .setOnCustomEmojiSelectedListener((reactedUsersListView1, customEmojiStickerSets) -> { if (getParentActivity() == null || getContext() == null) return; EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, customEmojiStickerSets) { @Override public void dismiss() { super.dismiss(); dimBehindView(false); } }; alert.setCalcMandatoryInsets(isKeyboardVisible()); alert.setDimBehind(false); closeMenu(false); showDialog(alert); }) .setOnProfileSelectedListener((view1, userId, messagePeerReaction) -> { Bundle args = new Bundle(); if (userId > 0) { args.putLong("user_id", userId); } else { args.putLong("chat_id", -userId); } args.putInt("report_reaction_message_id", messageObject.getId()); args.putLong("report_reaction_from_dialog_id", dialog_id); ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); }), LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); } else if (reaction.reaction instanceof TLRPC.TL_reactionCustomEmoji) { TLRPC.TL_reactionCustomEmoji customEmoji = (TLRPC.TL_reactionCustomEmoji) reaction.reaction; TLRPC.InputStickerSet inputStickerSet = AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).findStickerSet(customEmoji.document_id); if (inputStickerSet != null) { button.stopAnimation(); ArrayList arr = new ArrayList(); arr.add(inputStickerSet); MessageContainsEmojiButton setButton = new MessageContainsEmojiButton(currentAccount, getContext(), themeDelegate, arr, MessageContainsEmojiButton.SINGLE_REACTION_TYPE); setButton.setOnClickListener(v -> { if (getParentActivity() == null || getContext() == null) return; new EmojiPacksAlert(ChatActivity.this, getContext(), themeDelegate, arr).show(); closeMenu(); }); scrimPopupContainerLayout.addView(setButton, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT)); forceBottom = true; } else { scrimPopupContainerLayout.setVisibility(View.GONE); } } else { scrimPopupContainerLayout.setVisibility(View.GONE); } 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() != 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) { float cellY = chatListView.getY() + cell.getY(); if (isInsideContainer) { int[] location = new int[2]; cell.getLocationInWindow(location); cellY = location[1]; } if (height < totalHeight / 2f && cellY + reactionsLayoutInBubble.y + button.y > totalHeight / 2f && !forceBottom) { scrimViewReactionOffset = -(height - dp(12)); popupY = (int) (cellY + reactionsLayoutInBubble.y + button.y - height); } else { scrimViewReactionOffset = 0; popupY = (int) (cellY + reactionsLayoutInBubble.y + button.y + button.height); } } else { scrimViewReactionOffset = 0; popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; } if (scrimPopupContainerLayout.getVisibility() != View.VISIBLE) { scrimViewReactionOffset = 0; } scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, scrimPopupX = popupX, scrimPopupY = popupY); chatListView.stopScroll(); chatLayoutManager.setCanScrollVertically(false); scrimViewTask = null; scrimViewReaction = reaction.reaction.hashCode(); scrimViewReactionAnimated = reaction.reaction instanceof TLRPC.TL_reactionCustomEmoji && LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD); dimBehindView(cell, !tags, true); hideHints(false); if (topUndoView != null) { topUndoView.hide(true, 1); } if (undoView != null) { undoView.hide(true, 1); } if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(false); } } else if (messageObject.areTags() && (chatMode == 0 || chatMode == MODE_SAVED)) { closeMenu(); openSearchWithText(""); if (actionBarSearchTags != null) { actionBarSearchTags.setChosen(ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction), true); } } else if (reaction != null) { pressedReaction(cell, reaction, x, y); } } private void pressedReaction(View cell, TLRPC.ReactionCount reaction, float x, float y) { ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(reaction.reaction); MessageObject messageObject; if (cell instanceof ChatMessageCell) { messageObject = ((ChatMessageCell) cell).getPrimaryMessageObject(); } else if (cell instanceof ChatActionCell) { messageObject = ((ChatActionCell) cell).getMessageObject(); } else return; selectReaction(cell, messageObject, null, null, x, y, visibleReaction,false, false, false, false); if (messageObject != null & messageObject.messageOwner != null) { if (chatAdapter.isFiltered) { MessageObject realMessage = messagesDict[0].get(messageObject.getId()); if (realMessage != null && realMessage.messageOwner != null) { realMessage.messageOwner.reactions = messageObject.messageOwner.reactions; } } else if (!chatAdapter.isFiltered && searchingReaction != null) { updateFilteredMessages(false); } } if (chatAdapter.isFiltered && !messageObject.hasReaction(searchingReaction)) { final MessageObject msg = messageObject; final MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(msg); if (groupedMessages != null) { for (int i = 0; i < groupedMessages.messages.size(); ++i) { MessageObject gmsg = groupedMessages.messages.get(i); getMediaDataController().removeMessageFromResults(gmsg.getId()); } } else { getMediaDataController().removeMessageFromResults(msg.getId()); } if (messagesSearchAdapter != null) { messagesSearchAdapter.notifyDataSetChanged(); } updateFilteredMessages(true); } } private int findAdPlace() { final ArrayList cachedApproximateHeight = new ArrayList<>(messages.size()); final int unreadRow = messages.indexOf(unreadMessageObject); int unreadY = -1; int unreadOffset = 0; final ArrayList adsY = new ArrayList<>(); final ArrayList adsIndices = new ArrayList<>(); final ArrayList adsIndexOffset = new ArrayList<>(); final HashSet groupIds = new HashSet<>(); int y = 0, o = 0; for (int i = 0; i < messages.size(); ++i) { final MessageObject msg = messages.get(i); final int h = msg.getApproximateHeightCached(); cachedApproximateHeight.add(h); if (msg.isSponsored() || i == unreadRow) { if (i == unreadRow) { unreadY = y; } adsIndices.add(i); adsY.add(y); adsIndexOffset.add(o); } if (!msg.hasValidGroupIdFast()) { o++; y += h; } else if (!groupIds.contains(msg.getGroupId())) { groupIds.add(msg.getGroupId()); o++; y += h; } } if (adsIndices.size() - (unreadRow >= 0 ? 1 : 0) <= 0) { return 0; } y = unreadY; o = unreadOffset; groupIds.clear(); for (int i = unreadRow; i >= 0; --i) { final MessageObject msg = messages.get(i); final int h = cachedApproximateHeight.get(i); if (!msg.hasValidGroupIdFast()) { o--; y -= h; } else if (!groupIds.contains(msg.getGroupId())) { groupIds.add(msg.getGroupId()); o--; y -= h; } if (msg.isSponsored() || msg.hasValidGroupIdFast() || msg == unreadMessageObject) continue; int t = -1, ty = -1, to = -1; int b = -1, by = -1, bo = -1; for (int j = 0; j < adsIndices.size(); ++j) { int idx = adsIndices.get(j); if (idx >= i && (t == -1 || t > idx)) { t = idx; ty = adsY.get(j); to = adsIndexOffset.get(j); } if (idx <= i && (b == -1 || b < idx)) { b = idx; by = adsY.get(j); bo = adsIndexOffset.get(j); } } if ( (t == -1 || Math.abs(t - i) > sponsoredMessagesPostsBetween + 1 && Math.abs(to - o) > sponsoredMessagesPostsBetween + 1 && Math.abs(ty - (y + h)) > AndroidUtilities.displaySize.y) && (b == -1 || Math.abs(b - i) > sponsoredMessagesPostsBetween + 1 && Math.abs(bo - o) > sponsoredMessagesPostsBetween + 1 && Math.abs(by - y) > AndroidUtilities.displaySize.y) ) { return i; } } y = 0; o = 0; groupIds.clear(); for (int i = 0; i < messages.size(); ++i) { MessageObject msg = messages.get(i); final int h = cachedApproximateHeight.get(i); if (!msg.hasValidGroupIdFast()) { o++; y += h; } else if (!groupIds.contains(msg.getGroupId())) { groupIds.add(msg.getGroupId()); o++; } if (msg.isSponsored() || msg.hasValidGroupIdFast() || msg == unreadMessageObject) continue; int t = -1, ty = -1, to = -1; int b = -1, by = -1, bo = -1; for (int j = 0; j < adsIndices.size(); ++j) { int idx = adsIndices.get(j); if (idx >= i && (t == -1 || t > idx)) { t = idx; ty = adsY.get(j); to = adsIndexOffset.get(j); } if (idx <= i && (b == -1 || b < idx)) { b = idx; by = adsY.get(j); bo = adsIndexOffset.get(j); } } if ( (t == -1 || Math.abs(t - i) >= sponsoredMessagesPostsBetween + 1 && Math.abs(to - o) >= sponsoredMessagesPostsBetween + 1 && Math.abs(ty - (y + h)) > AndroidUtilities.displaySize.y) && (b == -1 || Math.abs(b - i) >= sponsoredMessagesPostsBetween + 1 && Math.abs(bo - o) >= sponsoredMessagesPostsBetween + 1 && Math.abs(by - y) > AndroidUtilities.displaySize.y) ) { return i; } } return -1; } public void fillMessageMenu( MessageObject primaryMessage, ArrayList icons, ArrayList items, ArrayList options ) { final MessageObject message = selectedObject; final MessageObject.GroupedMessages groupedMessages = selectedObjectGroup; final int type = getMessageType(message); boolean allowChatActions = true; boolean allowPin; if (chatMode == MODE_SAVED || chatMode == MODE_QUICK_REPLIES) { allowPin = false; } else if (chatMode == MODE_SCHEDULED || (isThreadChat() && !isTopic)) { allowPin = false; } else if (currentChat != null) { allowPin = message.getDialogId() != mergeDialogId && ChatObject.canPinMessages(currentChat) && (!currentChat.monoforum /*|| ChatObject.canManageMonoForum(currentAccount, 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; } if (UserObject.isReplyUser(dialog_id) || dialog_id == UserObject.VERIFY) { allowPin = false; } allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION; boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards || getDialogId() == UserObject.VERIFY; boolean noforwardsOrPaidMedia = noforwards || message.type == MessageObject.TYPE_PAID_MEDIA; boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())) && !message.isExpiredStory(); boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId && message.type != MessageObject.TYPE_STORY && message.type != MessageObject.TYPE_POLL; 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 (message.isExpiredStory() || 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 || bottomChannelButtonsLayout != null && bottomChannelButtonsLayout.getVisibility() == View.VISIBLE && !(bottomOverlayChatWaitsReply && selectedObject != null && (MessageObject.getTopicId(currentAccount, selectedObject.messageOwner, ChatObject.isForum(currentChat)) != 0 || selectedObject.wasJustSent))) { allowChatActions = false; } if (currentChat != null && (ChatObject.isNotInChat(currentChat) && !ChatObject.isMonoForum(currentChat) && !isThreadChat())) { allowChatActions = false; } if (currentChat != null && (ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup)) { allowChatActions = false; } if (currentChat != null && (!ChatObject.canSendMessages(currentChat))) { allowChatActions = false; } if (message.isSponsored() && !getUserConfig().isPremium() && !getMessagesController().premiumFeaturesBlocked() && !message.sponsoredCanReport) { items.add(LocaleController.getString(R.string.HideAd)); options.add(OPTION_HIDE_SPONSORED_MESSAGE); icons.add(R.drawable.msg_block2); } if (message.isSponsored() && message.sponsoredCanReport) { items.add(LocaleController.getString(R.string.AboutRevenueSharingAds)); options.add(OPTION_ABOUT_REVENUE_SHARING_ADS); icons.add(R.drawable.msg_report); items.add(LocaleController.getString(R.string.ReportAd)); options.add(OPTION_REPORT_AD); icons.add(R.drawable.msg_block2); if (!getMessagesController().premiumFeaturesBlocked()) { items.add(getString(R.string.RemoveAds)); options.add(OPTION_REMOVE_ADS); icons.add(R.drawable.msg_cancel); } } final @DrawableRes int deleteIconRes; if (selectedObject.isPaidSuggestedPostProtected()) { deleteIconRes = R.drawable.menu_delete_paid; } else if (selectedObject.messageOwner.ttl_period != 0) { deleteIconRes = R.drawable.msg_delete_auto; } else { deleteIconRes = R.drawable.msg_delete; } if (type == -1) { if ((selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.isAnimatedEmoji() || selectedObject.isAnimatedEmojiStickers() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwardsOrPaidMedia && !message.isExpiredStory()) { items.add(LocaleController.getString(R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString(R.string.CancelSending)); options.add(OPTION_CANCEL_SENDING); icons.add(R.drawable.msg_delete); } else if (type == 0) { items.add(LocaleController.getString(R.string.Retry)); options.add(OPTION_RETRY); icons.add(R.drawable.msg_retry); items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(deleteIconRes); } else if (type == 1) { if (currentChat != null) { if (allowChatActions && !isInsideContainer) { items.add(LocaleController.getString(R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.menu_reply); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && primaryMessage != null && primaryMessage.hasReplies() && currentChat.megagroup && primaryMessage.canViewThread()) { items.add(LocaleController.formatPluralString("ViewReplies", primaryMessage.getRepliesCount())); options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.msg_viewreplies); } if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.action == null && currentChat != null && currentChat.forum && !isTopic && selectedObject.messageOwner != null && selectedObject.messageOwner.reply_to != null && selectedObject.messageOwner.reply_to.forum_topic) { items.add(LocaleController.getString(R.string.ViewInTopic)); options.add(OPTION_VIEW_IN_TOPIC); icons.add(R.drawable.msg_viewintopic); } if (allowUnpin) { items.add(LocaleController.getString(R.string.UnpinMessage)); options.add(OPTION_UNPIN); icons.add(R.drawable.msg_unpin); } else if (allowPin) { items.add(LocaleController.getString(R.string.PinMessage)); options.add(OPTION_PIN); icons.add(R.drawable.msg_pin); } if (selectedObject != null && selectedObject.contentType == 0 && (!TextUtils.isEmpty(selectedObject.getMessageTextToTranslate(groupedMessages, null)) && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { items.add(LocaleController.getString(R.string.TranslateMessage)); options.add(OPTION_TRANSLATE); icons.add(R.drawable.msg_translate); } if (message.canEditMessage(currentChat) && message.type != MessageObject.TYPE_POLL) { items.add(LocaleController.getString(R.string.Edit)); options.add(OPTION_EDIT); icons.add(R.drawable.msg_edit); } if (ChatObject.isMonoForum(currentChat) && selectedObject.getGroupId() == 0 && selectedObjectGroup == null && message != null && message.messageOwner != null && message.messageOwner.suggested_post == null && message.messageOwner.action == null) { items.add(LocaleController.getString(R.string.EditOfferAdd)); options.add(OPTION_SUGGESTION_ADD_OFFER); icons.add(R.drawable.menu_edit_price); } // if (message.scheduled && message.type == MessageObject.TYPE_PAID_MEDIA && message.canEditMessage(currentChat)) { // items.add(LocaleController.getString(R.string.PaidMediaPriceButton)); // options.add(OPTION_EDIT_PRICE); // icons.add(R.drawable.menu_feature_paid); // } if (selectedObject.contentType == 0 && !selectedObject.isMediaEmptyWebpage() && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { items.add(LocaleController.getString(R.string.ReportChat)); options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.msg_report); } } else { if (selectedObject.getId() > 0 && allowChatActions && !isInsideContainer) { items.add(LocaleController.getString(R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.menu_reply); } } if (selectedObject != null && selectedObject.messageOwner != null && currentUser != null && !UserObject.isService(currentUser.id) && (selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift || selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGiftUnique || selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium)) { items.add(selectedObject.isOutOwner() ? getString(R.string.SendAnotherGift) : formatString(R.string.SendGiftTo, UserObject.getForcedFirstName(currentUser))); options.add(OPTION_GIFT); icons.add(R.drawable.menu_gift); } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message)) && !(message != null && message.messageOwner != null && message.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate)) { items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(deleteIconRes); } } else if (type == 20) { items.add(LocaleController.getString(R.string.Retry)); options.add(OPTION_RETRY); icons.add(R.drawable.msg_retry); if (!noforwardsOrPaidMedia) { items.add(LocaleController.getString(R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(deleteIconRes); } else { if (currentEncryptedChat == null) { if (!selectedObject.isPaidSuggestedPostProtected() && chatMode == MODE_SCHEDULED) { items.add(LocaleController.getString(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(R.string.CallBack) : LocaleController.getString(R.string.CallAgain)); options.add(OPTION_CALL_AGAIN); icons.add(R.drawable.msg_callback); if (VoIPHelper.canRateCall(call)) { items.add(LocaleController.getString(R.string.CallMessageReportProblem)); options.add(OPTION_RATE_CALL); icons.add(R.drawable.msg_fave); } } if ((allowChatActions || !noforwardsOrPaidMedia && ChatObject.isChannelAndNotMegaGroup(currentChat) && !selectedObject.isSponsored() && selectedObject.contentType == 0 && chatMode == MODE_DEFAULT) && !isInsideContainer) { items.add(LocaleController.getString(R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.menu_reply); } if ((selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.isDice() || selectedObject.isAnimatedEmoji() || selectedObject.isAnimatedEmojiStickers() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwardsOrPaidMedia && !selectedObject.sponsoredCanReport) { items.add(LocaleController.getString(R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && primaryMessage != null && (currentChat.has_link || primaryMessage.hasReplies()) && currentChat.megagroup && primaryMessage.canViewThread()) { if (primaryMessage.hasReplies()) { items.add(LocaleController.formatPluralString("ViewReplies", primaryMessage.getRepliesCount())); } else { items.add(LocaleController.getString(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) && !ChatObject.isMonoForum(currentChat) && selectedObject.getDialogId() != mergeDialogId) { items.add(LocaleController.getString(R.string.CopyLink)); options.add(OPTION_COPY_LINK); icons.add(R.drawable.msg_link); } if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.action == null && currentChat != null && currentChat.forum && !isTopic && selectedObject.messageOwner != null && selectedObject.messageOwner.reply_to != null && selectedObject.messageOwner.reply_to.forum_topic) { items.add(LocaleController.getString(R.string.ViewInTopic)); options.add(OPTION_VIEW_IN_TOPIC); icons.add(R.drawable.msg_viewintopic); } if (type == 2) { if (chatMode != MODE_SCHEDULED) { if (selectedObject.type == MessageObject.TYPE_POLL && !message.isPollClosed()) { TLRPC.MessageMedia media = MessageObject.getMedia(selectedObject); if (media instanceof TLRPC.TL_messageMediaPoll) { if (message.canUnvote()) { items.add(LocaleController.getString(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(R.string.StopQuiz)); } else { items.add(LocaleController.getString(R.string.StopPoll)); } options.add(OPTION_STOP_POLL_OR_QUIZ); icons.add(R.drawable.msg_pollstop); } } else if (media instanceof TLRPC.TL_messageMediaToDo) { if (message.canEditMessage(currentChat)) { items.add(getString(R.string.EditToDo)); options.add(OPTION_EDIT_TODO); icons.add(R.drawable.msg_edit); } if (message.canAppendToTodo()) { items.add(getString(R.string.AddTasks)); options.add(OPTION_ADD_TO_TODO); icons.add(R.drawable.msg_addbot); } } } else if (selectedObject.isMusic() && !noforwardsOrPaidMedia && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); } else if (selectedObject.isDocument() && !noforwardsOrPaidMedia && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); } } } else if (type == 3 && !noforwardsOrPaidMedia) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { items.add(LocaleController.getString(R.string.SaveToGIFs)); options.add(OPTION_ADD_TO_GIFS); icons.add(R.drawable.msg_gif); } } else if (type == 4) { if (!noforwardsOrPaidMedia && !selectedObject.hasRevealedExtendedMedia()) { if (selectedObject.isVideo()) { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString(R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (selectedObject.isMusic() && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (selectedObject.getDocument() != null && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { items.add(LocaleController.getString(R.string.SaveToGIFs)); options.add(OPTION_ADD_TO_GIFS); icons.add(R.drawable.msg_gif); } items.add(LocaleController.getString(R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString(R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); } } } } else if (type == 5) { items.add(LocaleController.getString(R.string.ApplyLocalizationFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_language); if (!noforwardsOrPaidMedia && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (type == 10) { items.add(LocaleController.getString(R.string.ApplyThemeFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_theme); if (!noforwardsOrPaidMedia && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (type == 6 && !noforwardsOrPaidMedia && !selectedObject.hasRevealedExtendedMedia()) { if (!selectedObject.needDrawBluredPreview() && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY2); icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString(R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } } else if (type == 7) { if (selectedObject.isMask()) { items.add(LocaleController.getString(R.string.AddToMasks)); options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.msg_sticker); } else { items.add(LocaleController.getString(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()) { items.add(LocaleController.getString(R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); } } else { items.add(LocaleController.getString(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(R.string.AddContactTitle)); options.add(OPTION_ADD_CONTACT); icons.add(R.drawable.msg_addcontact); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { if (!noforwardsOrPaidMedia) { items.add(LocaleController.getString(R.string.Copy)); options.add(OPTION_COPY_PHONE_NUMBER); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString(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 (getMediaDataController().canAddStickerToFavorites()) { items.add(LocaleController.getString(R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); } } else { items.add(LocaleController.getString(R.string.DeleteFromFavorites)); options.add(OPTION_DELETE_STICKER_FROM_FAVORITES); icons.add(R.drawable.msg_unfave); } } if (!selectedObject.isSponsored() && chatMode != MODE_QUICK_REPLIES && chatMode != MODE_SCHEDULED && (!selectedObject.needDrawBluredPreview() || selectedObject.hasExtendedMediaPreview()) && !selectedObject.isLiveLocation() && selectedObject.type != MessageObject.TYPE_PHONE_CALL && !noforwards && selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_GIFT_OFFER && selectedObject.type != MessageObject.TYPE_GIFT_OFFER_REJECTED && selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM_CHANNEL && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction() && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION && message.type != MessageObject.TYPE_GIFT_STARS) { items.add(LocaleController.getString(R.string.Forward)); options.add(OPTION_FORWARD); icons.add(R.drawable.msg_forward); } if (allowUnpin) { items.add(LocaleController.getString(R.string.UnpinMessage)); options.add(OPTION_UNPIN); icons.add(R.drawable.msg_unpin); } else if (allowPin) { items.add(LocaleController.getString(R.string.PinMessage)); options.add(OPTION_PIN); icons.add(R.drawable.msg_pin); } if (selectedObject != null && selectedObject.contentType == 0 && (!TextUtils.isEmpty(selectedObject.getMessageTextToTranslate(selectedObjectGroup, null)) && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { items.add(LocaleController.getString(R.string.TranslateMessage)); options.add(OPTION_TRANSLATE); icons.add(R.drawable.msg_translate); } if (allowEdit) { items.add(LocaleController.getString(R.string.Edit)); options.add(OPTION_EDIT); icons.add(R.drawable.msg_edit); } if (ChatObject.isMonoForum(currentChat) && selectedObject.getGroupId() == 0 && selectedObjectGroup == null && message != null && message.messageOwner != null && message.messageOwner.suggested_post == null && message.messageOwner.action == null) { items.add(LocaleController.getString(R.string.EditOfferAdd)); options.add(OPTION_SUGGESTION_ADD_OFFER); icons.add(R.drawable.menu_edit_price); } if (!selectedObject.isPaidSuggestedPostProtected() && chatMode == MODE_SCHEDULED && selectedObject.canEditMessageScheduleTime(currentChat)) { items.add(LocaleController.getString(R.string.MessageScheduleEditTime)); options.add(OPTION_EDIT_SCHEDULE_TIME); icons.add(R.drawable.msg_calendar2); } MessageObject msg = selectedObjectGroup != null ? selectedObjectGroup.findPrimaryMessageObject() : selectedObject; if (msg != null && msg.isFactCheckable() && getMessagesController().canEditFactcheck && ChatObject.isChannelAndNotMegaGroup(currentChat) && chatMode == MODE_DEFAULT) { items.add(LocaleController.getString(msg.getFactCheck() == null ? R.string.AddFactCheck : R.string.EditFactCheck)); options.add(OPTION_FACT_CHECK); icons.add(R.drawable.menu_factcheck); } 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(R.string.BlockContact)); options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.msg_block2); } else { items.add(LocaleController.getString(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(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(deleteIconRes); } } else { if (allowChatActions && !isInsideContainer) { items.add(LocaleController.getString(R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.menu_reply); } if ((selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.isAnimatedEmoji() || selectedObject.isAnimatedEmojiStickers() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwardsOrPaidMedia) { items.add(LocaleController.getString(R.string.Copy)); options.add(OPTION_COPY); icons.add(R.drawable.msg_copy); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && primaryMessage != null && (currentChat.has_link || primaryMessage.hasReplies()) && currentChat.megagroup && primaryMessage.canViewThread()) { if (primaryMessage.hasReplies()) { items.add(LocaleController.formatPluralString("ViewReplies", primaryMessage.getRepliesCount())); } else { items.add(LocaleController.getString(R.string.ViewThread)); } options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.msg_viewreplies); } if (selectedObject != null && selectedObject.messageOwner != null && selectedObject.messageOwner.action == null && currentChat != null && currentChat.forum && !isTopic && selectedObject.messageOwner != null && selectedObject.messageOwner.reply_to != null && selectedObject.messageOwner.reply_to.forum_topic) { items.add(LocaleController.getString(R.string.ViewInTopic)); options.add(OPTION_VIEW_IN_TOPIC); icons.add(R.drawable.msg_viewintopic); } if (type == 4 && !noforwardsOrPaidMedia && !selectedObject.hasRevealedExtendedMedia() && !selectedObject.needDrawBluredPreview()) { if (selectedObject.isVideo()) { items.add(LocaleController.getString(R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (selectedObject.isMusic() && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null && !selectedObject.isVoiceOnce() && !selectedObject.isRoundOnce()) { items.add(LocaleController.getString(R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.msg_download); items.add(LocaleController.getString(R.string.ShareFile)); options.add(OPTION_SHARE); icons.add(R.drawable.msg_shareout); } else { items.add(LocaleController.getString(R.string.SaveToGallery)); options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.msg_gallery); } } else if (type == 5) { items.add(LocaleController.getString(R.string.ApplyLocalizationFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_language); } else if (type == 10) { items.add(LocaleController.getString(R.string.ApplyThemeFile)); options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.msg_theme); } else if (type == 7) { items.add(LocaleController.getString(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(R.string.AddContactTitle)); options.add(OPTION_ADD_CONTACT); icons.add(R.drawable.msg_addcontact); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { if (!noforwardsOrPaidMedia) { items.add(LocaleController.getString(R.string.Copy)); options.add(OPTION_COPY_PHONE_NUMBER); icons.add(R.drawable.msg_copy); } items.add(LocaleController.getString(R.string.Call)); options.add(OPTION_CALL); icons.add(R.drawable.msg_callback); } } items.add(LocaleController.getString(chatMode == MODE_SAVED && threadMessageId != getUserConfig().getClientUserId() ? R.string.Remove : R.string.Delete)); options.add(OPTION_DELETE); icons.add(deleteIconRes); } } } private void updateBotforumTabsBottomMargin() { if (topicsTabs == null) { return; } final float margin = windowInsetsStateHolder.getAnimatedMaxBottomInset() + (chatInputViewsContainer.getInputBubbleHeight() + dp(9)); topicsTabs.setSideMenuBackgroundMarginBottom(margin); } private void checkUi_botMenuPosition() { final float margin = windowInsetsStateHolder.getAnimatedMaxBottomInset() + (chatInputViewsContainer.getInputBubbleHeight() + dp(9 + 6)); if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuContainer != null) { chatActivityEnterView.botCommandsMenuContainer.setTranslationY(-margin); } if (mentionContainer != null) { mentionContainer.setTranslationY(mentionContainer.isReversed() ? dp(5) : -margin); } } @Override public boolean isSupportEdgeToEdge() { return true; } /* */ private float calculateInputIslandHeight(boolean target) { final float enterViewIslandHeight = Math.max( chatActivityEnterView != null ? chatActivityEnterView.getIslandTotalHeight(target): 0, dp(44)); final float defaultIslandHeight = dp(44); final float enterViewFactor; float visibility; if (target) { enterViewFactor = bottomViewsVisibilityController.getCurrentPriorityContainerId() == MESSAGE_INPUT_CONTAINER ? 1 : 0; visibility = bottomViewsVisibilityController.getCurrentPriorityContainerId() == 0 ? 0 : 1; } else { enterViewFactor = bottomViewsVisibilityController.getVisibility(MESSAGE_INPUT_CONTAINER); visibility = 1f - bottomViewsVisibilityController.getVisibility(0); } if (!isInsideContainer && !isInPreviewMode()) { return Math.max(lerp(defaultIslandHeight, enterViewIslandHeight, enterViewFactor) * visibility, dp(44)); } else { return lerp(defaultIslandHeight, enterViewIslandHeight, enterViewFactor) * visibility; } } private float inputIslandHeightCurrent; private float inputIslandHeightTarget; private void checkUi_inputIslandHeight() { if (contentView == null) { return; } inputIslandHeightCurrent = calculateInputIslandHeight(false); inputIslandHeightTarget = calculateInputIslandHeight(true); chatInputViewsContainer.setInputBubbleHeight(inputIslandHeightCurrent); updatePagedownButtonsPosition(); updateBotforumTabsBottomMargin(); checkUi_botMenuPosition(); checkUi_BlurHeight(); checkUi_emptyContainerPosition(); checkUi_chatListViewPaddings(); } private static final Rect clipBoundsRect = new Rect(); private void checkUi_BlurHeight() { final float inputHeight = windowInsetsStateHolder.getAnimatedMaxBottomInset() + dp(9) + chatInputViewsContainer.getInputBubbleHeight() + dp(7); final float fullHeight = chatInputViewsContainer.getMeasuredHeight() + dp(36); final float result = lerp(inputHeight, fullHeight, animatorRoundMessageCameraVisibility.getFloatValue()); chatInputViewsContainer.setBlurredBottomHeight(result); int clipBound = contentView.getMeasuredHeight() - (int) result + dp(36); clipBound = androidx.core.math.MathUtils.clamp(clipBound, 0, contentView.getMeasuredHeight()); clipBoundsRect.set(0, 0, contentView.getMeasuredWidth(), clipBound); clipBoundsRect.set(0, blurredViewTopOffset, chatListView.getMeasuredWidth(), chatListView.getMeasuredHeight() - blurredViewBottomOffset - (int) result + dp(36) ); } private void checkUi_emptyContainerPosition() { if (emptyViewContainer != null) { emptyViewContainer.setTranslationY(-0.5f * (dp(9) + windowInsetsStateHolder.getAnimatedImeBottomInset() + chatInputViewsContainer.getInputBubbleHeight() )); } } @Override public void onFactorChanged(int id, float factor, float fraction, FactorAnimator callee) { if (id == ANIMATOR_ID_PULLING_DOWN_CONTAINER_VISIBILITY) { onBottomItemsVisibilityChanged(); } else if (id == ANIMATOR_ID_ROUND_MESSAGE_CAMERA_VISIBILITY) { checkUi_BlurHeight(); } } private static final int ANIMATOR_ID_PULLING_DOWN_CONTAINER_VISIBILITY = 0; private static final int ANIMATOR_ID_ROUND_MESSAGE_CAMERA_VISIBILITY = 1; private final BoolAnimator animatorPullingDownContainerVisibility = new BoolAnimator(ANIMATOR_ID_PULLING_DOWN_CONTAINER_VISIBILITY, this, CubicBezierInterpolator.EASE_OUT_QUINT, 320); private final BoolAnimator animatorRoundMessageCameraVisibility = new BoolAnimator(ANIMATOR_ID_ROUND_MESSAGE_CAMERA_VISIBILITY, this, CubicBezierInterpolator.EASE_OUT_QUINT, 320); public static final int MESSAGE_INPUT_CONTAINER = 1; public static final int BOTTOM_OVERLAY_TEXT_CONTAINER = 2; public static final int BOTTOM_OVERLAY_CHAT_CONTAINER = 3; public static final int MESSAGE_ACTION_CONTAINER = 5; public static final int MESSAGE_SEARCH_CONTAINER = 4; private final ChatActivityBottomViewsVisibilityController bottomViewsVisibilityController = new ChatActivityBottomViewsVisibilityController(this::onBottomItemsVisibilityChanged); private void checkBottomViewVisibility(View view, int containerId, boolean allowVisibilityChange) { if (view != null) { final float alpha = bottomViewsVisibilityController.getVisibility(containerId) * (1f - animatorPullingDownContainerVisibility.getFloatValue()); view.setAlpha(alpha); if (allowVisibilityChange) { final int visibility = alpha > 0 ? View.VISIBLE : View.GONE; if (view.getVisibility() != visibility) { view.setVisibility(visibility); } } } } private void onBottomItemsVisibilityChanged() { checkBottomViewVisibility(actionsButtonsLayout, MESSAGE_ACTION_CONTAINER, true); checkBottomViewVisibility(chatActivityEnterView, MESSAGE_INPUT_CONTAINER, false); checkBottomViewVisibility(searchContainer, MESSAGE_SEARCH_CONTAINER, true); checkBottomViewVisibility(bottomChannelButtonsLayout, BOTTOM_OVERLAY_CHAT_CONTAINER, false); checkBottomViewVisibility(bottomOverlay, BOTTOM_OVERLAY_TEXT_CONTAINER, false); final float actionFactor = bottomViewsVisibilityController.getVisibility(MESSAGE_ACTION_CONTAINER); if (actionsButtonsLayout != null) { actionsButtonsLayout.setTotalVisibilityFactor(actionFactor); } if (chatActivityEnterView != null) { chatActivityEnterView.setTranslationY(-dp(54) * actionFactor); } if (searchContainer != null) { searchContainer.setTranslationY(-dp(54) * actionFactor); } if (bottomChannelButtonsLayout != null) { bottomChannelButtonsLayout.setTranslationY(-dp(54) * actionFactor); } if (bottomOverlay != null) { bottomOverlay.setTranslationY(-dp(54) * actionFactor); } if (chatInputViewsContainer != null) { chatInputViewsContainer.setInputBubbleAlpha((int) (255 * (1f - actionFactor))); chatInputViewsContainer.setInputBubbleTranslationY(-dp(54) * actionFactor); } if (bottomChannelButtonsLayout != null) { bottomChannelButtonsLayout.setTotalVisibilityFactor( bottomViewsVisibilityController.getVisibility(BOTTOM_OVERLAY_CHAT_CONTAINER) * (1f - animatorPullingDownContainerVisibility.getFloatValue()) ); } if (pullingDownDrawable != null) { final float factor = animatorPullingDownContainerVisibility.getFloatValue(); if (pullingDownDrawable.progressToBottomPanel != factor) { pullingDownDrawable.progressToBottomPanel = factor; fragmentView.invalidate(); } } checkUi_inputIslandHeight(); } private boolean glassSourcesInvalidated; private void invalidateAllGlassAttachedViews() { glassSourcesInvalidated = true; contentView.invalidate(); for (View v: glassAttachedViews) { v.invalidate(); } } private void onSideControlButtonOnClick(int buttonId, View v) { if (buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_PAGE_DOWN) { onPageDownClicked(); } else if (buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_MENTION) { loadLastUnreadMention(); } else if (buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_REACTIONS) { wasManualScroll = true; getMessagesController().getNextReactionMention(dialog_id, getTopicId(), reactionsMentionCount, (messageId) -> { if (messageId == 0) { reactionsMentionCount = 0; updateReactionsMentionButton(true); getMessagesController().markReactionsAsRead(dialog_id, getTopicId()); } else { updateReactionsMentionButton(true); scrollToMessageId(messageId, 0, false, 0, true, 0); } }); } else if (buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_SEARCH_UP) { goToNextOrPrevSearchMessage(true); } else if (buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_SEARCH_DOWN) { goToNextOrPrevSearchMessage(false); } else if (buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_ATTACH) { if (chatAttachAlert != null) { chatAttachAlert.setEditingMessageObject(0, null); } openAttachMenu(); } } private void goToNextOrPrevSearchMessage(boolean searchUp) { if (chatMode == MODE_SEARCH) { HashtagSearchController.getInstance(currentAccount).jumpToMessage(classGuid, hashtagSearchSelectedIndex + (searchUp ? 1 : -1), searchType); } else { getMediaDataController().searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, searchUp ? (reversed ? 2 : 1) : (reversed ? 1 : 2), threadMessageId, searchingUserMessages, searchingChatMessages, searchingReaction); showMessagesSearchListView(false); } } private void loadLastUnreadMention() { wasManualScroll = true; if (hasAllMentionsLocal) { getMessagesStorage().getUnreadMention(dialog_id, getTopicId(), 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; if (isTopic) { req.top_msg_id = (int) threadMessageId; req.flags |= 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, getTopicId(), newMentionsCount); if (newMentionsCount == 0) { hasAllMentionsLocal = true; showMentionDownButton(false, true); } else { sideControlsButtonsLayout.setButtonCount(ChatActivitySideControlsButtonsLayout.BUTTON_MENTION, newMentionsCount, true); 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); } })); } } private boolean onSideControlButtonOnLongClick(int buttonId, View view) { final boolean isMentionButton = buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_MENTION; final boolean isReactionButton = buttonId == ChatActivitySideControlsButtonsLayout.BUTTON_REACTIONS; if (isMentionButton || isReactionButton) { final Runnable onRead; final int type; if (isMentionButton) { type = ReadAllMentionsMenu.TYPE_MENTIONS; onRead = () -> { 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, getTopicId()); hasAllMentionsLocal = true; showMentionDownButton(false, true); if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } }; } else { type = ReadAllMentionsMenu.TYPE_REACTIONS; onRead = () -> { for (int i = 0; i < messages.size(); i++) { messages.get(i).markReactionsAsRead(); } reactionsMentionCount = 0; updateReactionsMentionButton(true); getMessagesController().markReactionsAsRead(dialog_id, getTopicId()); if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); } }; } scrimPopupWindow = ReadAllMentionsMenu.show(type, getParentActivity(), getParentLayout(), contentView, view, getResourceProvider(), onRead); dimBehindView(sideControlsButtonsLayout, true); scrimPopupWindow.setOnDismissListener(() -> { scrimPopupWindow = null; menuDeleteItem = null; scrimPopupWindowItems = null; chatLayoutManager.setCanScrollVertically(true); dimBehindView(false); if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setAllowDrawCursor(true); } }); try { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {} return true; } return false; } public void startFireworks() { if (fireworksOverlay == null || fireworksOverlay.isStarted()) { return; } fireworksOverlay.start(); try { fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {}; } private OnPostDrawView invalidateBlurredSourcesView; private static final int BLUR_INVALIDATE_FLAG_SCROLL = 1; private static final int BLUR_INVALIDATE_FLAG_POSITIONS = 1 << 1; private void invalidateMergedVisibleBlurredPositionsAndSourcesPositions() { invalidateMergedVisibleBlurredPositionsAndSources(BLUR_INVALIDATE_FLAG_POSITIONS); } private void invalidateMergedVisibleBlurredPositionsAndSources(int flags) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || scrollableViewNoiseSuppressor == null) { return; } invalidateBlurredSourcesView.invalidate(flags); } private final ArrayList glassDrawablesPositions = new ArrayList<>(); private final ArrayList glassDrawablesPositionsMerged = new ArrayList<>(); private int glassDrawablesPositionsCount; private void invalidateMergedVisibleBlurredPositionsAndSourcesImpl(int flags) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || scrollableViewNoiseSuppressor == null) { return; } if (BitwiseUtils.hasFlag(flags, BLUR_INVALIDATE_FLAG_POSITIONS)) { glassDrawablesPositionsCount = getMergedVisibleBlurredPositions(glassDrawablesPositionsMerged); scrollableViewNoiseSuppressor.setupRenderNodes(glassDrawablesPositionsMerged, glassDrawablesPositionsCount); } //if (BitwiseUtils.hasFlag(flags, BLUR_INVALIDATE_FLAG_POSITIONS | BLUR_INVALIDATE_FLAG_SCROLL)) { for (int a = 0; a < glassDrawablesPositionsCount; a++) { final RectF position = scrollableViewNoiseSuppressor.getPosition(a); Canvas c = scrollableViewNoiseSuppressor.beginRecordingRect(a); c.save(); c.translate(-position.left, -position.top); contentView.drawList(c, position); c.restore(); scrollableViewNoiseSuppressor.endRecordingRect(); } scrollableViewNoiseSuppressor.invalidateResultRenderNodes(contentView.getWidth(), contentView.getHeight()); //} } private int getMergedVisibleBlurredPositions(List positions) { final int positionsCount = getVisibleBlurredPositions(glassDrawablesPositions); final int mergedPositionsCount = RectFMergeBounding.mergeOverlapping(glassDrawablesPositions, positionsCount, positions); for (int a = 0; a < mergedPositionsCount; a++) { final RectF position = positions.get(a); position.left = Math.max(0, position.left); position.top = Math.max(chatListView.getY(), position.top); position.right = Math.min(contentView.getMeasuredWidth(), position.right); position.bottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), position.bottom); /*if (drawDebug) { ((Canvas) null).drawRect(position, Theme.DEBUG_GREEN_STROKE); }*/ } return mergedPositionsCount; } private int getVisibleBlurredPositions(List positions) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { int count = 0; if (glassBackgroundSourceFrostedRenderNode != null) { final int blurAlpha = Color.alpha(Theme.getColor(SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH ? Theme.key_chat_BlurAlpha : Theme.key_chat_BlurAlphaSlow, getResourceProvider())); if (blurAlpha < 255) { final RectF rectf; if (positions.isEmpty()) { positions.add(rectf = new RectF()); } else { rectf = positions.get(0); } rectf.set(0, 0, contentView.getMeasuredWidth(), chatListView.getPaddingTop() + chatListView.getY()); rectf.inset(0, -dp(45)); count += 1; } count += glassBackgroundSourceFrostedRenderNode.getVisiblePositions(positions, count, dp(48)); } if (glassBackgroundSourceRenderNode != null) { count += glassBackgroundSourceRenderNode.getVisiblePositions(positions, count, dp(8)); } if (navbarContentSourceWallpaperAndMessagesRenderNode != null) { count += navbarContentSourceWallpaperAndMessagesRenderNode.getVisiblePositions(positions, count, dp(48)); } return count; } else { return 0; } } private final Rect clipBoundsTmp = new Rect(); private void invalidateClipRectForBackgroundAndChatList() { if (contentView == null) { return; } final int topClip = ActionBar.getCurrentActionBarHeight() + windowInsetsStateHolder.getInsets(WindowInsetsCompat.Type.statusBars()).top; final int bottomClip = (int) Math.max(0, windowInsetsStateHolder.getAnimatedImeBottomInset() * windowInsetsStateHolder.getAnimatedKeyboardVisibility() - dp(29)); if (contentView.backgroundView != null) { clipBoundsTmp.set(0, topClip, contentView.getMeasuredWidth(), contentView.getMeasuredHeight() - bottomClip); contentView.backgroundView.setClipBounds(clipBoundsTmp); } if (chatListView != null) { clipBoundsTmp.set(0, topClip, contentView.getMeasuredWidth(), contentView.getMeasuredHeight() - bottomClip); clipBoundsTmp.offset(0, -chatListView.getTop()); chatListView.setClipBounds(clipBoundsTmp); } if (chatInputViewsContainer != null && chatInputViewsContainer.getFadeView() != null) { clipBoundsTmp.set(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight() - bottomClip); // chatInputViewsContainer.getFadeView().setClipBounds(clipBoundsTmp); } } private abstract class ChatListRecyclerView extends RecyclerListViewInternal { public ChatListRecyclerView(Context context, ThemeDelegate themeDelegate) { super(context, themeDelegate); } abstract void drawChatBackgroundElements(Canvas canvas); abstract void drawChatForegroundElements(Canvas canvas); } }