pin_messages_box.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 "boxes/pin_messages_box.h"
  8. #include "apiwrap.h"
  9. #include "data/data_chat.h"
  10. #include "data/data_user.h"
  11. #include "lang/lang_keys.h"
  12. #include "history/history.h"
  13. #include "history/history_item.h"
  14. #include "main/main_session.h"
  15. #include "ui/boxes/confirm_box.h"
  16. #include "ui/widgets/checkbox.h"
  17. #include "styles/style_layers.h"
  18. #include "styles/style_boxes.h"
  19. namespace {
  20. [[nodiscard]] bool IsOldForPin(
  21. MsgId id,
  22. not_null<PeerData*> peer,
  23. MsgId topicRootId) {
  24. const auto normal = peer->migrateToOrMe();
  25. const auto migrated = normal->migrateFrom();
  26. const auto top = Data::ResolveTopPinnedId(normal, topicRootId, migrated);
  27. if (!top) {
  28. return false;
  29. } else if (peer == migrated) {
  30. return peerIsChannel(top.peer) || (id < top.msg);
  31. } else if (migrated) {
  32. return peerIsChannel(top.peer) && (id < top.msg);
  33. } else {
  34. return (id < top.msg);
  35. }
  36. }
  37. } // namespace
  38. void PinMessageBox(
  39. not_null<Ui::GenericBox*> box,
  40. not_null<HistoryItem*> item) {
  41. struct State {
  42. QPointer<Ui::Checkbox> pinForPeer;
  43. QPointer<Ui::Checkbox> notify;
  44. mtpRequestId requestId = 0;
  45. };
  46. const auto peer = item->history()->peer;
  47. const auto msgId = item->id;
  48. const auto topicRootId = item->topic() ? item->topicRootId() : MsgId();
  49. const auto pinningOld = IsOldForPin(msgId, peer, topicRootId);
  50. const auto state = box->lifetime().make_state<State>();
  51. const auto api = box->lifetime().make_state<MTP::Sender>(
  52. &peer->session().mtp());
  53. auto checkbox = [&]() -> object_ptr<Ui::Checkbox> {
  54. if (peer->isUser() && !peer->isSelf()) {
  55. auto object = object_ptr<Ui::Checkbox>(
  56. box,
  57. tr::lng_pinned_also_for_other(
  58. tr::now,
  59. lt_user,
  60. peer->shortName()),
  61. false,
  62. st::urlAuthCheckbox);
  63. object->setAllowTextLines();
  64. state->pinForPeer = Ui::MakeWeak(object.data());
  65. return object;
  66. } else if (!pinningOld && (peer->isChat() || peer->isMegagroup())) {
  67. auto object = object_ptr<Ui::Checkbox>(
  68. box,
  69. tr::lng_pinned_notify(tr::now),
  70. true,
  71. st::urlAuthCheckbox);
  72. object->setAllowTextLines();
  73. state->notify = Ui::MakeWeak(object.data());
  74. return object;
  75. }
  76. return { nullptr };
  77. }();
  78. auto pinMessage = [=] {
  79. if (state->requestId) {
  80. return;
  81. }
  82. auto flags = MTPmessages_UpdatePinnedMessage::Flags(0);
  83. if (state->notify && !state->notify->checked()) {
  84. flags |= MTPmessages_UpdatePinnedMessage::Flag::f_silent;
  85. }
  86. if (state->pinForPeer && !state->pinForPeer->checked()) {
  87. flags |= MTPmessages_UpdatePinnedMessage::Flag::f_pm_oneside;
  88. }
  89. state->requestId = api->request(MTPmessages_UpdatePinnedMessage(
  90. MTP_flags(flags),
  91. peer->input,
  92. MTP_int(msgId)
  93. )).done([=](const MTPUpdates &result) {
  94. peer->session().api().applyUpdates(result);
  95. box->closeBox();
  96. }).fail([=] {
  97. box->closeBox();
  98. }).send();
  99. };
  100. Ui::ConfirmBox(box, {
  101. .text = (pinningOld
  102. ? tr::lng_pinned_pin_old_sure()
  103. : (peer->isChat() || peer->isMegagroup())
  104. ? tr::lng_pinned_pin_sure_group()
  105. : tr::lng_pinned_pin_sure()),
  106. .confirmed = std::move(pinMessage),
  107. .confirmText = tr::lng_pinned_pin(),
  108. });
  109. if (checkbox) {
  110. auto padding = st::boxPadding;
  111. padding.setTop(padding.bottom());
  112. box->addRow(std::move(checkbox), std::move(padding));
  113. }
  114. }