Check listened / viewed for voice / video messages.

This commit is contained in:
John Preston 2021-09-08 13:50:48 +03:00
parent eb1874566b
commit fa5e66a736
4 changed files with 86 additions and 26 deletions

View file

@ -1707,10 +1707,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_context_seen_loading" = "Loading..."; "lng_context_seen_loading" = "Loading...";
"lng_context_seen_text#one" = "{count} Seen"; "lng_context_seen_text#one" = "{count} Seen";
"lng_context_seen_text#other" = "{count} Seen"; "lng_context_seen_text#other" = "{count} Seen";
"lng_context_seen_text_none" = "Nobody Viewed";
"lng_context_seen_listened#one" = "{count} Listened"; "lng_context_seen_listened#one" = "{count} Listened";
"lng_context_seen_listened#other" = "{count} Listened"; "lng_context_seen_listened#other" = "{count} Listened";
"lng_context_seen_listened_none" = "Nobody Listened";
"lng_context_seen_watched#one" = "{count} Watched"; "lng_context_seen_watched#one" = "{count} Watched";
"lng_context_seen_watched#other" = "{count} Watched"; "lng_context_seen_watched#other" = "{count} Watched";
"lng_context_seen_watched_none" = "Nobody Watched";
"lng_send_image_empty" = "Could not send an empty file: {name}"; "lng_send_image_empty" = "Could not send an empty file: {name}";
"lng_send_image_too_large" = "Could not send a file, because it is larger than 1500 MB: {name}"; "lng_send_image_too_large" = "Could not send a file, because it is larger than 1500 MB: {name}";

View file

@ -12,9 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_document.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_media_types.h"
#include "main/main_app_config.h" #include "main/main_app_config.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_account.h" #include "main/main_account.h"
@ -26,6 +28,9 @@ namespace Api {
namespace { namespace {
struct Cached { struct Cached {
explicit Cached(UserId unknownFlag)
: list(std::vector<UserId>{ unknownFlag }) {
}
rpl::variable<std::vector<UserId>> list; rpl::variable<std::vector<UserId>> list;
mtpRequestId requestId = 0; mtpRequestId requestId = 0;
}; };
@ -33,6 +38,17 @@ struct Cached {
struct Context { struct Context {
base::flat_map<not_null<HistoryItem*>, Cached> cached; base::flat_map<not_null<HistoryItem*>, Cached> cached;
base::flat_map<not_null<Main::Session*>, rpl::lifetime> subscriptions; base::flat_map<not_null<Main::Session*>, rpl::lifetime> subscriptions;
[[nodiscard]] Cached &cache(not_null<HistoryItem*> item) {
const auto i = cached.find(item);
if (i != end(cached)) {
return i->second;
}
return cached.emplace(
item,
Cached(item->history()->session().userId())
).first->second;
}
}; };
[[nodiscard]] auto Contexts() [[nodiscard]] auto Contexts()
@ -65,10 +81,39 @@ struct Context {
return result; return result;
} }
[[nodiscard]] bool ListUnknown(
const std::vector<UserId> &list,
not_null<HistoryItem*> item) {
return (list.size() == 1)
&& (list.front() == item->history()->session().userId());
}
[[nodiscard]] Ui::WhoReadType DetectType(not_null<HistoryItem*> item) {
if (const auto media = item->media()) {
if (!media->webpage()) {
if (const auto document = media->document()) {
if (document->isVoiceMessage()) {
return Ui::WhoReadType::Listened;
} else if (document->isVideoMessage()) {
return Ui::WhoReadType::Watched;
}
}
}
}
return Ui::WhoReadType::Seen;
}
} // namespace } // namespace
bool WhoReadExists(not_null<HistoryItem*> item) { bool WhoReadExists(not_null<HistoryItem*> item) {
if (!item->out() || item->unread()) { if (!item->out()) {
return false;
}
const auto type = DetectType(item);
const auto unseen = (type == Ui::WhoReadType::Seen)
? item->unread()
: item->isUnreadMedia();
if (unseen) {
return false; return false;
} }
const auto history = item->history(); const auto history = item->history();
@ -122,38 +167,37 @@ rpl::producer<std::vector<UserId>> WhoReadIds(
context->cached.erase(i); context->cached.erase(i);
}, context->subscriptions[session]); }, context->subscriptions[session]);
} }
auto &cache = context->cached[item]; auto &entry = context->cache(item);
if (!cache.requestId) { if (!entry.requestId) {
const auto makeEmpty = [=] { const auto makeEmpty = [=] {
// Special value that marks a validated empty list. // Special value that marks a validated empty list.
return std::vector<UserId>{ return std::vector<UserId>{
item->history()->session().userId() item->history()->session().userId()
}; };
}; };
cache.requestId = session->api().request( entry.requestId = session->api().request(
MTPmessages_GetMessageReadParticipants( MTPmessages_GetMessageReadParticipants(
item->history()->peer->input, item->history()->peer->input,
MTP_int(item->id) MTP_int(item->id)
) )
).done([=](const MTPVector<MTPlong> &result) { ).done([=](const MTPVector<MTPlong> &result) {
auto &entry = context->cache(item);
entry.requestId = 0;
auto users = std::vector<UserId>(); auto users = std::vector<UserId>();
users.reserve(std::max(result.v.size(), 1)); users.reserve(std::max(result.v.size(), 1));
for (const auto &id : result.v) { for (const auto &id : result.v) {
users.push_back(UserId(id)); users.push_back(UserId(id));
} }
if (users.empty()) { entry.list = std::move(users);
}
context->cached[item].list = users.empty()
? makeEmpty()
: std::move(users);
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
if (context->cached[item].list.current().empty()) { auto &entry = context->cache(item);
context->cached[item].list = makeEmpty(); entry.requestId = 0;
if (ListUnknown(entry.list.current(), item)) {
entry.list = std::vector<UserId>();
} }
}).send(); }).send();
} }
return cache.list.value().start_existing(consumer); return entry.list.value().start_existing(consumer);
}; };
} }
@ -165,14 +209,9 @@ rpl::producer<Ui::WhoReadContent> WhoRead(
context context
) | rpl::map([=](const std::vector<UserId> &users) { ) | rpl::map([=](const std::vector<UserId> &users) {
const auto owner = &item->history()->owner(); const auto owner = &item->history()->owner();
if (users.empty()) { if (ListUnknown(users, item)) {
return Ui::WhoReadContent{ .unknown = true }; return Ui::WhoReadContent{ .unknown = true };
} }
const auto nobody = (users.size() == 1)
&& (users.front() == owner->session().userId());
if (nobody) {
return Ui::WhoReadContent();
}
auto participants = ranges::views::all( auto participants = ranges::views::all(
users users
) | ranges::views::transform([&](UserId id) { ) | ranges::views::transform([&](UserId id) {
@ -187,6 +226,7 @@ rpl::producer<Ui::WhoReadContent> WhoRead(
}) | ranges::to_vector; }) | ranges::to_vector;
return Ui::WhoReadContent{ return Ui::WhoReadContent{
.participants = std::move(participants), .participants = std::move(participants),
.type = DetectType(item),
}; };
}); });
} }

View file

@ -121,6 +121,15 @@ Action::Action(
paint(p); paint(p);
}, lifetime()); }, lifetime());
clicks(
) | rpl::start_with_next([=] {
if (_content.participants.size() == 1) {
if (const auto onstack = _participantChosen) {
onstack(_content.participants.front().id);
}
}
}, lifetime());
enableMouseSelecting(); enableMouseSelecting();
} }
@ -129,9 +138,10 @@ void Action::resolveMinWidth() {
const auto width = [&](const QString &text) { const auto width = [&](const QString &text) {
return _st.itemStyle.font->width(text); return _st.itemStyle.font->width(text);
}; };
const auto maxTextWidth = std::max( const auto maxTextWidth = std::max({
width(tr::lng_context_seen_text(tr::now, lt_count, 999)), width(tr::lng_context_seen_text(tr::now, lt_count, 999)),
width(tr::lng_context_seen_listened(tr::now, lt_count, 999))); width(tr::lng_context_seen_listened(tr::now, lt_count, 999)),
width(tr::lng_context_seen_watched(tr::now, lt_count, 999)) });
const auto maxWidth = _st.itemPadding.left() const auto maxWidth = _st.itemPadding.left()
+ maxIconWidth + maxIconWidth
+ maxTextWidth + maxTextWidth
@ -160,7 +170,7 @@ void Action::updateUserpicsFromContent() {
} }
void Action::populateSubmenu() { void Action::populateSubmenu() {
if (_content.participants.empty()) { if (_content.participants.size() < 2) {
_parentMenu->removeSubmenu(action()); _parentMenu->removeSubmenu(action());
return; return;
} }
@ -172,6 +182,7 @@ void Action::populateSubmenu() {
}; };
submenu->addAction(participant.name, chosen); submenu->addAction(participant.name, chosen);
} }
_parentMenu->checkSubmenuShow();
} }
void Action::paint(Painter &p) { void Action::paint(Painter &p) {
@ -206,10 +217,16 @@ void Action::refreshText() {
: (count == 1) : (count == 1)
? _content.participants.front().name ? _content.participants.front().name
: (_content.type == WhoReadType::Watched) : (_content.type == WhoReadType::Watched)
? tr::lng_context_seen_watched(tr::now, lt_count, count) ? (count
? tr::lng_context_seen_watched(tr::now, lt_count, count)
: tr::lng_context_seen_watched_none(tr::now))
: (_content.type == WhoReadType::Listened) : (_content.type == WhoReadType::Listened)
? tr::lng_context_seen_listened(tr::now, lt_count, count) ? (count
: tr::lng_context_seen_text(tr::now, lt_count, count)) }, ? tr::lng_context_seen_listened(tr::now, lt_count, count)
: tr::lng_context_seen_listened_none(tr::now))
: (count
? tr::lng_context_seen_text(tr::now, lt_count, count)
: tr::lng_context_seen_text_none(tr::now))) },
MenuTextOptions); MenuTextOptions);
} }

@ -1 +1 @@
Subproject commit 6651d9f9b6fb7ebc9d18e6b3429862477d891b2e Subproject commit f4cf3094c29e445256bd1c198323d393be4405c1