Show reaction notifications in groups.

This commit is contained in:
John Preston 2022-01-28 18:47:04 +03:00
parent 54e7dfe986
commit 1dd7cc956b
5 changed files with 58 additions and 42 deletions

View file

@ -846,23 +846,19 @@ void HistoryItem::toggleReaction(const QString &reaction) {
}
void HistoryItem::updateReactions(const MTPMessageReactions *reactions) {
const auto history = this->history();
const auto toUser = (reactions && out())
? history->peer->asUser()
: nullptr;
const auto toContact = toUser && toUser->isContact();
const auto hadUnread = hasUnreadReaction();
setReactions(reactions);
const auto hasUnread = hasUnreadReaction();
if (hasUnread && !hadUnread) {
// This may read the reaction already.
addToUnreadThings(HistoryUnreadThings::AddType::New);
if (toContact && hasUnreadReaction()) {
// Call to addToUnreadThings may have read the reaction already.
if (hasUnreadReaction()) {
const auto notification = ItemNotification{
this,
ItemNotificationType::Reaction,
};
history->pushNotification(notification);
history()->pushNotification(notification);
Core::App().notifications().schedule(notification);
}
} else if (!hasUnread && hadUnread) {
@ -947,22 +943,21 @@ QString HistoryItem::chosenReaction() const {
return _reactions ? _reactions->chosen() : QString();
}
QString HistoryItem::lookupHisReaction() const {
HistoryItemUnreadReaction HistoryItem::lookupUnreadReaction() const {
if (!_reactions) {
return QString();
return {};
}
const auto &list = _reactions->list();
if (list.empty()) {
return QString();
const auto recent = _reactions->recent();
for (const auto &[emoji, list] : _reactions->recent()) {
const auto i = ranges::find(
list,
true,
&Data::RecentReaction::unread);
if (i != end(list)) {
return { .from = i->peer, .emoji = emoji };
}
}
const auto chosen = _reactions->chosen();
const auto &[first, count] = list.front();
if (chosen.isEmpty() || first != chosen || count > 1) {
return first;
} else if (list.size() == 1) {
return QString();
}
return list.back().first;
return {};
}
crl::time HistoryItem::lastReactionsRefreshTime() const {

View file

@ -63,6 +63,15 @@ enum class Context : char;
class ElementDelegate;
} // namespace HistoryView
struct HistoryItemUnreadReaction {
PeerData *from = nullptr;
QString emoji;
explicit operator bool() const {
return (from != nullptr) && !emoji.isEmpty();
}
};
struct HiddenSenderInfo;
class History;
@ -373,7 +382,7 @@ public:
std::vector<Data::RecentReaction>> &;
[[nodiscard]] bool canViewReactions() const;
[[nodiscard]] QString chosenReaction() const;
[[nodiscard]] QString lookupHisReaction() const;
[[nodiscard]] HistoryItemUnreadReaction lookupUnreadReaction() const;
[[nodiscard]] crl::time lastReactionsRefreshTime() const;
[[nodiscard]] bool hasDirectLink() const;

View file

@ -657,13 +657,14 @@ void System::showNext() {
const auto reactionNotification
= (notify->type == ItemNotificationType::Reaction);
const auto reaction = reactionNotification
? notify->item->lookupHisReaction()
: QString();
if (!reactionNotification || !reaction.isEmpty()) {
? notify->item->lookupUnreadReaction()
: HistoryItemUnreadReaction();
if (!reactionNotification || reaction) {
_manager->showNotification({
.item = notify->item,
.forwardedCount = forwardedCount,
.reaction = reaction,
.reactionFrom = reaction.from,
.reactionEmoji = reaction.emoji,
});
}
}
@ -879,13 +880,14 @@ void Manager::openNotificationMessage(
not_null<History*> history,
MsgId messageId) {
const auto openExactlyMessage = [&] {
if (history->peer->isChannel()) {
const auto peer = history->peer;
if (peer->isBroadcast()) {
return false;
}
const auto item = history->owner().message(history->peer, messageId);
if (!item
|| !item->isRegular()
|| (!item->out() && !item->mentionsMe())) {
|| (!item->out() && (!item->mentionsMe() || peer->isUser()))) {
return false;
}
return true;
@ -928,17 +930,17 @@ void Manager::notificationReplied(
void NativeManager::doShowNotification(NotificationFields &&fields) {
const auto options = getNotificationOptions(
fields.item,
(fields.reaction.isEmpty()
? ItemNotificationType::Message
: ItemNotificationType::Reaction));
(fields.reactionFrom
? ItemNotificationType::Reaction
: ItemNotificationType::Message));
const auto item = fields.item;
const auto peer = item->history()->peer;
const auto reaction = fields.reaction;
if (!reaction.isEmpty() && options.hideNameAndPhoto) {
const auto reactionFrom = fields.reactionFrom;
if (reactionFrom && options.hideNameAndPhoto) {
return;
}
const auto scheduled = !options.hideNameAndPhoto
&& fields.reaction.isEmpty()
&& !reactionFrom
&& (item->out() || peer->isSelf())
&& item->isFromScheduled();
const auto title = options.hideNameAndPhoto
@ -947,13 +949,15 @@ void NativeManager::doShowNotification(NotificationFields &&fields) {
? tr::lng_notification_reminder(tr::now)
: peer->name;
const auto fullTitle = addTargetAccountName(title, &peer->session());
const auto subtitle = (options.hideNameAndPhoto || !reaction.isEmpty())
const auto subtitle = reactionFrom
? (reactionFrom != peer ? reactionFrom->name : QString())
: options.hideNameAndPhoto
? QString()
: item->notificationHeader();
const auto text = !reaction.isEmpty()
const auto text = reactionFrom
? TextWithPermanentSpoiler(ComposeReactionNotification(
item,
reaction,
fields.reactionEmoji,
options.hideMessageText))
: options.hideMessageText
? tr::lng_notification_preview(tr::now)

View file

@ -219,7 +219,8 @@ public:
struct NotificationFields {
not_null<HistoryItem*> item;
int forwardedCount = 0;
QString reaction;
PeerData *reactionFrom = nullptr;
QString reactionEmoji;
};
explicit Manager(not_null<System*> system) : _system(system) {

View file

@ -78,8 +78,12 @@ Manager::Manager(System *system)
Manager::QueuedNotification::QueuedNotification(NotificationFields &&fields)
: history(fields.item->history())
, peer(history->peer)
, reaction(fields.reaction)
, author(reaction.isEmpty() ? fields.item->notificationHeader() : QString())
, reaction(fields.reactionEmoji)
, author(!fields.reactionFrom
? fields.item->notificationHeader()
: (fields.reactionFrom != peer)
? fields.reactionFrom->name
: QString())
, item((fields.forwardedCount < 2) ? fields.item.get() : nullptr)
, forwardedCount(fields.forwardedCount)
, fromScheduled(reaction.isEmpty() && (fields.item->out() || peer->isSelf())
@ -814,10 +818,13 @@ void Notification::updateNotifyDisplay() {
p.setPen(st::dialogsTextFg);
p.setFont(st::dialogsTextFont);
const auto text = !_reaction.isEmpty()
? Manager::ComposeReactionNotification(
? (!_author.isEmpty()
? Ui::Text::PlainLink(_author).append(' ')
: TextWithEntities()
).append(Manager::ComposeReactionNotification(
_item,
_reaction,
options.hideMessageText)
options.hideMessageText))
: _item
? _item->toPreview({
.hideSender = reminder,