| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "ui/chat/choose_send_as.h"
- #include "boxes/peer_list_box.h"
- #include "data/data_peer.h"
- #include "data/data_channel.h"
- #include "data/data_peer_values.h"
- #include "history/history.h"
- #include "ui/controls/send_as_button.h"
- #include "ui/text/text_utilities.h"
- #include "ui/painter.h"
- #include "window/window_session_controller.h"
- #include "main/main_session.h"
- #include "main/session/send_as_peers.h"
- #include "lang/lang_keys.h"
- #include "settings/settings_premium.h"
- #include "styles/style_calls.h"
- #include "styles/style_boxes.h"
- #include "styles/style_chat.h"
- #include "styles/style_chat_helpers.h"
- namespace Ui {
- namespace {
- class Row final : public PeerListRow {
- public:
- explicit Row(const Main::SendAsPeer &sendAsPeer);
- int paintNameIconGetWidth(
- Painter &p,
- Fn<void()> repaint,
- crl::time now,
- int nameLeft,
- int nameTop,
- int nameWidth,
- int availableWidth,
- int outerWidth,
- bool selected) override;
- private:
- bool _premiumRequired = false;
- };
- class ListController final : public PeerListController {
- public:
- ListController(
- std::vector<Main::SendAsPeer> list,
- not_null<PeerData*> selected);
- Main::Session &session() const override;
- void prepare() override;
- void rowClicked(not_null<PeerListRow*> row) override;
- [[nodiscard]] rpl::producer<not_null<PeerData*>> clicked() const;
- private:
- std::unique_ptr<Row> createRow(const Main::SendAsPeer &sendAsPeer);
- std::vector<Main::SendAsPeer> _list;
- not_null<PeerData*> _selected;
- rpl::event_stream<not_null<PeerData*>> _clicked;
- };
- Row::Row(const Main::SendAsPeer &sendAsPeer)
- : PeerListRow(sendAsPeer.peer)
- , _premiumRequired(sendAsPeer.premiumRequired) {
- }
- int Row::paintNameIconGetWidth(
- Painter &p,
- Fn<void()> repaint,
- crl::time now,
- int nameLeft,
- int nameTop,
- int nameWidth,
- int availableWidth,
- int outerWidth,
- bool selected) {
- if (_premiumRequired && !peer()->session().premium()) {
- const auto &icon = st::emojiPremiumRequired;
- availableWidth -= icon.width();
- const auto x = nameLeft + std::min(nameWidth, availableWidth);
- icon.paint(p, x, nameTop, outerWidth);
- return icon.width();
- }
- return PeerListRow::paintNameIconGetWidth(
- p,
- std::move(repaint),
- now,
- nameLeft,
- nameTop,
- nameWidth,
- availableWidth,
- outerWidth,
- selected);
- }
- ListController::ListController(
- std::vector<Main::SendAsPeer> list,
- not_null<PeerData*> selected)
- : PeerListController()
- , _list(std::move(list))
- , _selected(selected) {
- Data::AmPremiumValue(
- &selected->session()
- ) | rpl::skip(1) | rpl::start_with_next([=] {
- const auto count = delegate()->peerListFullRowsCount();
- for (auto i = 0; i != count; ++i) {
- delegate()->peerListUpdateRow(
- delegate()->peerListRowAt(i));
- }
- }, lifetime());
- }
- Main::Session &ListController::session() const {
- return _selected->session();
- }
- std::unique_ptr<Row> ListController::createRow(
- const Main::SendAsPeer &sendAsPeer) {
- auto result = std::make_unique<Row>(sendAsPeer);
- if (sendAsPeer.peer->isSelf()) {
- result->setCustomStatus(
- tr::lng_group_call_join_as_personal(tr::now));
- } else if (sendAsPeer.peer->isMegagroup()) {
- result->setCustomStatus(tr::lng_send_as_anonymous_admin(tr::now));
- } else if (const auto channel = sendAsPeer.peer->asChannel()) {
- result->setCustomStatus(tr::lng_chat_status_subscribers(
- tr::now,
- lt_count,
- channel->membersCount()));
- }
- return result;
- }
- void ListController::prepare() {
- delegate()->peerListSetSearchMode(PeerListSearchMode::Disabled);
- for (const auto &sendAsPeer : _list) {
- auto row = createRow(sendAsPeer);
- const auto raw = row.get();
- delegate()->peerListAppendRow(std::move(row));
- if (sendAsPeer.peer == _selected) {
- delegate()->peerListSetRowChecked(raw, true);
- raw->finishCheckedAnimation();
- }
- }
- delegate()->peerListRefreshRows();
- }
- void ListController::rowClicked(not_null<PeerListRow*> row) {
- const auto peer = row->peer();
- if (peer == _selected) {
- return;
- }
- _clicked.fire_copy(peer);
- }
- rpl::producer<not_null<PeerData*>> ListController::clicked() const {
- return _clicked.events();
- }
- } // namespace
- void ChooseSendAsBox(
- not_null<GenericBox*> box,
- std::vector<Main::SendAsPeer> list,
- not_null<PeerData*> chosen,
- Fn<bool(not_null<PeerData*>)> done) {
- Expects(ranges::contains(list, chosen, &Main::SendAsPeer::peer));
- Expects(done != nullptr);
- box->setWidth(st::groupCallJoinAsWidth);
- box->setTitle(tr::lng_send_as_title());
- const auto &labelSt = st::confirmPhoneAboutLabel;
- box->addRow(object_ptr<Ui::FlatLabel>(
- box,
- tr::lng_group_call_join_as_about(),
- labelSt));
- auto &lifetime = box->lifetime();
- const auto delegate = lifetime.make_state<
- PeerListContentDelegateSimple
- >();
- const auto controller = lifetime.make_state<ListController>(
- list,
- chosen);
- controller->setStyleOverrides(
- &st::peerListJoinAsList,
- nullptr);
- controller->clicked(
- ) | rpl::start_with_next([=](not_null<PeerData*> peer) {
- const auto weak = MakeWeak(box);
- if (done(peer) && weak) {
- box->closeBox();
- }
- }, box->lifetime());
- const auto content = box->addRow(
- object_ptr<PeerListContent>(box, controller),
- style::margins());
- delegate->setContent(content);
- controller->setDelegate(delegate);
- box->addButton(tr::lng_box_done(), [=] { box->closeBox(); });
- }
- void SetupSendAsButton(
- not_null<SendAsButton*> button,
- rpl::producer<PeerData*> active,
- not_null<Window::SessionController*> window) {
- using namespace rpl::mappers;
- const auto current = button->lifetime().make_state<
- rpl::variable<PeerData*>
- >(std::move(active));
- button->setClickedCallback([=] {
- const auto peer = current->current();
- if (!peer) {
- return;
- }
- const auto session = &peer->session();
- const auto &list = session->sendAsPeers().list(peer);
- if (list.size() < 2) {
- return;
- }
- const auto done = [=](not_null<PeerData*> sendAs) {
- const auto i = ranges::find(
- list,
- sendAs,
- &Main::SendAsPeer::peer);
- if (i != end(list)
- && i->premiumRequired
- && !sendAs->session().premium()) {
- Settings::ShowPremiumPromoToast(
- window->uiShow(),
- tr::lng_send_as_premium_required(
- tr::now,
- lt_link,
- Ui::Text::Link(
- Ui::Text::Bold(
- tr::lng_send_as_premium_required_link(
- tr::now))),
- Ui::Text::WithEntities),
- u"send_as"_q);
- return false;
- }
- session->sendAsPeers().saveChosen(peer, sendAs);
- return true;
- };
- window->show(Box(
- Ui::ChooseSendAsBox,
- list,
- session->sendAsPeers().resolveChosen(peer),
- done));
- });
- auto userpic = current->value(
- ) | rpl::filter([=](PeerData *peer) {
- return peer && peer->isChannel();
- }) | rpl::map([=](not_null<PeerData*> peer) {
- const auto channel = peer->asChannel();
- auto updates = rpl::single(
- rpl::empty
- ) | rpl::then(channel->session().sendAsPeers().updated(
- ) | rpl::filter(
- _1 == channel
- ) | rpl::to_empty);
- return rpl::combine(
- std::move(updates),
- channel->adminRightsValue()
- ) | rpl::map([=] {
- return channel->session().sendAsPeers().resolveChosen(channel);
- }) | rpl::distinct_until_changed(
- ) | rpl::map([=](not_null<PeerData*> chosen) {
- return Data::PeerUserpicImageValue(
- chosen,
- st::sendAsButton.size * style::DevicePixelRatio());
- }) | rpl::flatten_latest();
- }) | rpl::flatten_latest();
- std::move(
- userpic
- ) | rpl::start_with_next([=](QImage &&userpic) {
- button->setUserpic(std::move(userpic));
- }, button->lifetime());
- }
- void SetupSendAsButton(
- not_null<SendAsButton*> button,
- not_null<Window::SessionController*> window) {
- auto active = window->activeChatValue(
- ) | rpl::map([=](Dialogs::Key key) {
- return key.history() ? key.history()->peer.get() : nullptr;
- });
- SetupSendAsButton(button, std::move(active), window);
- }
- } // namespace Ui
|