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/view/history_view_element.h" 11 #include "history/admin_log/history_admin_log_item.h" 12 #include "history/admin_log/history_admin_log_section.h" 13 #include "ui/rp_widget.h" 14 #include "ui/effects/animations.h" 15 #include "ui/widgets/tooltip.h" 16 #include "mtproto/sender.h" 17 #include "base/timer.h" 18 19 struct ChatRestrictionsInfo; 20 21 namespace Data { 22 class CloudImageView; 23 } // namespace Data 24 25 namespace Main { 26 class Session; 27 } // namespace Main 28 29 namespace HistoryView { 30 class Element; 31 struct TextState; 32 struct StateRequest; 33 enum class CursorState : char; 34 enum class PointState : char; 35 } // namespace HistoryView 36 37 namespace Ui { 38 class PopupMenu; 39 class ChatStyle; 40 } // namespace Ui 41 42 namespace Window { 43 class SessionController; 44 } // namespace Window 45 46 namespace AdminLog { 47 48 class SectionMemento; 49 50 class InnerWidget final 51 : public Ui::RpWidget 52 , public Ui::AbstractTooltipShower 53 , public HistoryView::ElementDelegate 54 , private base::Subscriber { 55 public: 56 InnerWidget( 57 QWidget *parent, 58 not_null<Window::SessionController*> controller, 59 not_null<ChannelData*> channel); 60 61 [[nodiscard]] Main::Session &session() const; theme()62 [[nodiscard]] not_null<Ui::ChatTheme*> theme() const { 63 return _theme.get(); 64 } 65 66 [[nodiscard]] rpl::producer<> showSearchSignal() const; 67 [[nodiscard]] rpl::producer<int> scrollToSignal() const; 68 [[nodiscard]] rpl::producer<> cancelSignal() const; 69 channel()70 [[nodiscard]] not_null<ChannelData*> channel() const { 71 return _channel; 72 } 73 74 // Set the correct scroll position after being resized. 75 void restoreScrollPosition(); 76 resizeToWidth(int newWidth,int minHeight)77 void resizeToWidth(int newWidth, int minHeight) { 78 _minHeight = minHeight; 79 return TWidget::resizeToWidth(newWidth); 80 } 81 82 void saveState(not_null<SectionMemento*> memento); 83 void restoreState(not_null<SectionMemento*> memento); 84 85 // Empty "flags" means all events. 86 void applyFilter(FilterValue &&value); 87 void applySearch(const QString &query); 88 void showFilter(Fn<void(FilterValue &&filter)> callback); 89 90 // Ui::AbstractTooltipShower interface. 91 QString tooltipText() const override; 92 QPoint tooltipPos() const override; 93 bool tooltipWindowActive() const override; 94 95 // HistoryView::ElementDelegate interface. 96 HistoryView::Context elementContext() override; 97 std::unique_ptr<HistoryView::Element> elementCreate( 98 not_null<HistoryMessage*> message, 99 HistoryView::Element *replacing = nullptr) override; 100 std::unique_ptr<HistoryView::Element> elementCreate( 101 not_null<HistoryService*> message, 102 HistoryView::Element *replacing = nullptr) override; 103 bool elementUnderCursor( 104 not_null<const HistoryView::Element*> view) override; 105 crl::time elementHighlightTime( 106 not_null<const HistoryItem*> item) override; 107 bool elementInSelectionMode() override; 108 bool elementIntersectsRange( 109 not_null<const HistoryView::Element*> view, 110 int from, 111 int till) override; 112 void elementStartStickerLoop( 113 not_null<const HistoryView::Element*> view) override; 114 void elementShowPollResults( 115 not_null<PollData*> poll, 116 FullMsgId context) override; 117 void elementOpenPhoto( 118 not_null<PhotoData*> photo, 119 FullMsgId context) override; 120 void elementOpenDocument( 121 not_null<DocumentData*> document, 122 FullMsgId context, 123 bool showInMediaView = false) override; 124 void elementCancelUpload(const FullMsgId &context) override; 125 void elementShowTooltip( 126 const TextWithEntities &text, 127 Fn<void()> hiddenCallback) override; 128 bool elementIsGifPaused() override; 129 bool elementHideReply( 130 not_null<const HistoryView::Element*> view) override; 131 bool elementShownUnread( 132 not_null<const HistoryView::Element*> view) override; 133 void elementSendBotCommand( 134 const QString &command, 135 const FullMsgId &context) override; 136 void elementHandleViaClick(not_null<UserData*> bot) override; 137 bool elementIsChatWide() override; 138 not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override; 139 void elementReplyTo(const FullMsgId &to) override; 140 void elementStartInteraction( 141 not_null<const HistoryView::Element*> view) override; 142 143 ~InnerWidget(); 144 145 protected: 146 void visibleTopBottomUpdated( 147 int visibleTop, 148 int visibleBottom) override; 149 150 void paintEvent(QPaintEvent *e) override; 151 void keyPressEvent(QKeyEvent *e) override; 152 void mousePressEvent(QMouseEvent *e) override; 153 void mouseMoveEvent(QMouseEvent *e) override; 154 void mouseReleaseEvent(QMouseEvent *e) override; 155 void mouseDoubleClickEvent(QMouseEvent *e) override; 156 void enterEventHook(QEnterEvent *e) override; 157 void leaveEventHook(QEvent *e) override; 158 void contextMenuEvent(QContextMenuEvent *e) override; 159 160 // Resizes content and counts natural widget height for the desired width. 161 int resizeGetHeight(int newWidth) override; 162 163 private: 164 using Element = HistoryView::Element; 165 enum class Direction { 166 Up, 167 Down, 168 }; 169 enum class MouseAction { 170 None, 171 PrepareDrag, 172 Dragging, 173 Selecting, 174 }; 175 enum class EnumItemsDirection { 176 TopToBottom, 177 BottomToTop, 178 }; 179 using TextState = HistoryView::TextState; 180 using CursorState = HistoryView::CursorState; 181 using PointState = HistoryView::PointState; 182 using StateRequest = HistoryView::StateRequest; 183 184 void mouseActionStart(const QPoint &screenPos, Qt::MouseButton button); 185 void mouseActionUpdate(const QPoint &screenPos); 186 void mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button); 187 void mouseActionCancel(); 188 void updateSelected(); 189 void performDrag(); 190 int itemTop(not_null<const Element*> view) const; 191 void repaintItem(const Element *view); 192 void refreshItem(not_null<const Element*> view); 193 void resizeItem(not_null<Element*> view); 194 QPoint mapPointToItem(QPoint point, const Element *view) const; 195 196 void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false); 197 void savePhotoToFile(not_null<PhotoData*> photo); 198 void saveDocumentToFile(not_null<DocumentData*> document); 199 void copyContextImage(not_null<PhotoData*> photo); 200 void showStickerPackInfo(not_null<DocumentData*> document); 201 void cancelContextDownload(not_null<DocumentData*> document); 202 void showContextInFolder(not_null<DocumentData*> document); 203 void openContextGif(FullMsgId itemId); 204 void copyContextText(FullMsgId itemId); 205 void copySelectedText(); 206 TextForMimeData getSelectedText() const; 207 void suggestRestrictUser(not_null<UserData*> user); 208 void restrictUser(not_null<UserData*> user, ChatRestrictionsInfo oldRights, ChatRestrictionsInfo newRights); 209 void restrictUserDone(not_null<UserData*> user, ChatRestrictionsInfo rights); 210 211 void requestAdmins(); 212 void checkPreloadMore(); 213 void updateVisibleTopItem(); 214 void preloadMore(Direction direction); 215 void itemsAdded(Direction direction, int addedCount); 216 void updateSize(); 217 void updateMinMaxIds(); 218 void updateEmptyText(); 219 void paintEmpty(Painter &p, not_null<const Ui::ChatStyle*> st); 220 void clearAfterFilterChange(); 221 void clearAndRequestLog(); 222 void addEvents(Direction direction, const QVector<MTPChannelAdminLogEvent> &events); 223 Element *viewForItem(const HistoryItem *item); 224 225 void toggleScrollDateShown(); 226 void repaintScrollDateCallback(); 227 bool displayScrollDate() const; 228 void scrollDateHide(); 229 void scrollDateCheck(); 230 void scrollDateHideByTimer(); 231 232 // This function finds all history items that are displayed and calls template method 233 // for each found message (in given direction) in the passed history with passed top offset. 234 // 235 // Method has "bool (*Method)(not_null<Element*> view, int itemtop, int itembottom)" signature 236 // if it returns false the enumeration stops immidiately. 237 template <EnumItemsDirection direction, typename Method> 238 void enumerateItems(Method method); 239 240 // This function finds all userpics on the left that are displayed and calls template method 241 // for each found userpic (from the top to the bottom) using enumerateItems() method. 242 // 243 // Method has "bool (*Method)(not_null<Element*> view, int userpicTop)" signature 244 // if it returns false the enumeration stops immediately. 245 template <typename Method> 246 void enumerateUserpics(Method method); 247 248 // This function finds all date elements that are displayed and calls template method 249 // for each found date element (from the bottom to the top) using enumerateItems() method. 250 // 251 // Method has "bool (*Method)(not_null<HistoryItem*> item, int itemtop, int dateTop)" signature 252 // if it returns false the enumeration stops immediately. 253 template <typename Method> 254 void enumerateDates(Method method); 255 256 const not_null<Window::SessionController*> _controller; 257 const not_null<ChannelData*> _channel; 258 const not_null<History*> _history; 259 MTP::Sender _api; 260 261 const std::unique_ptr<Ui::PathShiftGradient> _pathGradient; 262 std::shared_ptr<Ui::ChatTheme> _theme; 263 264 std::vector<OwnedItem> _items; 265 std::set<uint64> _eventIds; 266 std::map<not_null<const HistoryItem*>, not_null<Element*>> _itemsByData; 267 base::flat_map<not_null<const HistoryItem*>, TimeId> _itemDates; 268 base::flat_set<FullMsgId> _animatedStickersPlayed; 269 base::flat_map< 270 not_null<PeerData*>, 271 std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache; 272 int _itemsTop = 0; 273 int _itemsWidth = 0; 274 int _itemsHeight = 0; 275 276 int _minHeight = 0; 277 int _visibleTop = 0; 278 int _visibleBottom = 0; 279 Element *_visibleTopItem = nullptr; 280 int _visibleTopFromItem = 0; 281 282 bool _scrollDateShown = false; 283 Ui::Animations::Simple _scrollDateOpacity; 284 SingleQueuedInvokation _scrollDateCheck; 285 base::Timer _scrollDateHideTimer; 286 Element *_scrollDateLastItem = nullptr; 287 int _scrollDateLastItemTop = 0; 288 289 // Up - max, Down - min. 290 uint64 _maxId = 0; 291 uint64 _minId = 0; 292 mtpRequestId _preloadUpRequestId = 0; 293 mtpRequestId _preloadDownRequestId = 0; 294 295 // Don't load anything until the memento was read. 296 bool _upLoaded = true; 297 bool _downLoaded = true; 298 bool _filterChanged = false; 299 Ui::Text::String _emptyText; 300 301 MouseAction _mouseAction = MouseAction::None; 302 TextSelectType _mouseSelectType = TextSelectType::Letters; 303 QPoint _dragStartPosition; 304 QPoint _mousePosition; 305 Element *_mouseActionItem = nullptr; 306 CursorState _mouseCursorState = CursorState(); 307 uint16 _mouseTextSymbol = 0; 308 bool _pressWasInactive = false; 309 310 Element *_selectedItem = nullptr; 311 TextSelection _selectedText; 312 bool _wasSelectedText = false; // was some text selected in current drag action 313 Qt::CursorShape _cursor = style::cur_default; 314 315 base::unique_qptr<Ui::PopupMenu> _menu; 316 317 QPoint _trippleClickPoint; 318 base::Timer _trippleClickTimer; 319 320 FilterValue _filter; 321 QString _searchQuery; 322 std::vector<not_null<UserData*>> _admins; 323 std::vector<not_null<UserData*>> _adminsCanEdit; 324 Fn<void(FilterValue &&filter)> _showFilterCallback; 325 326 rpl::event_stream<> _showSearchSignal; 327 rpl::event_stream<int> _scrollToSignal; 328 rpl::event_stream<> _cancelSignal; 329 330 }; 331 332 } // namespace AdminLog 333