"Fossies" - the Fresh Open Source Software Archive

Member "tdesktop-2.6.1/Telegram/SourceFiles/history/history_widget.h" (24 Feb 2021, 22056 Bytes) of package /linux/misc/tdesktop-2.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "history_widget.h" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.5.9_vs_2.6.0.

    1 /*
    2 This file is part of Telegram Desktop,
    3 the official desktop application for the Telegram messaging service.
    4 
    5 For license and copyright information please follow this link:
    6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
    7 */
    8 #pragma once
    9 
   10 #include "history/history_drag_area.h"
   11 #include "ui/widgets/tooltip.h"
   12 #include "mainwidget.h"
   13 #include "chat_helpers/field_autocomplete.h"
   14 #include "window/section_widget.h"
   15 #include "ui/widgets/input_fields.h"
   16 #include "ui/effects/animations.h"
   17 #include "ui/rp_widget.h"
   18 #include "mtproto/sender.h"
   19 #include "base/flags.h"
   20 #include "base/timer.h"
   21 
   22 class RPCError;
   23 struct FileLoadResult;
   24 struct SendingAlbum;
   25 enum class SendMediaType;
   26 class MessageLinksParser;
   27 
   28 namespace Data {
   29 enum class PreviewState : char;
   30 } // namespace Data
   31 
   32 namespace SendMenu {
   33 enum class Type;
   34 } // namespace SendMenu
   35 
   36 namespace Api {
   37 struct SendOptions;
   38 } // namespace Api
   39 
   40 namespace InlineBots {
   41 namespace Layout {
   42 class ItemBase;
   43 class Widget;
   44 } // namespace Layout
   45 struct ResultSelected;
   46 } // namespace InlineBots
   47 
   48 namespace Support {
   49 class Autocomplete;
   50 struct Contact;
   51 } // namespace Support
   52 
   53 namespace Ui {
   54 class AbstractButton;
   55 class InnerDropdown;
   56 class DropdownMenu;
   57 class PlainShadow;
   58 class PopupMenu;
   59 class IconButton;
   60 class HistoryDownButton;
   61 class EmojiButton;
   62 class SendButton;
   63 class SilentToggle;
   64 class FlatButton;
   65 class LinkButton;
   66 class RoundButton;
   67 class PinnedBar;
   68 class GroupCallBar;
   69 struct PreparedList;
   70 class SendFilesWay;
   71 enum class ReportReason;
   72 namespace Toast {
   73 class Instance;
   74 } // namespace Toast
   75 } // namespace Ui
   76 
   77 namespace Window {
   78 class SessionController;
   79 } // namespace Window
   80 
   81 namespace ChatHelpers {
   82 class TabbedPanel;
   83 class TabbedSection;
   84 class TabbedSelector;
   85 } // namespace ChatHelpers
   86 
   87 namespace Storage {
   88 enum class MimeDataState;
   89 struct UploadedPhoto;
   90 struct UploadedDocument;
   91 struct UploadedThumbDocument;
   92 } // namespace Storage
   93 
   94 namespace HistoryView {
   95 class TopBarWidget;
   96 class ContactStatus;
   97 class Element;
   98 class PinnedTracker;
   99 class GroupCallTracker;
  100 namespace Controls {
  101 class RecordLock;
  102 class VoiceRecordBar;
  103 class TTLButton;
  104 } // namespace Controls
  105 } // namespace HistoryView
  106 
  107 class DragArea;
  108 class SendFilesBox;
  109 class BotKeyboard;
  110 class MessageField;
  111 class HistoryInner;
  112 struct HistoryMessageMarkupButton;
  113 
  114 class HistoryWidget final : public Window::AbstractSectionWidget {
  115 public:
  116     using FieldHistoryAction = Ui::InputField::HistoryAction;
  117     using RecordLock = HistoryView::Controls::RecordLock;
  118     using VoiceRecordBar = HistoryView::Controls::VoiceRecordBar;
  119 
  120     HistoryWidget(
  121         QWidget *parent,
  122         not_null<Window::SessionController*> controller);
  123 
  124     void start();
  125 
  126     void historyLoaded();
  127 
  128     [[nodiscard]] bool preventsClose(Fn<void()> &&continueCallback) const;
  129 
  130     // When resizing the widget with top edge moved up or down and we
  131     // want to add this top movement to the scroll position, so inner
  132     // content will not move.
  133     void setGeometryWithTopMoved(const QRect &newGeometry, int topDelta);
  134 
  135     void windowShown();
  136     [[nodiscard]] bool doWeReadServerHistory() const;
  137     [[nodiscard]] bool doWeReadMentions() const;
  138     bool skipItemRepaint();
  139     void checkHistoryActivation();
  140 
  141     void leaveToChildEvent(QEvent *e, QWidget *child) override;
  142 
  143     bool isItemCompletelyHidden(HistoryItem *item) const;
  144     void updateTopBarSelection();
  145     void updateTopBarChooseForReport();
  146 
  147     void loadMessages();
  148     void loadMessagesDown();
  149     void firstLoadMessages();
  150     void delayedShowAt(MsgId showAtMsgId);
  151 
  152     QRect historyRect() const;
  153 
  154     void updateFieldPlaceholder();
  155     void updateStickersByEmoji();
  156 
  157     bool confirmSendingFiles(const QStringList &files);
  158     bool confirmSendingFiles(not_null<const QMimeData*> data);
  159     void sendFileConfirmed(const std::shared_ptr<FileLoadResult> &file,
  160         const std::optional<FullMsgId> &oldId = std::nullopt);
  161 
  162     void updateControlsVisibility();
  163     void updateControlsGeometry();
  164 
  165     History *history() const;
  166     PeerData *peer() const;
  167     void setMsgId(MsgId showAtMsgId);
  168     MsgId msgId() const;
  169 
  170     bool hasTopBarShadow() const {
  171         return peer() != nullptr;
  172     }
  173     void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams &params);
  174     void finishAnimating();
  175 
  176     void doneShow();
  177 
  178     QPoint clampMousePosition(QPoint point);
  179 
  180     void checkSelectingScroll(QPoint point);
  181     void noSelectingScroll();
  182 
  183     bool touchScroll(const QPoint &delta);
  184 
  185     void enqueueMessageHighlight(not_null<HistoryView::Element*> view);
  186     crl::time highlightStartTime(not_null<const HistoryItem*> item) const;
  187 
  188     MessageIdsList getSelectedItems() const;
  189     void itemEdited(not_null<HistoryItem*> item);
  190 
  191     void updateScrollColors();
  192 
  193     void replyToMessage(FullMsgId itemId);
  194     void replyToMessage(not_null<HistoryItem*> item);
  195     void editMessage(FullMsgId itemId);
  196     void editMessage(not_null<HistoryItem*> item);
  197 
  198     MsgId replyToId() const;
  199     bool lastForceReplyReplied(const FullMsgId &replyTo) const;
  200     bool lastForceReplyReplied() const;
  201     bool cancelReply(bool lastKeyboardUsed = false);
  202     void cancelEdit();
  203     void updateForwarding();
  204     void updateForwardingTexts();
  205 
  206     void clearReplyReturns();
  207     void pushReplyReturn(not_null<HistoryItem*> item);
  208     QList<MsgId> replyReturns();
  209     void setReplyReturns(PeerId peer, const QList<MsgId> &replyReturns);
  210     void calcNextReplyReturn();
  211 
  212     void updatePreview();
  213     void previewCancel();
  214 
  215     void escape();
  216 
  217     void sendBotCommand(
  218         not_null<PeerData*> peer,
  219         UserData *bot,
  220         const QString &cmd,
  221         MsgId replyTo);
  222     void hideSingleUseKeyboard(PeerData *peer, MsgId replyTo);
  223     bool insertBotCommand(const QString &cmd);
  224 
  225     bool eventFilter(QObject *obj, QEvent *e) override;
  226 
  227     // With force=true the markup is updated even if it is
  228     // already shown for the passed history item.
  229     void updateBotKeyboard(History *h = nullptr, bool force = false);
  230 
  231     void fastShowAtEnd(not_null<History*> history);
  232     void applyDraft(
  233         FieldHistoryAction fieldHistoryAction = FieldHistoryAction::Clear);
  234     void showHistory(const PeerId &peer, MsgId showAtMsgId, bool reload = false);
  235     void setChooseReportMessagesDetails(
  236         Ui::ReportReason reason,
  237         Fn<void(MessageIdsList)> callback);
  238     void clearAllLoadRequests();
  239     void clearDelayedShowAtRequest();
  240     void clearDelayedShowAt();
  241     void saveFieldToHistoryLocalDraft();
  242 
  243     void applyCloudDraft(History *history);
  244 
  245     void updateHistoryDownPosition();
  246     void updateHistoryDownVisibility();
  247     void updateUnreadMentionsPosition();
  248     void updateUnreadMentionsVisibility();
  249 
  250     void updateFieldSubmitSettings();
  251 
  252     void activate();
  253     void setInnerFocus();
  254     [[nodiscard]] rpl::producer<> cancelRequests() const {
  255         return _cancelRequests.events();
  256     }
  257 
  258     void updateNotifyControls();
  259 
  260     bool contentOverlapped(const QRect &globalRect);
  261 
  262     QPixmap grabForShowAnimation(const Window::SectionSlideParams &params);
  263 
  264     void forwardSelected();
  265     void confirmDeleteSelected();
  266     void clearSelected();
  267 
  268     bool sendExistingDocument(
  269         not_null<DocumentData*> document,
  270         Api::SendOptions options);
  271     bool sendExistingPhoto(
  272         not_null<PhotoData*> photo,
  273         Api::SendOptions options);
  274 
  275     void showInfoTooltip(
  276         const TextWithEntities &text,
  277         Fn<void()> hiddenCallback);
  278     void hideInfoTooltip(anim::type animated);
  279 
  280     // Tabbed selector management.
  281     bool pushTabbedSelectorToThirdSection(
  282         not_null<PeerData*> peer,
  283         const Window::SectionShow &params) override;
  284     bool returnTabbedSelector() override;
  285 
  286     // Float player interface.
  287     bool floatPlayerHandleWheelEvent(QEvent *e) override;
  288     QRect floatPlayerAvailableRect() override;
  289 
  290     PeerData *ui_getPeerForMouseAction();
  291 
  292     bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo);
  293 
  294     ~HistoryWidget();
  295 
  296 protected:
  297     void resizeEvent(QResizeEvent *e) override;
  298     void keyPressEvent(QKeyEvent *e) override;
  299     void mousePressEvent(QMouseEvent *e) override;
  300     void paintEvent(QPaintEvent *e) override;
  301     void leaveEventHook(QEvent *e) override;
  302     void mouseReleaseEvent(QMouseEvent *e) override;
  303     void mouseMoveEvent(QMouseEvent *e) override;
  304 
  305 private:
  306     using TabbedPanel = ChatHelpers::TabbedPanel;
  307     using TabbedSelector = ChatHelpers::TabbedSelector;
  308     enum ScrollChangeType {
  309         ScrollChangeNone,
  310 
  311         // When we toggle a pinned message.
  312         ScrollChangeAdd,
  313 
  314         // When loading a history part while scrolling down.
  315         ScrollChangeNoJumpToBottom,
  316     };
  317     struct ScrollChange {
  318         ScrollChangeType type;
  319         int value;
  320     };
  321     struct ChooseMessagesForReport {
  322         Ui::ReportReason reason = {};
  323         Fn<void(MessageIdsList)> callback;
  324         bool active = false;
  325     };
  326     enum class TextUpdateEvent {
  327         SaveDraft = (1 << 0),
  328         SendTyping = (1 << 1),
  329     };
  330     using TextUpdateEvents = base::flags<TextUpdateEvent>;
  331     friend inline constexpr bool is_flag_type(TextUpdateEvent) { return true; };
  332 
  333     void checkSuggestToGigagroup();
  334 
  335     void initTabbedSelector();
  336     void initVoiceRecordBar();
  337     void refreshTabbedPanel();
  338     void createTabbedPanel();
  339     void setTabbedPanel(std::unique_ptr<TabbedPanel> panel);
  340     void updateField();
  341     void fieldChanged();
  342     void fieldTabbed();
  343     void fieldFocused();
  344     void fieldResized();
  345 
  346     void insertHashtagOrBotCommand(
  347         QString str,
  348         FieldAutocomplete::ChooseMethod method);
  349     void insertMention(UserData *user);
  350     void cancelInlineBot();
  351     void saveDraft(bool delayed = false);
  352     void saveCloudDraft();
  353     void saveDraftDelayed();
  354     void checkFieldAutocomplete();
  355     void showMembersDropdown();
  356     void windowIsVisibleChanged();
  357 
  358     // Checks if we are too close to the top or to the bottom
  359     // in the scroll area and preloads history if needed.
  360     void preloadHistoryIfNeeded();
  361 
  362     void handleScroll();
  363     void scrollByTimer();
  364     void updateHistoryItemsByTimer();
  365 
  366     [[nodiscard]] Dialogs::EntryState computeDialogsEntryState() const;
  367     void refreshTopBarActiveChat();
  368 
  369     void requestMessageData(MsgId msgId);
  370     void messageDataReceived(ChannelData *channel, MsgId msgId);
  371 
  372     void send(Api::SendOptions options);
  373     void sendWithModifiers(Qt::KeyboardModifiers modifiers);
  374     void sendSilent();
  375     void sendScheduled();
  376     [[nodiscard]] SendMenu::Type sendMenuType() const;
  377     [[nodiscard]] SendMenu::Type sendButtonMenuType() const;
  378     void handlePendingHistoryUpdate();
  379     void fullPeerUpdated(PeerData *peer);
  380     void toggleTabbedSelectorMode();
  381     void recountChatWidth();
  382     void historyDownClicked();
  383     void showNextUnreadMention();
  384     void handlePeerUpdate();
  385     void setMembersShowAreaActive(bool active);
  386     void handleHistoryChange(not_null<const History*> history);
  387     void showAboutTopPromotion();
  388     void unreadCountUpdated();
  389 
  390     [[nodiscard]] int computeMaxFieldHeight() const;
  391     void toggleMuteUnmute();
  392     void reportSelectedMessages();
  393     void toggleKeyboard(bool manual = true);
  394     void startBotCommand();
  395     void hidePinnedMessage();
  396     void cancelFieldAreaState();
  397     void unblockUser();
  398     void sendBotStartCommand();
  399     void joinChannel();
  400 
  401     void supportInitAutocomplete();
  402     void supportInsertText(const QString &text);
  403     void supportShareContact(Support::Contact contact);
  404 
  405     void highlightMessage(MsgId universalMessageId);
  406     void checkNextHighlight();
  407     void updateHighlightedMessage();
  408     void clearHighlightMessages();
  409     void stopMessageHighlight();
  410 
  411     auto computeSendButtonType() const;
  412 
  413     void animationCallback();
  414     void updateOverStates(QPoint pos);
  415     void chooseAttach();
  416     void historyDownAnimationFinish();
  417     void unreadMentionsAnimationFinish();
  418     void sendButtonClicked();
  419     void unreadMessageAdded(not_null<HistoryItem*> item);
  420 
  421     bool canSendFiles(not_null<const QMimeData*> data) const;
  422     bool confirmSendingFiles(
  423         const QStringList &files,
  424         const QString &insertTextOnCancel);
  425     bool confirmSendingFiles(
  426         QImage &&image,
  427         QByteArray &&content,
  428         std::optional<bool> overrideSendImagesAsPhotos = std::nullopt,
  429         const QString &insertTextOnCancel = QString());
  430     bool confirmSendingFiles(
  431         not_null<const QMimeData*> data,
  432         std::optional<bool> overrideSendImagesAsPhotos,
  433         const QString &insertTextOnCancel = QString());
  434     bool confirmSendingFiles(
  435         Ui::PreparedList &&list,
  436         const QString &insertTextOnCancel = QString());
  437     bool showSendingFilesError(const Ui::PreparedList &list) const;
  438 
  439     void sendingFilesConfirmed(
  440         Ui::PreparedList &&list,
  441         Ui::SendFilesWay way,
  442         TextWithTags &&caption,
  443         Api::SendOptions options,
  444         bool ctrlShiftEnter);
  445 
  446     void uploadFile(const QByteArray &fileContent, SendMediaType type);
  447     void itemRemoved(not_null<const HistoryItem*> item);
  448 
  449     // Updates position of controls around the message field,
  450     // like send button, emoji button and others.
  451     void moveFieldControls();
  452     void updateFieldSize();
  453 
  454     bool canWriteMessage() const;
  455     std::optional<QString> writeRestriction() const;
  456     void orderWidgets();
  457 
  458     void clearInlineBot();
  459     void inlineBotChanged();
  460 
  461     // Look in the _field for the inline bot and query string.
  462     void updateInlineBotQuery();
  463 
  464     // Request to show results in the emoji panel.
  465     void applyInlineBotQuery(UserData *bot, const QString &query);
  466 
  467     void cancelReplyAfterMediaSend(bool lastKeyboardUsed);
  468     bool replyToPreviousMessage();
  469     bool replyToNextMessage();
  470     [[nodiscard]] bool showSlowmodeError();
  471 
  472     void hideChildWidgets();
  473     void hideSelectorControlsAnimated();
  474     int countMembersDropdownHeightMax() const;
  475 
  476     void updateReplyToName();
  477     void checkForwardingInfo();
  478     bool editingMessage() const {
  479         return _editMsgId != 0;
  480     }
  481     bool jumpToDialogRow(const Dialogs::RowDescriptor &to);
  482 
  483     void setupShortcuts();
  484     bool showNextChat();
  485     bool showPreviousChat();
  486 
  487     void handlePeerMigration();
  488 
  489     void updateReplyEditTexts(bool force = false);
  490     void updateReplyEditText(not_null<HistoryItem*> item);
  491 
  492     void updatePinnedViewer();
  493     void setupPinnedTracker();
  494     void checkPinnedBarState();
  495     void refreshPinnedBarButton(bool many);
  496     void checkLastPinnedClickedIdReset(
  497         int wasScrollTop,
  498         int nowScrollTop);
  499 
  500     void checkMessagesTTL();
  501     void setupGroupCallTracker();
  502 
  503     void sendInlineResult(InlineBots::ResultSelected result);
  504 
  505     void drawField(Painter &p, const QRect &rect);
  506     void paintEditHeader(
  507         Painter &p,
  508         const QRect &rect,
  509         int left,
  510         int top) const;
  511     void drawRestrictedWrite(Painter &p, const QString &error);
  512     bool paintShowAnimationFrame();
  513 
  514     void updateMouseTracking();
  515 
  516     // destroys _history and _migrated unread bars
  517     void destroyUnreadBar();
  518     void destroyUnreadBarOnClose();
  519     void createUnreadBarIfBelowVisibleArea(int withScrollTop);
  520     [[nodiscard]] bool insideJumpToEndInsteadOfToUnread() const;
  521     void createUnreadBarAndResize();
  522 
  523     void saveEditMsg();
  524 
  525     void checkPreview();
  526     void requestPreview();
  527     void gotPreview(QString links, const MTPMessageMedia &media, mtpRequestId req);
  528     void messagesReceived(PeerData *peer, const MTPmessages_Messages &messages, int requestId);
  529     void messagesFailed(const RPCError &error, int requestId);
  530     void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages);
  531     void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages);
  532 
  533     void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
  534     void updateListSize();
  535 
  536     // Does any of the shown histories has this flag set.
  537     bool hasPendingResizedItems() const;
  538 
  539     // Counts scrollTop for placing the scroll right at the unread
  540     // messages bar, choosing from _history and _migrated unreadBar.
  541     std::optional<int> unreadBarTop() const;
  542     int itemTopForHighlight(not_null<HistoryView::Element*> view) const;
  543     void scrollToCurrentVoiceMessage(FullMsgId fromId, FullMsgId toId);
  544 
  545     // Scroll to current y without updating the _lastUserScrolled time.
  546     // Used to distinguish between user scrolls and syntetic scrolls.
  547     // This one is syntetic.
  548     void synteticScrollToY(int y);
  549 
  550     void writeDrafts();
  551     void writeDraftTexts();
  552     void writeDraftCursors();
  553     void setFieldText(
  554         const TextWithTags &textWithTags,
  555         TextUpdateEvents events = 0,
  556         FieldHistoryAction fieldHistoryAction = FieldHistoryAction::Clear);
  557     void clearFieldText(
  558         TextUpdateEvents events = 0,
  559         FieldHistoryAction fieldHistoryAction = FieldHistoryAction::Clear);
  560 
  561     HistoryItem *getItemFromHistoryOrMigrated(MsgId genericMsgId) const;
  562     void animatedScrollToItem(MsgId msgId);
  563     void animatedScrollToY(int scrollTo, HistoryItem *attachTo = nullptr);
  564 
  565     // when scroll position or scroll area size changed this method
  566     // updates the boundings of the visible area in HistoryInner
  567     void visibleAreaUpdated();
  568     int countInitialScrollTop();
  569     int countAutomaticScrollTop();
  570     void preloadHistoryByScroll();
  571     void checkReplyReturns();
  572     void scrollToAnimationCallback(FullMsgId attachToId, int relativeTo);
  573 
  574     bool readyToForward() const;
  575     bool hasSilentToggle() const;
  576 
  577     void handleSupportSwitch(not_null<History*> updated);
  578 
  579     void inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result);
  580     void inlineBotResolveFail(const RPCError &error, const QString &username);
  581 
  582     bool isRecording() const;
  583 
  584     bool isBotStart() const;
  585     bool isBlocked() const;
  586     bool isJoinChannel() const;
  587     bool isMuteUnmute() const;
  588     bool isReportMessages() const;
  589     bool updateCmdStartShown();
  590     void updateSendButtonType();
  591     bool showRecordButton() const;
  592     bool showInlineBotCancel() const;
  593     void refreshSilentToggle();
  594 
  595     void setupScheduledToggle();
  596     void refreshScheduledToggle();
  597 
  598     bool kbWasHidden() const;
  599 
  600     MTP::Sender _api;
  601     MsgId _replyToId = 0;
  602     Ui::Text::String _replyToName;
  603     int _replyToNameVersion = 0;
  604 
  605     HistoryItemsList _toForward;
  606     Ui::Text::String _toForwardFrom, _toForwardText;
  607     int _toForwardNameVersion = 0;
  608 
  609     MsgId _editMsgId = 0;
  610 
  611     HistoryItem *_replyEditMsg = nullptr;
  612     Ui::Text::String _replyEditMsgText;
  613     mutable base::Timer _updateEditTimeLeftDisplay;
  614 
  615     object_ptr<Ui::IconButton> _fieldBarCancel;
  616 
  617     std::unique_ptr<HistoryView::PinnedTracker> _pinnedTracker;
  618     std::unique_ptr<Ui::PinnedBar> _pinnedBar;
  619     int _pinnedBarHeight = 0;
  620     FullMsgId _pinnedClickedId;
  621     std::optional<FullMsgId> _minPinnedId;
  622 
  623     std::unique_ptr<HistoryView::GroupCallTracker> _groupCallTracker;
  624     std::unique_ptr<Ui::GroupCallBar> _groupCallBar;
  625     int _groupCallBarHeight = 0;
  626 
  627     bool _preserveScrollTop = false;
  628 
  629     mtpRequestId _saveEditMsgRequestId = 0;
  630 
  631     QStringList _parsedLinks;
  632     QString _previewLinks;
  633     WebPageData *_previewData = nullptr;
  634     typedef QMap<QString, WebPageId> PreviewCache;
  635     PreviewCache _previewCache;
  636     mtpRequestId _previewRequest = 0;
  637     Ui::Text::String _previewTitle;
  638     Ui::Text::String _previewDescription;
  639     base::Timer _previewTimer;
  640     Data::PreviewState _previewState = Data::PreviewState();
  641 
  642     bool _replyForwardPressed = false;
  643 
  644     HistoryItem *_replyReturn = nullptr;
  645     QList<MsgId> _replyReturns;
  646 
  647     PeerData *_peer = nullptr;
  648 
  649     ChannelId _channel = NoChannel;
  650     bool _canSendMessages = false;
  651     MsgId _showAtMsgId = ShowAtUnreadMsgId;
  652 
  653     int _firstLoadRequest = 0; // Not real mtpRequestId.
  654     int _preloadRequest = 0; // Not real mtpRequestId.
  655     int _preloadDownRequest = 0; // Not real mtpRequestId.
  656 
  657     MsgId _delayedShowAtMsgId = -1;
  658     int _delayedShowAtRequest = 0; // Not real mtpRequestId.
  659 
  660     object_ptr<HistoryView::TopBarWidget> _topBar;
  661     object_ptr<Ui::ScrollArea> _scroll;
  662     QPointer<HistoryInner> _list;
  663     History *_migrated = nullptr;
  664     History *_history = nullptr;
  665     // Initial updateHistoryGeometry() was called.
  666     bool _historyInited = false;
  667     // If updateListSize() was called without updateHistoryGeometry().
  668     bool _updateHistoryGeometryRequired = false;
  669     int _addToScroll = 0;
  670 
  671     int _lastScrollTop = 0; // gifs optimization
  672     crl::time _lastScrolled = 0;
  673     base::Timer _updateHistoryItems;
  674 
  675     crl::time _lastUserScrolled = 0;
  676     bool _synteticScrollEvent = false;
  677     Ui::Animations::Simple _scrollToAnimation;
  678 
  679     Ui::Animations::Simple _historyDownShown;
  680     bool _historyDownIsShown = false;
  681     object_ptr<Ui::HistoryDownButton> _historyDown;
  682 
  683     Ui::Animations::Simple _unreadMentionsShown;
  684     bool _unreadMentionsIsShown = false;
  685     object_ptr<Ui::HistoryDownButton> _unreadMentions;
  686 
  687     object_ptr<FieldAutocomplete> _fieldAutocomplete;
  688     object_ptr<Support::Autocomplete> _supportAutocomplete;
  689     std::unique_ptr<MessageLinksParser> _fieldLinksParser;
  690 
  691     UserData *_inlineBot = nullptr;
  692     QString _inlineBotUsername;
  693     bool _inlineLookingUpBot = false;
  694     mtpRequestId _inlineBotResolveRequestId = 0;
  695     bool _isInlineBot = false;
  696 
  697     std::unique_ptr<HistoryView::ContactStatus> _contactStatus;
  698 
  699     const std::shared_ptr<Ui::SendButton> _send;
  700     object_ptr<Ui::FlatButton> _unblock;
  701     object_ptr<Ui::FlatButton> _botStart;
  702     object_ptr<Ui::FlatButton> _joinChannel;
  703     object_ptr<Ui::FlatButton> _muteUnmute;
  704     object_ptr<Ui::FlatButton> _reportMessages;
  705     object_ptr<Ui::IconButton> _attachToggle;
  706     object_ptr<Ui::EmojiButton> _tabbedSelectorToggle;
  707     object_ptr<Ui::IconButton> _botKeyboardShow;
  708     object_ptr<Ui::IconButton> _botKeyboardHide;
  709     object_ptr<Ui::IconButton> _botCommandStart;
  710     object_ptr<Ui::SilentToggle> _silent = { nullptr };
  711     object_ptr<Ui::IconButton> _scheduled = { nullptr };
  712     std::unique_ptr<HistoryView::Controls::TTLButton> _ttlInfo;
  713     const std::unique_ptr<VoiceRecordBar> _voiceRecordBar;
  714     bool _cmdStartShown = false;
  715     object_ptr<Ui::InputField> _field;
  716     bool _inReplyEditForward = false;
  717     bool _inClickable = false;
  718 
  719     bool _kbShown = false;
  720     HistoryItem *_kbReplyTo = nullptr;
  721     object_ptr<Ui::ScrollArea> _kbScroll;
  722     QPointer<BotKeyboard> _keyboard;
  723 
  724     object_ptr<Ui::InnerDropdown> _membersDropdown = { nullptr };
  725     base::Timer _membersDropdownShowTimer;
  726 
  727     object_ptr<InlineBots::Layout::Widget> _inlineResults = { nullptr };
  728     std::unique_ptr<TabbedPanel> _tabbedPanel;
  729 
  730     DragArea::Areas _attachDragAreas;
  731 
  732     Fn<void()> _raiseEmojiSuggestions;
  733 
  734     bool _nonEmptySelection = false;
  735 
  736     TextUpdateEvents _textUpdateEvents = (TextUpdateEvents() | TextUpdateEvent::SaveDraft | TextUpdateEvent::SendTyping);
  737 
  738     QString _confirmSource;
  739 
  740     Ui::Animations::Simple _a_show;
  741     Window::SlideDirection _showDirection;
  742     QPixmap _cacheUnder, _cacheOver;
  743 
  744     base::Timer _scrollTimer;
  745     int32 _scrollDelta = 0;
  746 
  747     MsgId _highlightedMessageId = 0;
  748     std::deque<MsgId> _highlightQueue;
  749     base::Timer _highlightTimer;
  750     crl::time _highlightStart = 0;
  751 
  752     crl::time _saveDraftStart = 0;
  753     bool _saveDraftText = false;
  754     base::Timer _saveDraftTimer;
  755     base::Timer _saveCloudDraftTimer;
  756 
  757     base::weak_ptr<Ui::Toast::Instance> _topToast;
  758     std::unique_ptr<ChooseMessagesForReport> _chooseForReport;
  759 
  760     object_ptr<Ui::PlainShadow> _topShadow;
  761     bool _inGrab = false;
  762 
  763     int _topDelta = 0;
  764 
  765     rpl::event_stream<> _cancelRequests;
  766 
  767 };