info_profile_phone_menu.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. #include "info/profile/info_profile_phone_menu.h"
  8. #include "data/data_user.h"
  9. #include "lang/lang_keys.h"
  10. #include "main/main_app_config.h"
  11. #include "main/main_app_config_values.h"
  12. #include "main/main_session.h"
  13. #include "ui/text/text_utilities.h"
  14. #include "ui/widgets/labels.h"
  15. #include "ui/widgets/menu/menu_action.h"
  16. #include "ui/widgets/popup_menu.h"
  17. #include "styles/style_chat.h" // expandedMenuSeparator.
  18. #include "styles/style_chat_helpers.h"
  19. namespace Info {
  20. namespace Profile {
  21. namespace {
  22. class TextItem final : public Ui::Menu::ItemBase {
  23. public:
  24. TextItem(
  25. not_null<Ui::RpWidget*> parent,
  26. const style::Menu &st,
  27. rpl::producer<TextWithEntities> &&text);
  28. not_null<QAction*> action() const override;
  29. bool isEnabled() const override;
  30. protected:
  31. int contentHeight() const override;
  32. private:
  33. const base::unique_qptr<Ui::FlatLabel> _label;
  34. const not_null<QAction*> _dummyAction;
  35. };
  36. [[nodiscard]] int CountMinWidthForHeight(
  37. not_null<Ui::FlatLabel*> label,
  38. int basicWidth,
  39. int heightLimit) {
  40. const auto height = [&](int width) {
  41. label->resizeToWidth(width);
  42. return label->height();
  43. };
  44. auto widthMin = basicWidth;
  45. auto widthMax = label->textMaxWidth();
  46. if (height(widthMin) <= heightLimit || height(widthMax) > heightLimit) {
  47. return basicWidth;
  48. }
  49. while (widthMin + 1 < widthMax) {
  50. const auto middle = (widthMin + widthMax) / 2;
  51. if (height(middle) > heightLimit) {
  52. widthMin = middle;
  53. } else {
  54. widthMax = middle;
  55. }
  56. }
  57. return widthMax;
  58. }
  59. TextItem::TextItem(
  60. not_null<Ui::RpWidget*> parent,
  61. const style::Menu &st,
  62. rpl::producer<TextWithEntities> &&text)
  63. : ItemBase(parent, st)
  64. , _label(base::make_unique_q<Ui::FlatLabel>(
  65. this,
  66. std::move(text),
  67. st::historyMessagesTTLLabel))
  68. , _dummyAction(Ui::CreateChild<QAction>(parent.get())) {
  69. // Try to fit the phrase in two lines.
  70. const auto limit = st::historyMessagesTTLLabel.style.font->height * 2;
  71. const auto min1 = st::historyMessagesTTLLabel.minWidth;
  72. const auto min2 = CountMinWidthForHeight(_label.get(), min1, limit);
  73. const auto added = st.itemPadding.left() + st.itemPadding.right();
  74. setMinWidth(std::max(min1, min2) + added);
  75. sizeValue(
  76. ) | rpl::start_with_next([=](const QSize &s) {
  77. if (s.width() <= added) {
  78. return;
  79. }
  80. _label->resizeToWidth(s.width() - added);
  81. _label->moveToLeft(
  82. st.itemPadding.left(),
  83. (s.height() - _label->height()) / 2);
  84. }, lifetime());
  85. _label->resizeToWidth(parent->width() - added);
  86. initResizeHook(parent->sizeValue());
  87. }
  88. not_null<QAction*> TextItem::action() const {
  89. return _dummyAction;
  90. }
  91. bool TextItem::isEnabled() const {
  92. return false;
  93. }
  94. int TextItem::contentHeight() const {
  95. return _label->height();
  96. }
  97. } // namespace
  98. bool IsCollectiblePhone(not_null<UserData*> user) {
  99. using Strings = std::vector<QString>;
  100. const auto prefixes = user->session().appConfig().get<Strings>(
  101. u"fragment_prefixes"_q,
  102. Strings{ u"888"_q });
  103. const auto phone = user->phone();
  104. const auto proj = [&](const QString &p) {
  105. return phone.startsWith(p);
  106. };
  107. return ranges::any_of(prefixes, proj);
  108. }
  109. void AddPhoneMenu(not_null<Ui::PopupMenu*> menu, not_null<UserData*> user) {
  110. if (user->isSelf() || !IsCollectiblePhone(user)) {
  111. return;
  112. } else if (const auto url = AppConfig::FragmentLink(&user->session())) {
  113. menu->addSeparator(&st::expandedMenuSeparator);
  114. const auto link = Ui::Text::Link(
  115. tr::lng_info_mobile_context_menu_fragment_about_link(tr::now),
  116. *url);
  117. menu->addAction(base::make_unique_q<TextItem>(
  118. menu->menu(),
  119. st::reactionMenu.menu,
  120. tr::lng_info_mobile_context_menu_fragment_about(
  121. lt_link,
  122. rpl::single(link),
  123. Ui::Text::RichLangValue)));
  124. }
  125. }
  126. } // namespace Profile
  127. } // namespace Info