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 "dialogs/dialogs_key.h"
11 #include "window/section_widget.h"
12 #include "ui/effects/animations.h"
13 #include "ui/widgets/scroll_area.h"
14 #include "ui/special_buttons.h"
15 #include "mtproto/sender.h"
16 #include "api/api_single_message_search.h"
17 
18 #include <QtCore/QTimer>
19 
20 namespace MTP {
21 class Error;
22 } // namespace MTP
23 
24 namespace Main {
25 class Session;
26 } // namespace Main
27 
28 namespace HistoryView {
29 class TopBarWidget;
30 } // namespace HistoryView
31 
32 namespace Ui {
33 class IconButton;
34 class PopupMenu;
35 class DropdownMenu;
36 class FlatButton;
37 class FlatInput;
38 class CrossButton;
39 template <typename Widget>
40 class FadeWrapScaled;
41 } // namespace Ui
42 
43 namespace Window {
44 class SessionController;
45 class ConnectionState;
46 } // namespace Window
47 
48 namespace Dialogs {
49 
50 struct RowDescriptor;
51 class Row;
52 class FakeRow;
53 class Key;
54 struct ChosenRow;
55 class InnerWidget;
56 enum class SearchRequestType;
57 
58 class Widget final : public Window::AbstractSectionWidget {
59 	Q_OBJECT
60 
61 public:
62 	Widget(QWidget *parent, not_null<Window::SessionController*> controller);
63 
64 	// When resizing the widget with top edge moved up or down and we
65 	// want to add this top movement to the scroll position, so inner
66 	// content will not move.
67 	void setGeometryWithTopMoved(const QRect &newGeometry, int topDelta);
68 
69 	void updateDragInScroll(bool inScroll);
70 
71 	void searchInChat(Key chat);
72 	void setInnerFocus();
73 
74 	void jumpToTop();
75 
76 	void startWidthAnimation();
77 	void stopWidthAnimation();
78 
hasTopBarShadow()79 	bool hasTopBarShadow() const {
80 		return true;
81 	}
82 	void showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams &params);
83 	void showFast();
84 
85 	void scrollToEntry(const RowDescriptor &entry);
86 
87 	void searchMessages(const QString &query, Key inChat = {});
88 	void onSearchMore();
89 
90 	void updateForwardBar();
91 
92 	[[nodiscard]] rpl::producer<> closeForwardBarRequests() const;
93 
94 	// Float player interface.
95 	bool floatPlayerHandleWheelEvent(QEvent *e) override;
96 	QRect floatPlayerAvailableRect() override;
97 
98 	~Widget();
99 
100 Q_SIGNALS:
101 	void cancelled();
102 
103 public Q_SLOTS:
104 	void onDraggingScrollDelta(int delta);
105 
106 	void onListScroll();
107 	bool onCancelSearch();
108 	void onCancelSearchInChat();
109 
110 	void onFilterCursorMoved(int from = -1, int to = -1);
111 	void onCompleteHashtag(QString tag);
112 
113 	void onDialogMoved(int movedFrom, int movedTo);
114 	bool onSearchMessages(bool searchCache = false);
115 	void onNeedSearchMessages();
116 
117 	void onChooseByDrag();
118 
119 private Q_SLOTS:
120 	void onDraggingScrollTimer();
121 
122 protected:
123 	void dragEnterEvent(QDragEnterEvent *e) override;
124 	void dragMoveEvent(QDragMoveEvent *e) override;
125 	void dragLeaveEvent(QDragLeaveEvent *e) override;
126 	void dropEvent(QDropEvent *e) override;
127 	void resizeEvent(QResizeEvent *e) override;
128 	void keyPressEvent(QKeyEvent *e) override;
129 	void paintEvent(QPaintEvent *e) override;
130 
131 private:
132 	enum class ShowAnimation {
133 		External,
134 		Internal,
135 	};
136 
137 	void animationCallback();
138 	void searchReceived(
139 		SearchRequestType type,
140 		const MTPmessages_Messages &result,
141 		mtpRequestId requestId);
142 	void peerSearchReceived(
143 		const MTPcontacts_Found &result,
144 		mtpRequestId requestId);
145 	void escape();
146 	void cancelSearchRequest();
147 
148 	void setupSupportMode();
149 	void setupConnectingWidget();
150 	void setupMainMenuToggle();
151 	bool searchForPeersRequired(const QString &query) const;
152 	void setSearchInChat(Key chat, PeerData *from = nullptr);
153 	void showJumpToDate();
154 	void showSearchFrom();
155 	void showMainMenu();
156 	void clearSearchCache();
157 	void updateControlsVisibility(bool fast = false);
158 	void updateLockUnlockVisibility();
159 	void updateLoadMoreChatsVisibility();
160 	void updateJumpToDateVisibility(bool fast = false);
161 	void updateSearchFromVisibility(bool fast = false);
162 	void updateControlsGeometry();
163 	void refreshFolderTopBar();
164 	void checkUpdateStatus();
165 	void changeOpenedFolder(Data::Folder *folder, anim::type animated);
166 	QPixmap grabForFolderSlideAnimation();
167 	void startSlideAnimation();
168 
169 	void fullSearchRefreshOn(rpl::producer<> events);
170 	void applyFilterUpdate(bool force = false);
171 	void refreshLoadMoreButton(bool mayBlock, bool isBlocked);
172 	void loadMoreBlockedByDate();
173 
174 	void searchFailed(
175 		SearchRequestType type,
176 		const MTP::Error &error,
177 		mtpRequestId requestId);
178 	void peopleFailed(const MTP::Error &error, mtpRequestId requestId);
179 
180 	void scrollToTop();
181 	void setupScrollUpButton();
182 	void updateScrollUpVisibility();
183 	void startScrollUpButtonAnimation(bool shown);
184 	void updateScrollUpPosition();
185 
186 	MTP::Sender _api;
187 
188 	bool _dragInScroll = false;
189 	bool _dragForward = false;
190 	QTimer _chooseByDragTimer;
191 
192 	object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
193 	object_ptr<Ui::RpWidget> _searchControls;
194 	object_ptr<HistoryView::TopBarWidget> _folderTopBar = { nullptr } ;
195 	object_ptr<Ui::IconButton> _mainMenuToggle;
196 	object_ptr<Ui::IconButton> _searchForNarrowFilters;
197 	object_ptr<Ui::FlatInput> _filter;
198 	object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _chooseFromUser;
199 	object_ptr<Ui::FadeWrapScaled<Ui::IconButton>> _jumpToDate;
200 	object_ptr<Ui::CrossButton> _cancelSearch;
201 	object_ptr<Ui::IconButton> _lockUnlock;
202 	object_ptr<Ui::ScrollArea> _scroll;
203 	QPointer<InnerWidget> _inner;
204 	class BottomButton;
205 	object_ptr<BottomButton> _updateTelegram = { nullptr };
206 	object_ptr<BottomButton> _loadMoreChats = { nullptr };
207 	std::unique_ptr<Window::ConnectionState> _connecting;
208 
209 	Ui::Animations::Simple _scrollToAnimation;
210 	Ui::Animations::Simple _a_show;
211 	Window::SlideDirection _showDirection = Window::SlideDirection();
212 	QPixmap _cacheUnder, _cacheOver;
213 	ShowAnimation _showAnimationType = ShowAnimation::External;
214 
215 	Ui::Animations::Simple _scrollToTopShown;
216 	bool _scrollToTopIsShown = false;
217 	object_ptr<Ui::HistoryDownButton> _scrollToTop;
218 
219 	Data::Folder *_openedFolder = nullptr;
220 	Dialogs::Key _searchInChat;
221 	History *_searchInMigrated = nullptr;
222 	PeerData *_searchFromAuthor = nullptr;
223 	QString _lastFilterText;
224 
225 	QTimer _searchTimer;
226 
227 	QString _peerSearchQuery;
228 	bool _peerSearchFull = false;
229 	mtpRequestId _peerSearchRequest = 0;
230 
231 	QString _searchQuery;
232 	PeerData *_searchQueryFrom = nullptr;
233 	int32 _searchNextRate = 0;
234 	bool _searchFull = false;
235 	bool _searchFullMigrated = false;
236 	int _searchInHistoryRequest = 0; // Not real mtpRequestId.
237 	mtpRequestId _searchRequest = 0;
238 
239 	base::flat_map<QString, MTPmessages_Messages> _searchCache;
240 	Api::SingleMessageSearch _singleMessageSearch;
241 	base::flat_map<mtpRequestId, QString> _searchQueries;
242 	base::flat_map<QString, MTPcontacts_Found> _peerSearchCache;
243 	base::flat_map<mtpRequestId, QString> _peerSearchQueries;
244 
245 	QPixmap _widthAnimationCache;
246 
247 	object_ptr<QTimer> _draggingScrollTimer = { nullptr };
248 	int _draggingScrollDelta = 0;
249 
250 	int _topDelta = 0;
251 
252 	rpl::event_stream<> _closeForwardBarRequests;
253 
254 };
255 
256 } // namespace Dialogs
257