tdesktop/Telegram/SourceFiles/mainwidget.h

545 lines
16 KiB
C
Raw Normal View History

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
2019-01-18 11:26:43 +00:00
#include "base/timer.h"
#include "base/weak_ptr.h"
2017-09-13 16:57:44 +00:00
#include "ui/rp_widget.h"
2019-04-02 09:13:30 +00:00
#include "ui/effects/animations.h"
2018-11-05 11:16:09 +00:00
#include "media/player/media_player_float.h"
#include "data/data_pts_waiter.h"
struct HistoryMessageMarkupButton;
class MainWindow;
class ConfirmBox;
class HistoryWidget;
class StackItem;
2017-12-19 16:57:42 +00:00
struct FileLoadResult;
2019-07-24 11:45:24 +00:00
namespace Main {
class Session;
} // namespace Main
namespace Notify {
struct PeerUpdate;
} // namespace Notify
2019-01-03 12:36:01 +00:00
namespace Data {
2019-01-28 13:59:49 +00:00
class WallPaper;
2019-01-03 12:36:01 +00:00
} // namespace Data
namespace Dialogs {
struct RowDescriptor;
class Row;
class Key;
2019-04-24 10:15:10 +00:00
class Widget;
} // namespace Dialogs
2016-09-17 19:28:33 +00:00
namespace Media {
namespace Player {
class Widget;
class VolumeWidget;
class Panel;
struct TrackState;
2016-09-17 19:28:33 +00:00
} // namespace Player
} // namespace Media
namespace Export {
namespace View {
class TopBar;
class PanelController;
struct Content;
} // namespace View
} // namespace Export
namespace Ui {
class ResizeArea;
class PlainShadow;
class DropdownMenu;
template <typename Widget>
2017-09-13 16:57:44 +00:00
class SlideWrap;
} // namespace Ui
namespace Window {
class SessionController;
template <typename Inner>
class TopBarWrapWidget;
class SectionMemento;
class SectionWidget;
class AbstractSectionWidget;
2019-02-10 16:29:55 +00:00
class ConnectionState;
struct SectionSlideParams;
struct SectionShow;
enum class Column;
class HistoryHider;
} // namespace Window
namespace Calls {
class Call;
class TopBar;
} // namespace Calls
namespace InlineBots {
namespace Layout {
class ItemBase;
} // namespace Layout
} // namespace InlineBots
2018-11-05 11:16:09 +00:00
class MainWidget
: public Ui::RpWidget
, public RPCSender
, private base::Subscriber
, private Media::Player::FloatDelegate {
Q_OBJECT
public:
using SectionShow = Window::SectionShow;
MainWidget(QWidget *parent, not_null<Window::SessionController*> controller);
2019-07-24 11:45:24 +00:00
Main::Session &session() const;
2019-01-18 12:27:37 +00:00
bool isMainSectionShown() const;
bool isThirdSectionShown() const;
int contentScrollAddToY() const;
2015-07-03 08:47:16 +00:00
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
void start();
2015-05-19 15:46:45 +00:00
void openPeerByName(
const QString &name,
MsgId msgId = ShowAtUnreadMsgId,
const QString &startToken = QString(),
FullMsgId clickFromMessageId = FullMsgId());
2015-05-19 15:46:45 +00:00
bool started();
void incrementSticker(DocumentData *sticker);
void activate();
2019-07-18 14:06:38 +00:00
[[nodiscard]] bool updateReceived(const mtpPrime *from, const mtpPrime *end);
void refreshDialog(Dialogs::Key key);
void removeDialog(Dialogs::Key key);
2018-01-22 17:39:20 +00:00
void repaintDialogRow(Dialogs::Mode list, not_null<Dialogs::Row*> row);
void repaintDialogRow(Dialogs::RowDescriptor row);
void windowShown();
void sentUpdatesReceived(uint64 randomId, const MTPUpdates &updates);
void sentUpdatesReceived(const MTPUpdates &updates) {
return sentUpdatesReceived(0, updates);
}
bool deleteChannelFailed(const RPCError &error);
void historyToDown(History *hist);
void dialogsToUp();
void newUnreadMsg(
not_null<History*> history,
not_null<HistoryItem*> item);
void markActiveHistoryAsRead();
PeerData *peer();
int backgroundFromY() const;
void showSection(
Window::SectionMemento &&memento,
const SectionShow &params);
void updateColumnLayout();
bool stackIsEmpty() const;
void showBackFromStack(
const SectionShow &params);
void orderWidgets();
QRect historyRect() const;
QPixmap grabForShowAnimation(const Window::SectionSlideParams &params);
void checkMainSectionToLayer();
void onSendFileConfirm(
const std::shared_ptr<FileLoadResult> &file,
const std::optional<FullMsgId> &oldId);
bool onSendSticker(DocumentData *sticker);
void updateOnlineDisplayIn(int32 msecs);
bool isActive() const;
bool doWeReadServerHistory() const;
bool doWeReadMentions() const;
bool lastWasOnline() const;
crl::time lastSetOnline() const;
void saveDraftToCloud();
void applyCloudDraft(History *history);
void writeDrafts(History *history);
int32 dlgsWidth() const;
void showForwardLayer(MessageIdsList &&items);
void showSendPathsLayer();
void cancelUploadLayer(not_null<HistoryItem*> item);
2015-10-18 12:49:34 +00:00
void shareUrlLayer(const QString &url, const QString &text);
void inlineSwitchLayer(const QString &botAndQuery);
void hiderLayer(base::unique_qptr<Window::HistoryHider> h);
bool setForwardDraft(PeerId peer, MessageIdsList &&items);
bool shareUrl(
PeerId peerId,
const QString &url,
const QString &text);
2017-12-30 08:15:42 +00:00
void replyToItem(not_null<HistoryItem*> item);
bool inlineSwitchChosen(PeerId peerId, const QString &botAndQuery);
bool sendPaths(PeerId peerId);
void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data);
bool selectingPeer() const;
void deletePhotoLayer(PhotoData *photo);
// While HistoryInner is not HistoryView::ListWidget.
crl::time highlightStartTime(not_null<const HistoryItem*> item) const;
MsgId currentReplyToIdFor(not_null<History*> history) const;
2016-04-14 19:24:42 +00:00
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo);
void hideSingleUseKeyboard(PeerData *peer, MsgId replyTo);
bool insertBotCommand(const QString &cmd);
void searchMessages(const QString &query, Dialogs::Key inChat);
void itemEdited(not_null<HistoryItem*> item);
2014-08-15 11:19:32 +00:00
void checkLastUpdate(bool afterSleep);
bool isIdle() const;
2015-02-03 15:02:46 +00:00
QPixmap cachedBackground(const QRect &forRect, int &x, int &y);
void updateScrollColors();
void setChatBackground(
const Data::WallPaper &background,
QImage &&image = QImage());
2015-02-03 15:02:46 +00:00
bool chatBackgroundLoading();
float64 chatBackgroundProgress() const;
2015-02-03 15:02:46 +00:00
void checkChatBackground();
Image *newBackgroundThumb();
void messageDataReceived(ChannelData *channel, MsgId msgId);
void updateBotKeyboard(History *h);
void pushReplyReturn(not_null<HistoryItem*> item);
void cancelForwarding(not_null<History*> history);
2019-07-26 16:06:22 +00:00
void finishForwarding(not_null<History*> history, bool silent);
2018-01-07 12:04:34 +00:00
// Does offerPeer or showPeerHistory.
void choosePeer(PeerId peerId, MsgId showAtMsgId);
void clearBotStartToken(PeerData *peer);
2015-09-13 08:41:27 +00:00
void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer
2015-09-21 20:57:42 +00:00
void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0);
2015-09-13 08:41:27 +00:00
2015-09-16 13:04:08 +00:00
void ctrlEnterSubmitUpdated();
void setInnerFocus();
2015-09-21 20:57:42 +00:00
void scheduleViewIncrement(HistoryItem *item);
void feedChannelDifference(const MTPDupdates_channelDifference &data);
2015-09-21 20:57:42 +00:00
2019-01-18 11:26:43 +00:00
// Made public for ApiWrap, while it is still here.
// Better would be for this to be moved to ApiWrap.
bool requestingDifference() const {
return _ptsWaiter.requesting();
}
2019-01-18 11:26:43 +00:00
void getDifference();
void updateOnline(bool gotOtherOffline = false);
void checkIdleFinish();
2015-10-01 14:05:05 +00:00
bool contentOverlapped(const QRect &globalRect);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount);
void documentLoadProgress(DocumentData *document);
2018-01-22 17:39:20 +00:00
void searchInChat(Dialogs::Key chat);
void app_sendBotCallback(
not_null<const HistoryMessageMarkupButton*> button,
not_null<const HistoryItem*> msg,
int row,
int column);
void ui_showPeerHistory(
PeerId peer,
const SectionShow &params,
MsgId msgId);
PeerData *ui_getPeerForMouseAction();
void notify_botCommandsChanged(UserData *bot);
void notify_inlineBotRequesting(bool requesting);
void notify_replyMarkupUpdated(const HistoryItem *item);
void notify_inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop);
bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo);
void notify_userIsBotChanged(UserData *bot);
void notify_historyMuteUpdated(History *history);
2015-12-07 13:05:00 +00:00
void closeBothPlayers();
bool isQuitPrevent();
~MainWidget();
signals:
void dialogsUpdated();
public slots:
void documentLoadProgress(FileLoader *loader);
void documentLoadFailed(FileLoader *loader, bool started);
void inlineResultLoadProgress(FileLoader *loader);
void inlineResultLoadFailed(FileLoader *loader, bool started);
void dialogsCancelled();
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
bool eventFilter(QObject *o, QEvent *e) override;
private:
using ChannelGetDifferenceTime = QMap<ChannelData*, crl::time>;
enum class ChannelDifferenceRequest {
Unknown,
PtsGapOrShortPoll,
AfterFail,
};
struct DeleteHistoryRequest {
PeerData *peer;
bool justClearHistory;
};
struct DeleteAllFromUserParams {
ChannelData *channel;
UserData *from;
};
2019-01-18 11:26:43 +00:00
void viewsIncrement();
void sendPing();
void getDifferenceByPts();
void getDifferenceAfterFail();
void animationCallback();
void handleAdaptiveLayoutUpdate();
void updateWindowAdaptiveLayout();
void handleAudioUpdate(const Media::Player::TrackState &state);
void updateMediaPlayerPosition();
void updateMediaPlaylistPosition(int x);
void updateControlsGeometry();
void updateDialogsWidthAnimated();
void updateThirdColumnToCurrentChat(
Dialogs::Key key,
bool canWrite);
[[nodiscard]] bool saveThirdSectionToStackBack() const;
[[nodiscard]] auto thirdSectionForCurrentMainSection(Dialogs::Key key)
-> std::unique_ptr<Window::SectionMemento>;
void userIsContactUpdated(not_null<UserData*> user);
2018-05-07 17:44:33 +00:00
void setupConnectingWidget();
void createPlayer();
void playerHeightUpdated();
void setCurrentCall(Calls::Call *call);
void createCallTopBar();
void destroyCallTopBar();
2017-09-13 16:57:44 +00:00
void callTopBarHeightUpdated(int callTopBarHeight);
void setCurrentExportView(Export::View::PanelController *view);
void createExportTopBar(Export::View::Content &&data);
void destroyExportTopBar();
void exportTopBarHeightUpdated();
Window::SectionSlideParams prepareShowAnimation(
bool willHaveTopBarShadow);
void showNewSection(
Window::SectionMemento &&memento,
const SectionShow &params);
void dropMainSection(Window::SectionWidget *widget);
Window::SectionSlideParams prepareThirdSectionAnimation(Window::SectionWidget *section);
// All this methods use the prepareShowAnimation().
Window::SectionSlideParams prepareMainSectionAnimation(Window::SectionWidget *section);
Window::SectionSlideParams prepareHistoryAnimation(PeerId historyPeerId);
Window::SectionSlideParams prepareDialogsAnimation();
void saveSectionInStack();
void getChannelDifference(ChannelData *channel, ChannelDifferenceRequest from = ChannelDifferenceRequest::Unknown);
void gotDifference(const MTPupdates_Difference &diff);
bool failDifference(const RPCError &e);
void feedDifference(const MTPVector<MTPUser> &users, const MTPVector<MTPChat> &chats, const MTPVector<MTPMessage> &msgs, const MTPVector<MTPUpdate> &other);
void gotState(const MTPupdates_State &state);
void updSetState(int32 pts, int32 date, int32 qts, int32 seq);
2015-09-13 08:41:27 +00:00
void gotChannelDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff);
bool failChannelDifference(ChannelData *channel, const RPCError &err);
void failDifferenceStartTimerFor(ChannelData *channel);
void feedUpdateVector(
const MTPVector<MTPUpdate> &updates,
bool skipMessageIds = false);
// Doesn't call sendHistoryChangeNotifications itself.
void feedMessageIds(const MTPVector<MTPUpdate> &updates);
// Doesn't call sendHistoryChangeNotifications itself.
void feedUpdate(const MTPUpdate &update);
void usernameResolveDone(QPair<MsgId, QString> msgIdAndStartToken, const MTPcontacts_ResolvedPeer &result);
bool usernameResolveFail(QString name, const RPCError &error);
int getMainSectionTop() const;
int getThirdSectionTop() const;
void hideAll();
void showAll();
void clearHider(not_null<Window::HistoryHider*> instance);
2019-01-18 11:26:43 +00:00
void cacheBackground();
void clearCachedBackground();
2018-11-05 11:16:09 +00:00
not_null<Media::Player::FloatDelegate*> floatPlayerDelegate();
not_null<Ui::RpWidget*> floatPlayerWidget() override;
not_null<Window::SessionController*> floatPlayerController() override;
2018-11-05 11:16:09 +00:00
not_null<Window::AbstractSectionWidget*> floatPlayerGetSection(
Window::Column column) override;
void floatPlayerEnumerateSections(Fn<void(
not_null<Window::AbstractSectionWidget*> widget,
Window::Column widgetColumn)> callback) override;
2018-11-05 13:18:54 +00:00
bool floatPlayerIsVisible(not_null<HistoryItem*> item) override;
void floatPlayerClosed(FullMsgId itemId);
bool getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, crl::time &curTime);
void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req);
bool viewsIncrementFail(const RPCError &error, mtpRequestId req);
void updateStatusDone(const MTPBool &result);
bool updateStatusFail(const RPCError &error);
void refreshResizeAreas();
template <typename MoveCallback, typename FinishCallback>
void createResizeArea(
object_ptr<Ui::ResizeArea> &area,
MoveCallback &&moveCallback,
FinishCallback &&finishCallback);
void ensureFirstColumnResizeAreaCreated();
void ensureThirdColumnResizeAreaCreated();
bool isReadyChatBackground(
const Data::WallPaper &background,
const QImage &image) const;
void setReadyChatBackground(
const Data::WallPaper &background,
QImage &&image);
2019-01-16 12:39:35 +00:00
void handleHistoryBack();
not_null<Window::SessionController*> _controller;
bool _started = false;
2019-04-02 09:13:30 +00:00
Ui::Animations::Simple _a_show;
bool _showBack = false;
2015-10-17 14:52:26 +00:00
QPixmap _cacheUnder, _cacheOver;
2017-11-12 16:50:58 +00:00
int _dialogsWidth = 0;
int _thirdColumnWidth = 0;
2019-04-02 09:13:30 +00:00
Ui::Animations::Simple _a_dialogsWidth;
object_ptr<Ui::PlainShadow> _sideShadow;
object_ptr<Ui::PlainShadow> _thirdShadow = { nullptr };
object_ptr<Ui::ResizeArea> _firstColumnResizeArea = { nullptr };
object_ptr<Ui::ResizeArea> _thirdColumnResizeArea = { nullptr };
2019-04-24 10:15:10 +00:00
object_ptr<Dialogs::Widget> _dialogs;
object_ptr<HistoryWidget> _history;
object_ptr<Window::SectionWidget> _mainSection = { nullptr };
object_ptr<Window::SectionWidget> _thirdSection = { nullptr };
std::unique_ptr<Window::SectionMemento> _thirdSectionFromStack;
2019-02-10 16:29:55 +00:00
std::unique_ptr<Window::ConnectionState> _connecting;
base::weak_ptr<Calls::Call> _currentCall;
2017-09-13 16:57:44 +00:00
object_ptr<Ui::SlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
Export::View::PanelController *_currentExportView = nullptr;
object_ptr<Window::TopBarWrapWidget<Export::View::TopBar>> _exportTopBar
= { nullptr };
object_ptr<Window::TopBarWrapWidget<Media::Player::Widget>> _player
= { nullptr };
object_ptr<Media::Player::VolumeWidget> _playerVolume = { nullptr };
object_ptr<Media::Player::Panel> _playerPlaylist;
bool _playerUsingPanel = false;
base::unique_qptr<Window::HistoryHider> _hider;
std::vector<std::unique_ptr<StackItem>> _stack;
int _playerHeight = 0;
int _callTopBarHeight = 0;
int _exportTopBarHeight = 0;
int _contentScrollAddToY = 0;
2015-07-03 08:47:16 +00:00
int32 updDate = 0;
int32 updQts = -1;
int32 updSeq = 0;
2019-01-18 11:26:43 +00:00
base::Timer _noUpdatesTimer;
2015-09-13 08:41:27 +00:00
PtsWaiter _ptsWaiter;
ChannelGetDifferenceTime _channelGetDifferenceTimeByPts, _channelGetDifferenceTimeAfterFail;
crl::time _getDifferenceTimeByPts = 0;
crl::time _getDifferenceTimeAfterFail = 0;
2015-09-13 08:41:27 +00:00
2019-01-18 11:26:43 +00:00
base::Timer _byPtsTimer;
2015-09-13 08:41:27 +00:00
QMap<int32, MTPUpdates> _bySeqUpdates;
2019-01-18 11:26:43 +00:00
base::Timer _bySeqTimer;
2015-09-13 08:41:27 +00:00
2019-01-18 11:26:43 +00:00
base::Timer _byMinChannelTimer;
mtpRequestId _onlineRequest = 0;
2019-01-18 11:26:43 +00:00
base::Timer _onlineTimer;
base::Timer _idleFinishTimer;
bool _lastWasOnline = false;
crl::time _lastSetOnline = 0;
bool _isIdle = false;
int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails
2019-01-16 12:25:29 +00:00
QMap<ChannelData*, int32> _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails
2019-01-18 11:26:43 +00:00
base::Timer _failDifferenceTimer;
crl::time _lastUpdateTime = 0;
bool _handlingChannelDifference = false;
2015-02-03 15:02:46 +00:00
QPixmap _cachedBackground;
QRect _cachedFor, _willCacheFor;
int _cachedX = 0;
int _cachedY = 0;
2019-01-18 11:26:43 +00:00
base::Timer _cacheBackgroundTimer;
2015-02-03 15:02:46 +00:00
PhotoData *_deletingPhoto = nullptr;
2019-01-16 12:25:29 +00:00
using ViewsIncrementMap = QMap<MsgId, bool>;
QMap<PeerData*, ViewsIncrementMap> _viewsIncremented, _viewsToIncrement;
QMap<PeerData*, mtpRequestId> _viewsIncrementRequests;
QMap<mtpRequestId, PeerData*> _viewsIncrementByRequest;
2019-01-18 11:26:43 +00:00
base::Timer _viewsIncrementTimer;
2015-09-21 20:57:42 +00:00
2019-01-16 12:39:35 +00:00
struct SettingBackground;
std::unique_ptr<SettingBackground> _background;
2015-02-03 15:02:46 +00:00
bool _firstColumnResizing = false;
int _firstColumnResizingShift = 0;
};