userpic_button.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "ui/widgets/buttons.h"
  9. #include "ui/userpic_view.h"
  10. class PeerData;
  11. namespace Data {
  12. class PhotoMedia;
  13. } // namespace Data
  14. namespace Window {
  15. class Controller;
  16. class SessionController;
  17. } // namespace Window
  18. namespace Media {
  19. namespace Streaming {
  20. class Instance;
  21. struct Update;
  22. enum class Error;
  23. struct Information;
  24. } // namespace Streaming
  25. } // namespace Media
  26. namespace style {
  27. struct UserpicButton;
  28. } // namespace style
  29. namespace Ui::Menu {
  30. class ItemBase;
  31. } // namespace Ui::Menu
  32. namespace Ui {
  33. class PopupMenu;
  34. class UserpicButton final : public RippleButton {
  35. public:
  36. enum class Role {
  37. ChoosePhoto,
  38. ChangePhoto,
  39. OpenPhoto,
  40. Custom,
  41. };
  42. enum class Source {
  43. PeerPhoto,
  44. NonPersonalPhoto,
  45. NonPersonalIfHasPersonal,
  46. Custom,
  47. };
  48. UserpicButton(
  49. QWidget *parent,
  50. not_null<::Window::Controller*> window,
  51. Role role,
  52. const style::UserpicButton &st,
  53. bool forceForumShape = false);
  54. UserpicButton(
  55. QWidget *parent,
  56. not_null<::Window::SessionController*> controller,
  57. not_null<PeerData*> peer,
  58. Role role,
  59. Source source,
  60. const style::UserpicButton &st);
  61. UserpicButton(
  62. QWidget *parent,
  63. not_null<PeerData*> peer, // Role::Custom, Source::PeerPhoto
  64. const style::UserpicButton &st);
  65. ~UserpicButton();
  66. enum class ChosenType {
  67. Set,
  68. Suggest,
  69. };
  70. struct ChosenImage {
  71. QImage image;
  72. ChosenType type = ChosenType::Set;
  73. struct {
  74. DocumentId documentId = 0;
  75. std::vector<QColor> colors;
  76. } markup;
  77. };
  78. // Role::OpenPhoto
  79. void switchChangePhotoOverlay(
  80. bool enabled,
  81. Fn<void(ChosenImage)> chosen);
  82. void showSavedMessagesOnSelf(bool enabled);
  83. void forceForumShape(bool force);
  84. // Role::ChoosePhoto or Role::ChangePhoto
  85. [[nodiscard]] rpl::producer<ChosenImage> chosenImages() const {
  86. return _chosenImages.events();
  87. }
  88. [[nodiscard]] QImage takeResultImage() {
  89. return std::move(_result);
  90. }
  91. void showCustom(QImage &&image);
  92. void showSource(Source source);
  93. void showCustomOnChosen();
  94. void overrideHasPersonalPhoto(bool has);
  95. [[nodiscard]] rpl::producer<> resetPersonalRequests() const;
  96. protected:
  97. void paintEvent(QPaintEvent *e) override;
  98. void mouseMoveEvent(QMouseEvent *e) override;
  99. void leaveEventHook(QEvent *e) override;
  100. void onStateChanged(State was, StateChangeSource source) override;
  101. QImage prepareRippleMask() const override;
  102. QPoint prepareRippleStartPosition() const override;
  103. private:
  104. void prepare();
  105. void setupPeerViewers();
  106. void startAnimation();
  107. void processPeerPhoto();
  108. void processNewPeerPhoto();
  109. void startNewPhotoShowing();
  110. void prepareUserpicPixmap();
  111. void fillShape(QPainter &p, const style::color &color) const;
  112. [[nodiscard]] QPoint countPhotoPosition() const;
  113. void startChangeOverlayAnimation();
  114. void updateCursorInChangeOverlay(QPoint localPos);
  115. void setCursorInChangeOverlay(bool inOverlay);
  116. void updateCursor();
  117. void updateVideo();
  118. [[nodiscard]] bool showSavedMessages() const;
  119. [[nodiscard]] bool showRepliesMessages() const;
  120. void checkStreamedIsStarted();
  121. bool createStreamingObjects(not_null<PhotoData*> photo);
  122. void clearStreaming();
  123. void handleStreamingUpdate(Media::Streaming::Update &&update);
  124. void handleStreamingError(Media::Streaming::Error &&error);
  125. void streamingReady(Media::Streaming::Information &&info);
  126. void paintUserpicFrame(Painter &p, QPoint photoPosition);
  127. [[nodiscard]] bool useForumShape() const;
  128. void grabOldUserpic();
  129. void setClickHandlerByRole();
  130. void requestSuggestAvailability();
  131. void openPeerPhoto();
  132. void choosePhotoLocally();
  133. [[nodiscard]] bool canSuggestPhoto(not_null<UserData*> user) const;
  134. [[nodiscard]] bool hasPersonalPhotoLocally() const;
  135. [[nodiscard]] auto makeResetToOriginalAction()
  136. -> base::unique_qptr<Menu::ItemBase>;
  137. const style::UserpicButton &_st;
  138. ::Window::SessionController *_controller = nullptr;
  139. ::Window::Controller *_window = nullptr;
  140. PeerData *_peer = nullptr;
  141. bool _forceForumShape = false;
  142. PeerUserpicView _userpicView;
  143. std::shared_ptr<Data::PhotoMedia> _nonPersonalView;
  144. Role _role = Role::ChangePhoto;
  145. bool _notShownYet = true;
  146. bool _waiting = false;
  147. QPixmap _userpic, _oldUserpic;
  148. bool _userpicHasImage = false;
  149. bool _showPeerUserpic = false;
  150. InMemoryKey _userpicUniqueKey;
  151. Animations::Simple _a_appearance;
  152. QImage _result;
  153. QImage _ellipseMask;
  154. std::array<QImage, 4> _roundingCorners;
  155. std::unique_ptr<Media::Streaming::Instance> _streamed;
  156. PhotoData *_streamedPhoto = nullptr;
  157. base::unique_qptr<PopupMenu> _menu;
  158. bool _showSavedMessagesOnSelf = false;
  159. bool _canOpenPhoto = false;
  160. bool _cursorInChangeOverlay = false;
  161. bool _changeOverlayEnabled = false;
  162. Animations::Simple _changeOverlayShown;
  163. rpl::event_stream<ChosenImage> _chosenImages;
  164. Source _source = Source::Custom;
  165. std::optional<bool> _overrideHasPersonalPhoto;
  166. rpl::event_stream<> _resetPersonalRequests;
  167. rpl::lifetime _sourceLifetime;
  168. };
  169. [[nodiscard]] not_null<Ui::UserpicButton*> CreateUploadSubButton(
  170. not_null<Ui::RpWidget*> parent,
  171. not_null<Window::SessionController*> controller);
  172. [[nodiscard]] not_null<Ui::UserpicButton*> CreateUploadSubButton(
  173. not_null<Ui::RpWidget*> parent,
  174. not_null<UserData*> contact,
  175. not_null<Window::SessionController*> controller);
  176. } // namespace Ui