Move discussion group link to three-dot menu.

This commit is contained in:
John Preston 2020-09-03 15:53:54 +04:00
parent 60002555c3
commit d42ce87c09
12 changed files with 95 additions and 208 deletions

View File

@ -812,6 +812,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_set_group_photo" = "Set Photo";
"lng_profile_add_participant" = "Add Members";
"lng_profile_view_channel" = "View Channel";
"lng_profile_view_discussion" = "View discussion";
"lng_profile_join_channel" = "Join Channel";
"lng_profile_join_group" = "Join Group";
"lng_profile_delete_and_exit" = "Leave";
@ -1330,7 +1331,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_restart_button" = "Restart";
"lng_channel_mute" = "Mute";
"lng_channel_unmute" = "Unmute";
"lng_channel_discuss" = "Discuss";
"lng_saved_messages" = "Saved Messages";
"lng_saved_short" = "Save";
"lng_saved_forward_here" = "Forward messages here for quick access";
@ -1350,17 +1350,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_replies_header#one" = "{count} reply";
"lng_replies_header#other" = "{count} replies";
"lng_replies_header_none" = "No replies";
"lng_replies_send_placeholder" = "Reply";
"lng_comments_view#one" = "View {count} Comment";
"lng_comments_view#other" = "View {count} Comments";
"lng_comments_view_thread" = "Leave a Comment";
"lng_comments_header#one" = "{count} comment";
"lng_comments_header#other" = "{count} comments";
"lng_comments_header_none" = "No comments";
"lng_comments_open_count#one" = "{count} comment";
"lng_comments_open_count#other" = "{count} comments";
"lng_comments_open_none" = "Leave a comment";
"lng_comments_send_placeholder" = "Comment";
"lng_archived_name" = "Archived chats";
"lng_archived_add" = "Archive";

View File

@ -613,6 +613,16 @@ const ChannelData *PeerData::asMegagroup() const {
: nullptr;
}
ChannelData *PeerData::asBroadcast() {
return isBroadcast() ? static_cast<ChannelData*>(this) : nullptr;
}
const ChannelData *PeerData::asBroadcast() const {
return isBroadcast()
? static_cast<const ChannelData*>(this)
: nullptr;
}
ChatData *PeerData::asChatNotMigrated() {
if (const auto chat = asChat()) {
return chat->migrateTo() ? nullptr : chat;
@ -729,6 +739,10 @@ bool PeerData::isMegagroup() const {
return isChannel() ? asChannel()->isMegagroup() : false;
}
bool PeerData::isBroadcast() const {
return isChannel() ? asChannel()->isBroadcast() : false;
}
bool PeerData::canWrite() const {
if (const auto user = asUser()) {
return user->canWrite();

View File

@ -158,6 +158,7 @@ public:
[[nodiscard]] bool isVerified() const;
[[nodiscard]] bool isScam() const;
[[nodiscard]] bool isMegagroup() const;
[[nodiscard]] bool isBroadcast() const;
[[nodiscard]] bool isNotificationsUser() const {
return (id == peerFromUser(333000))
@ -204,6 +205,8 @@ public:
[[nodiscard]] const ChannelData *asChannel() const;
[[nodiscard]] ChannelData *asMegagroup();
[[nodiscard]] const ChannelData *asMegagroup() const;
[[nodiscard]] ChannelData *asBroadcast();
[[nodiscard]] const ChannelData *asBroadcast() const;
[[nodiscard]] ChatData *asChatNotMigrated();
[[nodiscard]] const ChatData *asChatNotMigrated() const;
[[nodiscard]] ChannelData *asChannelOrMigrated();

View File

@ -1540,24 +1540,17 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_widget->replyToMessage(itemId);
});
}
const auto withComments = item->repliesAreComments();
const auto repliesCount = item->repliesCount();
const auto withReplies = IsServerMsgId(item->id)
&& (repliesCount > 0 || item->replyToTop());
const auto noBubbleButton = !withComments
|| (item->mainView() && !item->mainView()->drawBubble());
if (withReplies && noBubbleButton) {
if (withReplies && item->history()->peer->isMegagroup()) {
const auto rootId = repliesCount ? item->id : item->replyToTop();
const auto phrase = (item->repliesCount() > 0)
? (withComments
? tr::lng_comments_view
: tr::lng_replies_view)(
tr::now,
lt_count,
item->repliesCount())
: (withComments
? tr::lng_comments_view_thread
: tr::lng_replies_view_thread)(tr::now);
const auto phrase = (repliesCount > 0)
? tr::lng_replies_view(
tr::now,
lt_count,
repliesCount)
: tr::lng_replies_view_thread(tr::now);
_menu->addAction(phrase, [=] {
controller->showRepliesForMessage(_history, rootId);
});

View File

@ -262,7 +262,7 @@ public:
}
virtual void setReplies(const MTPMessageReplies &data) {
}
virtual void changeRepliesCount(int delta, UserId replier) {
virtual void changeRepliesCount(int delta, PeerId replier) {
}
virtual void setReplyToTop(MsgId replyToTop) {
}

View File

@ -41,7 +41,7 @@ struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, Histor
int textWidth = 0;
int count = -1;
};
std::vector<UserId> recentRepliers;
std::vector<PeerId> recentRepliers;
Part views;
Part replies;
ChannelId commentsChannelId = 0;

View File

@ -927,6 +927,20 @@ void HistoryMessage::createComponents(const CreateConfig &config) {
setViewsCount(config.viewsCount);
if (config.mtpReplies) {
setReplies(*config.mtpReplies);
} else if (isSending()) {
if (const auto broadcast = history()->peer->asBroadcast()) {
if (const auto linked = broadcast->linkedChat()) {
setReplies(MTP_messageReplies(
MTP_flags(MTPDmessageReplies::Flag::f_comments
| MTPDmessageReplies::Flag::f_comments),
MTP_int(0),
MTP_int(0),
MTPVector<MTPPeer>(), // recent_repliers
MTP_int(linked->bareId()),
MTP_int(0), // max_id
MTP_int(0))); // read_max_id
}
}
}
}
if (const auto edited = Get<HistoryMessageEdited>()) {
@ -1471,11 +1485,11 @@ void HistoryMessage::setReplies(const MTPMessageReplies &data) {
views = Get<HistoryMessageViews>();
}
const auto repliers = [&] {
auto result = std::vector<UserId>();
auto result = std::vector<PeerId>();
if (const auto list = data.vrecent_repliers()) {
result.reserve(list->v.size());
for (const auto &id : list->v) {
result.push_back(id.v);
result.push_back(peerFromMTP(id));
}
}
return result;
@ -1525,7 +1539,7 @@ void HistoryMessage::refreshRepliesText(
}
}
void HistoryMessage::changeRepliesCount(int delta, UserId replier) {
void HistoryMessage::changeRepliesCount(int delta, PeerId replier) {
const auto views = Get<HistoryMessageViews>();
const auto limit = HistoryMessageViews::kMaxRecentRepliers;
if (!views || views->replies.count < 0) {
@ -1596,12 +1610,10 @@ void HistoryMessage::changeReplyToTopCounter(
}
const auto changeFor = [&](not_null<HistoryItem*> item) {
if (const auto from = displayFrom()) {
if (const auto user = from->asUser()) {
item->changeRepliesCount(delta, user->bareId());
return;
}
item->changeRepliesCount(delta, from->id);
return;
}
item->changeRepliesCount(delta, UserId());
item->changeRepliesCount(delta, PeerId());
};
if (const auto views = top->Get<HistoryMessageViews>()) {
if (views->commentsChannelId) {

View File

@ -135,7 +135,7 @@ public:
void setViewsCount(int count) override;
void setForwardsCount(int count) override;
void setReplies(const MTPMessageReplies &data) override;
void changeRepliesCount(int delta, UserId replier) override;
void changeRepliesCount(int delta, PeerId replier) override;
void setReplyToTop(MsgId replyToTop) override;
void setRealId(MsgId newId) override;
void incrementReplyToTopCounter() override;

View File

@ -139,101 +139,6 @@ constexpr auto kCommonModifiers = 0
| Qt::ControlModifier;
const auto kPsaAboutPrefix = "cloud_lng_about_psa_";
object_ptr<Ui::FlatButton> SetupDiscussButton(
not_null<QWidget*> parent,
not_null<Window::SessionController*> controller) {
auto result = object_ptr<Ui::FlatButton>(
parent,
QString(),
st::historyComposeButton);
const auto button = result.data();
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
tr::lng_channel_discuss() | Ui::Text::ToUpper(),
st::historyComposeButtonLabel);
const auto badge = Ui::CreateChild<Ui::UnreadBadge>(button);
label->show();
controller->activeChatValue(
) | rpl::map([=](Dialogs::Key chat) {
return chat.history();
}) | rpl::map([=](History *history) {
return history ? history->peer->asChannel() : nullptr;
}) | rpl::map([=](ChannelData *channel) -> rpl::producer<ChannelData*> {
if (channel && channel->isBroadcast()) {
return channel->session().changes().peerFlagsValue(
channel,
Data::PeerUpdate::Flag::ChannelLinkedChat
) | rpl::map([=] {
return channel->linkedChat();
});
}
return rpl::single<ChannelData*>(nullptr);
}) | rpl::flatten_latest(
) | rpl::distinct_until_changed(
) | rpl::map([=](ChannelData *chat)
-> rpl::producer<std::tuple<int, bool>> {
if (chat) {
using UpdateFlag = Data::PeerUpdate::Flag;
return rpl::merge(
chat->session().changes().historyUpdates(
Data::HistoryUpdate::Flag::UnreadView
) | rpl::filter([=](const Data::HistoryUpdate &update) {
return (update.history->peer == chat);
}) | rpl::to_empty,
chat->session().changes().peerFlagsValue(
chat,
UpdateFlag::Notifications | UpdateFlag::ChannelAmIn
) | rpl::to_empty
) | rpl::map([=] {
const auto history = chat->amIn()
? chat->owner().historyLoaded(chat)
: nullptr;
return history
? std::make_tuple(
history->unreadCountForBadge(),
!history->mute())
: std::make_tuple(0, false);
});
} else {
return rpl::single(std::make_tuple(0, false));
}
}) | rpl::flatten_latest(
) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](int count, bool active) {
badge->setText(QString::number(count), active);
badge->setVisible(count > 0);
}, badge->lifetime());
rpl::combine(
badge->shownValue(),
badge->widthValue(),
label->widthValue(),
button->widthValue()
) | rpl::start_with_next([=](
bool badgeShown,
int badgeWidth,
int labelWidth,
int width) {
const auto textTop = st::historyComposeButton.textTop;
const auto badgeTop = textTop
+ st::historyComposeButton.font->height
- badge->textBaseline();
const auto add = badgeShown
? (textTop + badgeWidth)
: 0;
const auto total = labelWidth + add;
label->moveToLeft((width - total) / 2, textTop, width);
badge->moveToRight((width - total) / 2, textTop, width);
}, button->lifetime());
label->setAttribute(Qt::WA_TransparentForMouseEvents);
badge->setAttribute(Qt::WA_TransparentForMouseEvents);
return result;
}
void ShowErrorToast(const QString &text) {
Ui::Toast::Show(Ui::Toast::Config{
.text = { text },
@ -278,7 +183,6 @@ HistoryWidget::HistoryWidget(
this,
tr::lng_channel_mute(tr::now).toUpper(),
st::historyComposeButton)
, _discuss(SetupDiscussButton(this, controller))
, _attachToggle(this, st::historyAttach)
, _tabbedSelectorToggle(this, st::historyAttachEmoji)
, _botKeyboardShow(this, st::historyBotKeyboardShow)
@ -318,7 +222,6 @@ HistoryWidget::HistoryWidget(
_botStart->addClickHandler([=] { sendBotStartCommand(); });
_joinChannel->addClickHandler([=] { joinChannel(); });
_muteUnmute->addClickHandler([=] { toggleMuteUnmute(); });
_discuss->addClickHandler([=] { goToDiscussionGroup(); });
connect(
_field,
&Ui::InputField::submitted,
@ -448,7 +351,6 @@ HistoryWidget::HistoryWidget(
_botStart->hide();
_joinChannel->hide();
_muteUnmute->hide();
_discuss->hide();
_send->setRecordStartCallback([this] { recordStartCallback(); });
_send->setRecordStopCallback([this](bool active) { recordStopCallback(active); });
@ -2140,7 +2042,6 @@ void HistoryWidget::updateControlsVisibility() {
if (isBlocked()) {
_joinChannel->hide();
_muteUnmute->hide();
_discuss->hide();
_botStart->hide();
if (_unblock->isHidden()) {
_unblock->clearState();
@ -2149,7 +2050,6 @@ void HistoryWidget::updateControlsVisibility() {
} else if (isJoinChannel()) {
_unblock->hide();
_muteUnmute->hide();
_discuss->hide();
_botStart->hide();
if (_joinChannel->isHidden()) {
_joinChannel->clearState();
@ -2163,19 +2063,10 @@ void HistoryWidget::updateControlsVisibility() {
_muteUnmute->clearState();
_muteUnmute->show();
}
if (hasDiscussionGroup()) {
if (_discuss->isHidden()) {
_discuss->clearState();
_discuss->show();
}
} else {
_discuss->hide();
}
} else if (isBotStart()) {
_unblock->hide();
_joinChannel->hide();
_muteUnmute->hide();
_discuss->hide();
if (_botStart->isHidden()) {
_botStart->clearState();
_botStart->show();
@ -2217,7 +2108,6 @@ void HistoryWidget::updateControlsVisibility() {
_botStart->hide();
_joinChannel->hide();
_muteUnmute->hide();
_discuss->hide();
_send->show();
updateSendButtonType();
if (_recording) {
@ -2296,7 +2186,6 @@ void HistoryWidget::updateControlsVisibility() {
_botStart->hide();
_joinChannel->hide();
_muteUnmute->hide();
_discuss->hide();
_attachToggle->hide();
if (_silent) {
_silent->hide();
@ -3242,22 +3131,6 @@ void HistoryWidget::toggleMuteUnmute() {
session().data().updateNotifySettings(_peer, muteForSeconds);
}
void HistoryWidget::goToDiscussionGroup() {
const auto channel = _peer ? _peer->asChannel() : nullptr;
const auto chat = channel ? channel->linkedChat() : nullptr;
if (!chat) {
return;
}
controller()->showPeerHistory(chat, Window::SectionShow::Way::Forward);
}
bool HistoryWidget::hasDiscussionGroup() const {
const auto channel = _peer ? _peer->asChannel() : nullptr;
return channel
&& channel->isBroadcast()
&& (channel->flags() & MTPDchannel::Flag::f_has_link);
}
void HistoryWidget::onBroadcastSilentChange() {
updateFieldPlaceholder();
}
@ -4033,7 +3906,7 @@ void HistoryWidget::moveFieldControls() {
// _attachToggle --------- _inlineResults -------------------------------------- _tabbedPanel --------- _fieldBarCancel
// (_attachDocument|_attachPhoto) _field (_scheduled) (_silent|_cmdStart|_kbShow) (_kbHide|_tabbedSelectorToggle) _send
// (_botStart|_unblock|_joinChannel|{_muteUnmute&_discuss})
// (_botStart|_unblock|_joinChannel|_muteUnmute)
auto buttonsBottom = bottom - _attachToggle->height();
auto left = 0;
@ -4073,20 +3946,7 @@ void HistoryWidget::moveFieldControls() {
_unblock->setGeometry(fullWidthButtonRect);
_joinChannel->setGeometry(fullWidthButtonRect);
if (hasDiscussionGroup()) {
_muteUnmute->setGeometry(myrtlrect(
0,
fullWidthButtonRect.y(),
width() / 2,
fullWidthButtonRect.height()));
_discuss->setGeometry(myrtlrect(
width() / 2,
fullWidthButtonRect.y(),
width() - (width() / 2),
fullWidthButtonRect.height()));
} else {
_muteUnmute->setGeometry(fullWidthButtonRect);
}
_muteUnmute->setGeometry(fullWidthButtonRect);
}
void HistoryWidget::updateFieldSize() {
@ -4458,7 +4318,6 @@ void HistoryWidget::handleHistoryChange(not_null<const History*> history) {
const auto botStart = isBotStart();
const auto joinChannel = isJoinChannel();
const auto muteUnmute = isMuteUnmute();
const auto discuss = muteUnmute && hasDiscussionGroup();
const auto update = false
|| (_unblock->isHidden() == unblock)
|| (!unblock && _botStart->isHidden() == botStart)
@ -4468,8 +4327,7 @@ void HistoryWidget::handleHistoryChange(not_null<const History*> history) {
|| (!unblock
&& !botStart
&& !joinChannel
&& (_muteUnmute->isHidden() == muteUnmute
|| _discuss->isHidden() == discuss));
&& _muteUnmute->isHidden() == muteUnmute);
if (update) {
updateControlsVisibility();
updateControlsGeometry();
@ -5999,8 +5857,7 @@ void HistoryWidget::handlePeerUpdate() {
}
if (!_a_show.animating()) {
if (_unblock->isHidden() == isBlocked()
|| (!isBlocked() && _joinChannel->isHidden() == isJoinChannel())
|| (isMuteUnmute() && _discuss->isHidden() == hasDiscussionGroup())) {
|| (!isBlocked() && _joinChannel->isHidden() == isJoinChannel())) {
resize = true;
}
bool newCanSendMessages = _peer->canWrite();

View File

@ -397,9 +397,6 @@ private:
void unblockUser();
void sendBotStartCommand();
void joinChannel();
void goToDiscussionGroup();
[[nodiscard]] bool hasDiscussionGroup() const;
void supportInitAutocomplete();
void supportInsertText(const QString &text);
@ -694,7 +691,6 @@ private:
object_ptr<Ui::FlatButton> _botStart;
object_ptr<Ui::FlatButton> _joinChannel;
object_ptr<Ui::FlatButton> _muteUnmute;
object_ptr<Ui::FlatButton> _discuss;
object_ptr<Ui::IconButton> _attachToggle;
object_ptr<Ui::EmojiButton> _tabbedSelectorToggle;
object_ptr<Ui::IconButton> _botKeyboardShow;

View File

@ -192,7 +192,7 @@ style::color FromNameFg(PeerId peerId, bool selected) {
struct Message::CommentsButton {
struct Userpic {
not_null<UserData*> user;
not_null<PeerData*> peer;
std::shared_ptr<Data::CloudImageView> view;
InMemoryKey uniqueKey;
};
@ -636,11 +636,11 @@ void Message::paintCommentsButton(
}
for (auto i = 0; i != count; ++i) {
auto &entry = list[i];
const auto user = entry.user;
const auto peer = entry.peer;
auto &view = entry.view;
const auto wasView = view.get();
if (views->recentRepliers[i] != user->bareId()
|| user->userpicUniqueKey(view) != entry.uniqueKey
if (views->recentRepliers[i] != peer->id
|| peer->userpicUniqueKey(view) != entry.uniqueKey
|| view.get() != wasView) {
return true;
}
@ -649,13 +649,13 @@ void Message::paintCommentsButton(
}();
if (regenerate) {
for (auto i = 0; i != count; ++i) {
const auto userId = views->recentRepliers[i];
const auto peerId = views->recentRepliers[i];
if (i == list.size()) {
list.push_back(CommentsButton::Userpic{
history()->owner().user(userId)
history()->owner().peer(peerId)
});
} else if (list[i].user->bareId() != userId) {
list[i].user = history()->owner().user(userId);
} else if (list[i].peer->id != peerId) {
list[i].peer = history()->owner().peer(peerId);
}
}
while (list.size() > count) {
@ -678,8 +678,8 @@ void Message::paintCommentsButton(
for (auto i = count; i != 0;) {
auto &entry = list[--i];
q.setCompositionMode(QPainter::CompositionMode_SourceOver);
entry.user->paintUserpic(q, entry.view, x, 0, single);
entry.uniqueKey = entry.user->userpicUniqueKey(entry.view);
entry.peer->paintUserpic(q, entry.view, x, 0, single);
entry.uniqueKey = entry.peer->userpicUniqueKey(entry.view);
q.setCompositionMode(QPainter::CompositionMode_Source);
q.drawEllipse(x, 0, single, single);
x -= single - shift;
@ -1183,23 +1183,29 @@ bool Message::getStateCommentsButton(
return false;
}
g.setHeight(g.height() - st::historyCommentsButtonHeight);
if (QRect(g.left(), g.top() + g.height(), g.width(), st::historyCommentsButtonHeight).contains(point)) {
if (!_comments->link) {
const auto fullId = data()->fullId();
_comments->link = std::make_shared<LambdaClickHandler>([=] {
if (const auto window = App::wnd()) {
if (const auto controller = window->sessionController()) {
if (const auto item = controller->session().data().message(fullId)) {
controller->showRepliesForMessage(item->history(), item->id);
}
if (data()->isSending()
|| !QRect(
g.left(),
g.top() + g.height(),
g.width(),
st::historyCommentsButtonHeight).contains(point)) {
return false;
}
if (!_comments->link) {
const auto fullId = data()->fullId();
_comments->link = std::make_shared<LambdaClickHandler>([=] {
if (const auto window = App::wnd()) {
if (const auto controller = window->sessionController()) {
if (const auto item = controller->session().data().message(fullId)) {
controller->showRepliesForMessage(item->history(), item->id);
}
}
});
}
outResult->link = _comments->link;
_comments->lastPoint = point - QPoint(g.left(), g.top() + g.height());
}
});
}
return false;
outResult->link = _comments->link;
_comments->lastPoint = point - QPoint(g.left(), g.top() + g.height());
return true;
}
bool Message::getStateFromName(
@ -1760,6 +1766,9 @@ void Message::refreshDataIdHook() {
if (base::take(_fastReplyLink)) {
_fastReplyLink = fastReplyLink();
}
if (_comments) {
_comments->link = nullptr;
}
}
int Message::timeLeft() const {

View File

@ -547,13 +547,21 @@ void Filler::addChannelActions(not_null<ChannelData*> channel) {
// }
//}
if (_source != PeerMenuSource::ChatsList) {
if (channel->isBroadcast()) {
if (const auto chat = channel->linkedChat()) {
_addAction(tr::lng_profile_view_discussion(tr::now), [=] {
navigation->showPeerHistory(
chat,
Window::SectionShow::Way::Forward);
});
}
}
if (EditPeerInfoBox::Available(channel)) {
const auto controller = _controller;
const auto text = isGroup
? tr::lng_manage_group_title(tr::now)
: tr::lng_manage_channel_title(tr::now);
_addAction(text, [=] {
controller->showEditPeerBox(channel);
navigation->showEditPeerBox(channel);
});
}
if (channel->canAddMembers()) {