diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index ebbed9f42..8230cbdee 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1349,6 +1349,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_requests_add_channel" = "Add to Channel"; "lng_group_requests_dismiss" = "Dismiss"; "lng_group_requests_was_added" = "{user} has been added to the group."; +"lng_group_requests_was_added_channel" = "{user} has been added to the channel."; "lng_group_requests_none" = "No member requests"; "lng_group_requests_none_channel" = "No subscriber requests"; diff --git a/Telegram/SourceFiles/api/api_invite_links.cpp b/Telegram/SourceFiles/api/api_invite_links.cpp index b2661bf8e..f39e609aa 100644 --- a/Telegram/SourceFiles/api/api_invite_links.cpp +++ b/Telegram/SourceFiles/api/api_invite_links.cpp @@ -466,7 +466,18 @@ void InviteLinks::processRequest( _api->requestParticipantsCountDelayed(channel); } _api->applyUpdates(result); - if (approved) { + if (link.isEmpty() && approved) { + // We don't know the link that was used for this user. + // Prune all the cache. + for (auto i = begin(_firstJoined); i != end(_firstJoined);) { + if (i->first.peer == peer) { + i = _firstJoined.erase(i); + } else { + ++i; + } + } + _firstSlices.remove(peer); + } else if (approved) { const auto i = _firstJoined.find({ peer, link }); if (i != end(_firstJoined)) { ++i->second.count; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 607eb9135..59ea28262 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -994,13 +994,27 @@ sponsoredUrlButton: RoundButton(defaultActiveButton) { requestsBoxItem: PeerListItem(peerListBoxItem) { height: 99px; + button: OutlineButton(defaultPeerListButton) { + textBg: contactsBg; + textBgOver: contactsBg; + ripple: RippleAnimation(defaultRippleAnimation) { + color: contactsBgOver; + } + } } requestsBoxList: PeerList(peerListBox) { + padding: margins(0px, 12px, 0px, 12px); item: requestsBoxItem; } requestsAcceptButton: RoundButton(defaultActiveButton) { + width: -28px; + height: 30px; + textTop: 6px; } requestsRejectButton: RoundButton(defaultLightButton) { + width: -28px; + height: 30px; + textTop: 6px; } requestAcceptPosition: point(71px, 58px); requestButtonsSkip: 9px; diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 2ec10319b..91d370aa0 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -542,6 +542,10 @@ bool PeerListRow::elementDisabled(int element) const { return (element == 1) && rightActionDisabled(); } +bool PeerListRow::elementOnlySelect(int element) const { + return false; +} + void PeerListRow::elementAddRipple( int element, QPoint point, @@ -1479,7 +1483,8 @@ crl::time PeerListContent::paintRow( : (_pressed.index.value >= 0) ? _pressed : _selected; - const auto selected = (active.index == index); + const auto selected = (active.index == index) + && (!active.element || !row->elementOnlySelect(active.element)); if (_mode == Mode::Custom) { _controller->customRowPaint(p, now, row, selected); @@ -1557,7 +1562,11 @@ crl::time PeerListContent::paintRow( row->paintStatusText(p, _st.item, _st.item.statusPosition.x(), _st.item.statusPosition.y(), statusw, width(), selected); } - row->elementsPaint(p, width(), selected, selected ? active.element : 0); + row->elementsPaint( + p, + width(), + selected, + (active.index == index) ? active.element : 0); return refreshStatusIn; } diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index 2318966a5..950feb1ca 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -130,6 +130,7 @@ public: virtual int elementsCount() const; virtual QRect elementGeometry(int element, int outerWidth) const; virtual bool elementDisabled(int element) const; + virtual bool elementOnlySelect(int element) const; virtual void elementAddRipple( int element, QPoint point, diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp index c2542d782..020593e69 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/popup_menu.h" #include "ui/abstract_button.h" #include "ui/toast/toast.h" +#include "ui/toasts/common_toasts.h" #include "ui/text/text_utilities.h" #include "ui/boxes/edit_invite_link.h" #include "boxes/share_box.h" @@ -59,7 +60,7 @@ using LinkData = Api::InviteLink; class RequestedRow final : public PeerListRow { public: - explicit RequestedRow(not_null peer); + RequestedRow(not_null peer, TimeId date); QSize rightActionSize() const override; QMargins rightActionMargins() const override; @@ -73,8 +74,9 @@ public: }; -RequestedRow::RequestedRow(not_null peer) +RequestedRow::RequestedRow(not_null peer, TimeId date) : PeerListRow(peer) { + setCustomStatus(PrepareRequestedRowStatus(date)); } QSize RequestedRow::rightActionSize() const { @@ -86,7 +88,7 @@ QSize RequestedRow::rightActionSize() const { QMargins RequestedRow::rightActionMargins() const { return QMargins( 0, - (st::inviteLinkList.item.height - rightActionSize().height()) / 2, + (st::peerListBoxItem.height - rightActionSize().height()) / 2, st::inviteLinkThreeDotsSkip, 0); } @@ -696,7 +698,7 @@ void Controller::appendSlice(const Api::JoinedByLinkSlice &slice) { for (const auto &user : slice.users) { _lastUser = user; delegate()->peerListAppendRow((_role == Role::Requested) - ? std::make_unique(user.user) + ? std::make_unique(user.user, user.date) : std::make_unique(user.user)); } delegate()->peerListRefreshRows(); @@ -764,6 +766,17 @@ void Controller::processRequest( delegate()->peerListRemoveRow(row); delegate()->peerListRefreshRows(); } + if (approved) { + Ui::ShowMultilineToast({ + .text = (_peer->isBroadcast() + ? tr::lng_group_requests_was_added_channel + : tr::lng_group_requests_was_added)( + tr::now, + lt_user, + Ui::Text::Bold(user->name), + Ui::Text::WithEntities) + }); + } }); const auto fail = crl::guard(this, [=] { _processed.fire({ user, false }); @@ -1288,3 +1301,26 @@ void ShowInviteLinkBox( std::move(initBox)), Ui::LayerOption::KeepOther); } + +QString PrepareRequestedRowStatus(TimeId date) { + const auto now = QDateTime::currentDateTime(); + const auto parsed = base::unixtime::parse(date); + const auto parsedDate = parsed.date(); + const auto time = parsed.time().toString(cTimeFormat()); + const auto dateGeneric = [&] { + return tr::lng_mediaview_date_time( + tr::now, + lt_date, + langDayOfMonth(parsedDate), + lt_time, + time); + }; + const auto dateString = (parsedDate.addDays(1) < now.date()) + ? dateGeneric() + : (parsedDate.addDays(1) == now.date()) + ? tr::lng_mediaview_yesterday(tr::now, lt_time, time) + : (now.date() == parsedDate) + ? tr::lng_mediaview_today(tr::now, lt_time, time) + : dateGeneric(); + return tr::lng_group_requests_status(tr::now, lt_date, dateString); +} diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h index 0d97c60be..31ebc884b 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_invite_link.h @@ -50,3 +50,5 @@ void DeleteLink( void ShowInviteLinkBox( not_null peer, const Api::InviteLink &link); + +[[nodiscard]] QString PrepareRequestedRowStatus(TimeId date); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp index 4943484b1..2d6740075 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/ripple_animation.h" #include "boxes/peer_list_controllers.h" #include "boxes/peers/edit_participants_box.h" // SubscribeToMigration +#include "boxes/peers/edit_peer_invite_link.h" // PrepareRequestedRowStatus #include "data/data_peer.h" #include "data/data_user.h" #include "data/data_chat.h" @@ -18,8 +19,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "main/main_session.h" #include "mtproto/sender.h" +#include "ui/text/text_utilities.h" +#include "ui/toasts/common_toasts.h" #include "lang/lang_keys.h" #include "window/window_session_controller.h" +#include "apiwrap.h" +#include "api/api_invite_links.h" #include "styles/style_boxes.h" namespace { @@ -58,6 +63,7 @@ public: int elementsCount() const override; QRect elementGeometry(int element, int outerWidth) const override; bool elementDisabled(int element) const override; + bool elementOnlySelect(int element) const override; void elementAddRipple( int element, QPoint point, @@ -82,27 +88,7 @@ Row::Row( TimeId date) : PeerListRow(user) , _delegate(delegate) { - const auto now = QDateTime::currentDateTime(); - const auto parsed = base::unixtime::parse(date); - const auto parsedDate = parsed.date(); - const auto time = parsed.time().toString(cTimeFormat()); - const auto dateGeneric = [&] { - return tr::lng_group_call_starts_date( - tr::now, - lt_date, - langDayOfMonthFull(parsedDate), - lt_time, - time); - }; - const auto dateString = (now.date().addDays(1) < parsedDate) - ? dateGeneric() - : (now.date().addDays(1) == parsedDate) - ? tr::lng_group_call_starts_tomorrow(tr::now, lt_time, time) - : (now.date() == parsedDate) - ? time - : dateGeneric(); - setCustomStatus( - tr::lng_group_requests_status(tr::now, lt_date, dateString)); + setCustomStatus(PrepareRequestedRowStatus(date)); } int Row::elementsCount() const { @@ -131,6 +117,10 @@ bool Row::elementDisabled(int element) const { return false; } +bool Row::elementOnlySelect(int element) const { + return true; +} + void Row::elementAddRipple( int element, QPoint point, @@ -345,8 +335,8 @@ void RequestsBoxController::refreshDescription() { setDescriptionText((delegate()->peerListFullRowsCount() > 0) ? QString() : _peer->isBroadcast() - ? tr::lng_group_removed_list_about(tr::now) - : tr::lng_channel_removed_list_about(tr::now)); + ? tr::lng_group_requests_none_channel(tr::now) + : tr::lng_group_requests_none(tr::now)); } void RequestsBoxController::rowClicked(not_null row) { @@ -362,7 +352,32 @@ void RequestsBoxController::rowElementClicked( void RequestsBoxController::processRequest( not_null user, bool approved) { - + const auto done = crl::guard(this, [=] { + if (const auto row = delegate()->peerListFindRow(user->id.value)) { + delegate()->peerListRemoveRow(row); + refreshDescription(); + delegate()->peerListRefreshRows(); + } + if (approved) { + Ui::ShowMultilineToast({ + .text = (_peer->isBroadcast() + ? tr::lng_group_requests_was_added_channel + : tr::lng_group_requests_was_added)( + tr::now, + lt_user, + Ui::Text::Bold(user->name), + Ui::Text::WithEntities) + }); + } + }); + const auto fail = [] {}; + session().api().inviteLinks().processRequest( + _peer, + QString(), // link + user, + approved, + done, + fail); } void RequestsBoxController::appendRow( diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h index 35f4a8640..abe857e65 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "boxes/peer_list_box.h" +#include "base/weak_ptr.h" namespace Window { class SessionNavigation; @@ -17,7 +18,9 @@ namespace Ui { class RippleAnimation; } // namespace Ui -class RequestsBoxController final : public PeerListController { +class RequestsBoxController final + : public PeerListController + , public base::has_weak_ptr { public: RequestsBoxController( not_null navigation,