Show reaction notifications in groups.
This commit is contained in:
parent
54e7dfe986
commit
1dd7cc956b
5 changed files with 58 additions and 42 deletions
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue