report_box_graphics.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 "ui/boxes/report_box_graphics.h"
  8. #include "info/profile/info_profile_icon.h"
  9. #include "lang/lang_keys.h"
  10. #include "lottie/lottie_icon.h"
  11. #include "settings/settings_common.h"
  12. #include "ui/layers/generic_box.h"
  13. #include "ui/painter.h"
  14. #include "ui/rect.h"
  15. #include "ui/vertical_list.h"
  16. #include "ui/toast/toast.h"
  17. #include "ui/widgets/buttons.h"
  18. #include "ui/widgets/fields/input_field.h"
  19. #include "ui/wrap/vertical_layout.h"
  20. #include "styles/style_chat_helpers.h"
  21. #include "styles/style_layers.h"
  22. #include "styles/style_info.h"
  23. #include "styles/style_channel_earn.h"
  24. #include "styles/style_settings.h"
  25. namespace Ui {
  26. namespace {
  27. constexpr auto kReportReasonLengthMax = 512;
  28. using Source = ReportSource;
  29. using Reason = ReportReason;
  30. } // namespace
  31. void ReportReasonBox(
  32. not_null<GenericBox*> box,
  33. const style::ReportBox &st,
  34. ReportSource source,
  35. Fn<void(Reason)> done) {
  36. box->setTitle([&] {
  37. switch (source) {
  38. case Source::Message: return tr::lng_report_message_title();
  39. case Source::Channel: return tr::lng_report_title();
  40. case Source::Group: return tr::lng_report_group_title();
  41. case Source::Bot: return tr::lng_report_bot_title();
  42. case Source::ProfilePhoto:
  43. return tr::lng_report_profile_photo_title();
  44. case Source::ProfileVideo:
  45. return tr::lng_report_profile_video_title();
  46. case Source::GroupPhoto: return tr::lng_report_group_photo_title();
  47. case Source::GroupVideo: return tr::lng_report_group_video_title();
  48. case Source::ChannelPhoto:
  49. return tr::lng_report_channel_photo_title();
  50. case Source::ChannelVideo:
  51. return tr::lng_report_channel_video_title();
  52. case Source::Story:
  53. return tr::lng_report_story();
  54. }
  55. Unexpected("'source' in ReportReasonBox.");
  56. }());
  57. auto margin = style::margins{ 0, st::reportReasonTopSkip, 0, 0 };
  58. const auto add = [&](
  59. Reason reason,
  60. tr::phrase<> text,
  61. const style::icon &icon) {
  62. const auto layout = box->verticalLayout();
  63. const auto button = layout->add(
  64. object_ptr<Ui::SettingsButton>(layout.get(), text(), st.button),
  65. margin);
  66. margin = {};
  67. button->setClickedCallback([=] {
  68. done(reason);
  69. });
  70. const auto height = st.button.padding.top()
  71. + st.button.height
  72. + st.button.padding.bottom();
  73. object_ptr<Info::Profile::FloatingIcon>(
  74. button,
  75. icon,
  76. QPoint{
  77. st::infoSharedMediaButtonIconPosition.x(),
  78. (height - icon.height()) / 2,
  79. });
  80. };
  81. add(Reason::Spam, tr::lng_report_reason_spam, st.spam);
  82. if (source == Source::Channel
  83. || source == Source::Group
  84. || source == Source::Bot) {
  85. add(Reason::Fake, tr::lng_report_reason_fake, st.fake);
  86. }
  87. add(
  88. Reason::Violence,
  89. tr::lng_report_reason_violence,
  90. st.violence);
  91. add(
  92. Reason::ChildAbuse,
  93. tr::lng_report_reason_child_abuse,
  94. st.children);
  95. add(
  96. Reason::Pornography,
  97. tr::lng_report_reason_pornography,
  98. st.pornography);
  99. add(
  100. Reason::Copyright,
  101. tr::lng_report_reason_copyright,
  102. st.copyright);
  103. if (source == Source::Message || source == Source::Story) {
  104. add(
  105. Reason::IllegalDrugs,
  106. tr::lng_report_reason_illegal_drugs,
  107. st.drugs);
  108. add(
  109. Reason::PersonalDetails,
  110. tr::lng_report_reason_personal_details,
  111. st.personal);
  112. }
  113. add(Reason::Other, tr::lng_report_reason_other, st.other);
  114. box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
  115. }
  116. void ReportDetailsBox(
  117. not_null<GenericBox*> box,
  118. const style::ReportBox &st,
  119. Fn<void(QString)> done) {
  120. box->setTitle(tr::lng_profile_report());
  121. AddReportDetailsIconButton(box);
  122. Ui::AddSkip(
  123. box->verticalLayout(),
  124. st::settingsBlockedListIconPadding.bottom());
  125. box->addRow(
  126. object_ptr<FlatLabel>(
  127. box, // #TODO reports
  128. tr::lng_report_details_about(),
  129. st.label),
  130. {
  131. st::boxRowPadding.left(),
  132. st::boxPadding.top(),
  133. st::boxRowPadding.right(),
  134. st::boxPadding.bottom(),
  135. });
  136. const auto details = box->addRow(
  137. object_ptr<InputField>(
  138. box,
  139. st.field,
  140. InputField::Mode::MultiLine,
  141. tr::lng_report_details(),
  142. QString()));
  143. details->setMaxLength(kReportReasonLengthMax);
  144. box->setFocusCallback([=] {
  145. details->setFocusFast();
  146. });
  147. const auto submit = [=] {
  148. const auto text = details->getLastText();
  149. done(text);
  150. };
  151. details->submits() | rpl::start_with_next(submit, details->lifetime());
  152. box->addButton(tr::lng_report_button(), submit);
  153. box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
  154. }
  155. not_null<Ui::AbstractButton*> AddReportOptionButton(
  156. not_null<Ui::VerticalLayout*> container,
  157. const QString &text,
  158. const style::ReportBox *stOverride) {
  159. const auto button = container->add(
  160. object_ptr<Ui::SettingsButton>(
  161. container,
  162. rpl::single(QString()),
  163. (stOverride ? stOverride : &st::defaultReportBox)->noIconButton));
  164. const auto textFg = (stOverride
  165. ? stOverride->label
  166. : st::sponsoredReportLabel).textFg->c;
  167. const auto label = Ui::CreateChild<Ui::FlatLabel>(
  168. button,
  169. rpl::single(text),
  170. st::sponsoredReportLabel);
  171. label->setTextColorOverride(textFg);
  172. const auto icon = Ui::CreateChild<Ui::RpWidget>(button);
  173. icon->resize(st::settingsPremiumArrow.size());
  174. icon->paintRequest() | rpl::start_with_next([=, w = icon->width()] {
  175. auto p = Painter(icon);
  176. st::settingsPremiumArrow.paint(p, 0, 0, w, textFg);
  177. }, icon->lifetime());
  178. button->sizeValue() | rpl::start_with_next([=](const QSize &size) {
  179. const auto left = button->st().padding.left();
  180. const auto right = button->st().padding.right();
  181. icon->moveToRight(right, (size.height() - icon->height()) / 2);
  182. label->resizeToWidth(size.width()
  183. - icon->width()
  184. - left
  185. - st::settingsButtonRightSkip
  186. - right);
  187. label->moveToLeft(left, (size.height() - label->height()) / 2);
  188. button->resize(
  189. button->width(),
  190. rect::m::sum::v(button->st().padding) + label->height());
  191. }, button->lifetime());
  192. label->setAttribute(Qt::WA_TransparentForMouseEvents);
  193. icon->setAttribute(Qt::WA_TransparentForMouseEvents);
  194. return button;
  195. }
  196. void AddReportDetailsIconButton(not_null<GenericBox*> box) {
  197. auto icon = Settings::CreateLottieIcon(
  198. box->verticalLayout(),
  199. {
  200. .name = u"blocked_peers_empty"_q,
  201. .sizeOverride = Size(st::changePhoneIconSize),
  202. },
  203. {});
  204. box->setShowFinishedCallback([animate = std::move(icon.animate)] {
  205. animate(anim::repeat::once);
  206. });
  207. box->addRow(std::move(icon.widget));
  208. }
  209. } // namespace Ui