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 "base/weak_ptr.h" 11 #include "chat_helpers/bot_command.h" 12 #include "ui/rp_widget.h" 13 #include "ui/effects/animations.h" 14 #include "media/player/media_player_float.h" 15 #include "mtproto/sender.h" 16 #include "data/data_pts_waiter.h" 17 18 struct HistoryMessageMarkupButton; 19 class MainWindow; 20 class HistoryWidget; 21 class StackItem; 22 struct FileLoadResult; 23 class History; 24 class Image; 25 26 namespace MTP { 27 class Error; 28 } // namespace MTP 29 30 namespace Api { 31 struct SendAction; 32 struct SendOptions; 33 } // namespace Api 34 35 namespace SendMenu { 36 enum class Type; 37 } // namespace SendMenu 38 39 namespace Main { 40 class Session; 41 } // namespace Main 42 43 namespace Data { 44 class WallPaper; 45 struct ForwardDraft; 46 } // namespace Data 47 48 namespace Dialogs { 49 struct RowDescriptor; 50 class Row; 51 class Key; 52 class Widget; 53 } // namespace Dialogs 54 55 namespace Media { 56 namespace Player { 57 class Widget; 58 class VolumeWidget; 59 class Panel; 60 struct TrackState; 61 } // namespace Player 62 } // namespace Media 63 64 namespace Export { 65 namespace View { 66 class TopBar; 67 class PanelController; 68 struct Content; 69 } // namespace View 70 } // namespace Export 71 72 namespace Ui { 73 class ConfirmBox; 74 class ResizeArea; 75 class PlainShadow; 76 class DropdownMenu; 77 enum class ReportReason; 78 template <typename Widget> 79 class SlideWrap; 80 } // namespace Ui 81 82 namespace Window { 83 class SessionController; 84 template <typename Inner> 85 class TopBarWrapWidget; 86 class SectionMemento; 87 class SectionWidget; 88 class AbstractSectionWidget; 89 class ConnectionState; 90 struct SectionSlideParams; 91 struct SectionShow; 92 enum class Column; 93 class HistoryHider; 94 } // namespace Window 95 96 namespace Calls { 97 class Call; 98 class GroupCall; 99 class TopBar; 100 } // namespace Calls 101 102 namespace Core { 103 class Changelogs; 104 } // namespace Core 105 106 namespace InlineBots { 107 namespace Layout { 108 class ItemBase; 109 } // namespace Layout 110 } // namespace InlineBots 111 112 class MainWidget 113 : public Ui::RpWidget 114 , private Media::Player::FloatDelegate 115 , private base::Subscriber { 116 Q_OBJECT 117 118 public: 119 using SectionShow = Window::SectionShow; 120 121 MainWidget( 122 QWidget *parent, 123 not_null<Window::SessionController*> controller); 124 ~MainWidget(); 125 126 [[nodiscard]] Main::Session &session() const; 127 [[nodiscard]] not_null<Window::SessionController*> controller() const; 128 129 [[nodiscard]] bool isMainSectionShown() const; 130 [[nodiscard]] bool isThirdSectionShown() const; 131 132 void returnTabbedSelector(); 133 134 void showAnimated(const QPixmap &bgAnimCache, bool back = false); 135 136 void activate(); 137 138 void windowShown(); 139 140 void dialogsToUp(); 141 void checkHistoryActivation(); 142 143 PeerData *peer(); 144 145 int backgroundFromY() const; 146 void showSection( 147 std::shared_ptr<Window::SectionMemento> memento, 148 const SectionShow ¶ms); 149 void updateColumnLayout(); 150 bool stackIsEmpty() const; 151 void showBackFromStack( 152 const SectionShow ¶ms); 153 void orderWidgets(); 154 QRect historyRect() const; 155 QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms); 156 void checkMainSectionToLayer(); 157 158 [[nodiscard]] SendMenu::Type sendMenuType() const; 159 bool sendExistingDocument(not_null<DocumentData*> document); 160 bool sendExistingDocument( 161 not_null<DocumentData*> document, 162 Api::SendOptions options); 163 164 bool isActive() const; 165 [[nodiscard]] bool doWeMarkAsRead() const; 166 167 void saveFieldToHistoryLocalDraft(); 168 169 int32 dlgsWidth() const; 170 171 void showForwardLayer(Data::ForwardDraft &&draft); 172 void showSendPathsLayer(); 173 void shareUrlLayer(const QString &url, const QString &text); 174 void inlineSwitchLayer(const QString &botAndQuery); 175 void hiderLayer(base::unique_qptr<Window::HistoryHider> h); 176 bool setForwardDraft(PeerId peer, Data::ForwardDraft &&draft); 177 bool shareUrl( 178 PeerId peerId, 179 const QString &url, 180 const QString &text); 181 bool inlineSwitchChosen(PeerId peerId, const QString &botAndQuery); 182 bool sendPaths(PeerId peerId); 183 void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data); 184 bool selectingPeer() const; 185 186 void sendBotCommand(Bot::SendCommandRequest request); 187 void hideSingleUseKeyboard(PeerData *peer, MsgId replyTo); 188 bool insertBotCommand(const QString &cmd); 189 190 void searchMessages(const QString &query, Dialogs::Key inChat); 191 192 void setChatBackground( 193 const Data::WallPaper &background, 194 QImage &&image = QImage()); 195 bool chatBackgroundLoading(); 196 float64 chatBackgroundProgress() const; 197 void checkChatBackground(); 198 Image *newBackgroundThumb(); 199 200 // Does offerPeer or showPeerHistory. 201 void choosePeer(PeerId peerId, MsgId showAtMsgId); 202 void clearBotStartToken(PeerData *peer); 203 204 void ctrlEnterSubmitUpdated(); 205 void setInnerFocus(); 206 207 bool contentOverlapped(const QRect &globalRect); 208 209 void searchInChat(Dialogs::Key chat); 210 211 void showChooseReportMessages( 212 not_null<PeerData*> peer, 213 Ui::ReportReason reason, 214 Fn<void(MessageIdsList)> done); 215 void clearChooseReportMessages(); 216 217 void toggleChooseChatTheme(not_null<PeerData*> peer); 218 219 void ui_showPeerHistory( 220 PeerId peer, 221 const SectionShow ¶ms, 222 MsgId msgId); 223 224 bool notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo); 225 226 using FloatDelegate::floatPlayerAreaUpdated; 227 228 void closeBothPlayers(); 229 void stopAndClosePlayer(); 230 231 bool preventsCloseSection(Fn<void()> callback) const; 232 bool preventsCloseSection( 233 Fn<void()> callback, 234 const SectionShow ¶ms) const; 235 236 public Q_SLOTS: 237 void inlineResultLoadProgress(FileLoader *loader); 238 void inlineResultLoadFailed(FileLoader *loader, bool started); 239 240 void dialogsCancelled(); 241 242 protected: 243 void paintEvent(QPaintEvent *e) override; 244 void resizeEvent(QResizeEvent *e) override; 245 void keyPressEvent(QKeyEvent *e) override; 246 bool eventFilter(QObject *o, QEvent *e) override; 247 248 private: 249 void animationCallback(); 250 void handleAdaptiveLayoutUpdate(); 251 void updateWindowAdaptiveLayout(); 252 void handleAudioUpdate(const Media::Player::TrackState &state); 253 void updateMediaPlayerPosition(); 254 void updateMediaPlaylistPosition(int x); 255 void updateControlsGeometry(); 256 void updateDialogsWidthAnimated(); 257 void updateThirdColumnToCurrentChat( 258 Dialogs::Key key, 259 bool canWrite); 260 [[nodiscard]] bool saveThirdSectionToStackBack() const; 261 [[nodiscard]] auto thirdSectionForCurrentMainSection(Dialogs::Key key) 262 -> std::shared_ptr<Window::SectionMemento>; 263 264 void setupConnectingWidget(); 265 void createPlayer(); 266 void playerHeightUpdated(); 267 268 void setCurrentCall(Calls::Call *call); 269 void setCurrentGroupCall(Calls::GroupCall *call); 270 void createCallTopBar(); 271 void destroyCallTopBar(); 272 void callTopBarHeightUpdated(int callTopBarHeight); 273 274 void setCurrentExportView(Export::View::PanelController *view); 275 void createExportTopBar(Export::View::Content &&data); 276 void destroyExportTopBar(); 277 void exportTopBarHeightUpdated(); 278 279 Window::SectionSlideParams prepareShowAnimation( 280 bool willHaveTopBarShadow); 281 void showNewSection( 282 std::shared_ptr<Window::SectionMemento> memento, 283 const SectionShow ¶ms); 284 void dropMainSection(Window::SectionWidget *widget); 285 286 Window::SectionSlideParams prepareThirdSectionAnimation(Window::SectionWidget *section); 287 288 // All this methods use the prepareShowAnimation(). 289 Window::SectionSlideParams prepareMainSectionAnimation(Window::SectionWidget *section); 290 Window::SectionSlideParams prepareHistoryAnimation(PeerId historyPeerId); 291 Window::SectionSlideParams prepareDialogsAnimation(); 292 293 void saveSectionInStack(); 294 295 int getMainSectionTop() const; 296 int getThirdSectionTop() const; 297 298 void hideAll(); 299 void showAll(); 300 void clearHider(not_null<Window::HistoryHider*> instance); 301 302 [[nodiscard]] auto floatPlayerDelegate() 303 -> not_null<Media::Player::FloatDelegate*>; 304 not_null<Ui::RpWidget*> floatPlayerWidget() override; 305 not_null<Media::Player::FloatSectionDelegate*> floatPlayerGetSection( 306 Window::Column column) override; 307 void floatPlayerEnumerateSections(Fn<void( 308 not_null<Media::Player::FloatSectionDelegate*> widget, 309 Window::Column widgetColumn)> callback) override; 310 bool floatPlayerIsVisible(not_null<HistoryItem*> item) override; 311 void floatPlayerClosed(FullMsgId itemId); 312 void floatPlayerDoubleClickEvent( 313 not_null<const HistoryItem*> item) override; 314 315 void refreshResizeAreas(); 316 template <typename MoveCallback, typename FinishCallback> 317 void createResizeArea( 318 object_ptr<Ui::ResizeArea> &area, 319 MoveCallback &&moveCallback, 320 FinishCallback &&finishCallback); 321 void ensureFirstColumnResizeAreaCreated(); 322 void ensureThirdColumnResizeAreaCreated(); 323 324 bool isReadyChatBackground( 325 const Data::WallPaper &background, 326 const QImage &image) const; 327 void setReadyChatBackground( 328 const Data::WallPaper &background, 329 QImage &&image); 330 331 void handleHistoryBack(); 332 333 bool isOneColumn() const; 334 bool isNormalColumn() const; 335 bool isThreeColumn() const; 336 337 const not_null<Window::SessionController*> _controller; 338 339 Ui::Animations::Simple _a_show; 340 bool _showBack = false; 341 QPixmap _cacheUnder, _cacheOver; 342 343 int _dialogsWidth = 0; 344 int _thirdColumnWidth = 0; 345 Ui::Animations::Simple _a_dialogsWidth; 346 347 object_ptr<Ui::PlainShadow> _sideShadow; 348 object_ptr<Ui::PlainShadow> _thirdShadow = { nullptr }; 349 object_ptr<Ui::ResizeArea> _firstColumnResizeArea = { nullptr }; 350 object_ptr<Ui::ResizeArea> _thirdColumnResizeArea = { nullptr }; 351 object_ptr<Dialogs::Widget> _dialogs; 352 object_ptr<HistoryWidget> _history; 353 object_ptr<Window::SectionWidget> _mainSection = { nullptr }; 354 object_ptr<Window::SectionWidget> _thirdSection = { nullptr }; 355 std::shared_ptr<Window::SectionMemento> _thirdSectionFromStack; 356 std::unique_ptr<Window::ConnectionState> _connecting; 357 358 base::weak_ptr<Calls::Call> _currentCall; 359 base::weak_ptr<Calls::GroupCall> _currentGroupCall; 360 rpl::lifetime _currentCallLifetime; 361 object_ptr<Ui::SlideWrap<Calls::TopBar>> _callTopBar = { nullptr }; 362 363 Export::View::PanelController *_currentExportView = nullptr; 364 object_ptr<Window::TopBarWrapWidget<Export::View::TopBar>> _exportTopBar 365 = { nullptr }; 366 rpl::lifetime _exportViewLifetime; 367 368 object_ptr<Window::TopBarWrapWidget<Media::Player::Widget>> _player 369 = { nullptr }; 370 object_ptr<Media::Player::VolumeWidget> _playerVolume = { nullptr }; 371 object_ptr<Media::Player::Panel> _playerPlaylist; 372 bool _playerUsingPanel = false; 373 374 base::unique_qptr<Window::HistoryHider> _hider; 375 std::vector<std::unique_ptr<StackItem>> _stack; 376 377 int _playerHeight = 0; 378 int _callTopBarHeight = 0; 379 int _exportTopBarHeight = 0; 380 int _contentScrollAddToY = 0; 381 382 PhotoData *_deletingPhoto = nullptr; 383 384 struct SettingBackground; 385 std::unique_ptr<SettingBackground> _background; 386 387 bool _firstColumnResizing = false; 388 int _firstColumnResizingShift = 0; 389 390 // _changelogs depends on _data, subscribes on chats loading event. 391 const std::unique_ptr<Core::Changelogs> _changelogs; 392 393 }; 394 395 namespace App { 396 MainWidget *main(); 397 } // namespace App 398