Improve group call service messages.

This commit is contained in:
John Preston 2020-12-01 17:17:05 +03:00
parent 5a324756fd
commit c82bc691e0
6 changed files with 104 additions and 13 deletions

View File

@ -1066,7 +1066,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_invite_users_many" = "{from} invited {users} to the voice chat";
"lng_action_invite_users_and_one" = "{accumulated}, {user}";
"lng_action_invite_users_and_last" = "{accumulated} and {user}";
"lng_action_group_call" = "Group call";
"lng_action_group_call_started" = "{from} started a voice chat";
"lng_action_group_call_finished" = "Voice chat finished ({duration})";
"lng_action_add_user" = "{from} added {user}";
"lng_action_add_users_many" = "{from} added {users}";
"lng_action_add_users_and_one" = "{accumulated}, {user}";
@ -1847,6 +1848,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_no_anonymous" = "Anonymous admins can't join voice chats :(";
"lng_group_call_context_mute" = "Mute";
"lng_group_call_context_unmute" = "Unmute";
"lng_group_call_duration_days#one" = "{count} day";
"lng_group_call_duration_days#other" = "{count} days";
"lng_group_call_duration_hours#one" = "{count} hour";
"lng_group_call_duration_hours#other" = "{count} hours";
"lng_group_call_duration_minutes#one" = "{count} minute";
"lng_group_call_duration_minutes#other" = "{count} minutes";
"lng_group_call_duration_seconds#one" = "{count} second";
"lng_group_call_duration_seconds#other" = "{count} seconds";
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";

View File

@ -1799,6 +1799,15 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updatePhoneCallSignalingData:
case mtpc_updateGroupCallParticipants:
case mtpc_updateGroupCall: {
if (update.type() == mtpc_updateGroupCall) {
const auto &data = update.c_updateGroupCall();
if (data.vcall().type() == mtpc_groupCallDiscarded) {
const auto &call = data.vcall().c_groupCallDiscarded();
session().data().groupCallDiscarded(
call.vid().v,
call.vduration().v);
}
}
Core::App().calls().handleUpdate(&session(), update);
} break;

View File

@ -800,6 +800,14 @@ void Session::unregisterGroupCall(not_null<GroupCall*> call) {
_groupCalls.remove(call->id());
}
rpl::producer<Session::GroupCallDiscard> Session::groupCallDiscards() const {
return _groupCallDiscarded.events();
}
void Session::groupCallDiscarded(uint64 id, int duration) {
_groupCallDiscarded.fire({ id, duration });
}
GroupCall *Session::groupCall(uint64 callId) const {
const auto i = _groupCalls.find(callId);
return (i != end(_groupCalls)) ? i->second.get() : nullptr;

View File

@ -158,6 +158,13 @@ public:
void unregisterGroupCall(not_null<GroupCall*> call);
GroupCall *groupCall(uint64 callId) const;
struct GroupCallDiscard {
uint64 id = 0;
int duration = 0;
};
rpl::producer<GroupCallDiscard> groupCallDiscards() const;
void groupCallDiscarded(uint64 id, int duration);
[[nodiscard]] auto invitedToCallUsers(uint64 callId) const
-> const base::flat_set<not_null<UserData*>> &;
void registerInvitedToCallUser(
@ -921,6 +928,7 @@ private:
base::flat_map<uint64, not_null<GroupCall*>> _groupCalls;
base::flat_map<uint64, base::flat_set<not_null<UserData*>>> _invitedToCallUsers;
rpl::event_stream<GroupCallDiscard> _groupCallDiscarded;
History *_topPromoted = nullptr;

View File

@ -274,6 +274,16 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
return result;
};
auto prepareGroupCall = [this](const MTPDmessageActionGroupCall &action) {
if (const auto duration = action.vduration()) {
return prepareDiscardedCallText(duration->v);
}
auto result = PreparedText{};
result.links.push_back(fromLink());
result.text = tr::lng_action_group_call_started(tr::now, lt_from, fromLinkText());
return result;
};
auto prepareInviteToGroupCall = [this](const MTPDmessageActionInviteToGroupCall &action) {
const auto channel = history()->peer->asChannel();
const auto callId = action.vcall().match([&](const MTPDinputGroupCall &data) {
@ -367,7 +377,7 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
LOG(("API Error: messageActionSecureValuesSentMe received."));
return PreparedText{ tr::lng_message_empty(tr::now) };
}, [&](const MTPDmessageActionGroupCall &data) {
return PreparedText{ tr::lng_action_group_call(tr::now) };
return prepareGroupCall(data);
}, [&](const MTPDmessageActionInviteToGroupCall &data) {
return prepareInviteToGroupCall(data);
}, [](const MTPDmessageActionEmpty &) {
@ -466,6 +476,22 @@ bool HistoryService::updateDependent(bool force) {
return (dependent->msg || !dependent->msgId);
}
HistoryService::PreparedText HistoryService::prepareDiscardedCallText(
int duration) {
const auto seconds = duration;
const auto days = seconds / 86400;
const auto hours = seconds / 3600;
const auto minutes = seconds / 60;
auto text = (days > 1)
? tr::lng_group_call_duration_days(tr::now, lt_count, days)
: (hours > 1)
? tr::lng_group_call_duration_hours(tr::now, lt_count, hours)
: (minutes > 1)
? tr::lng_group_call_duration_minutes(tr::now, lt_count, minutes)
: tr::lng_group_call_duration_seconds(tr::now, lt_count, seconds);
return PreparedText{ tr::lng_action_group_call_finished(tr::now, lt_duration, text) };
}
HistoryService::PreparedText HistoryService::preparePinnedText() {
auto result = PreparedText {};
auto pinned = Get<HistoryServicePinned>();
@ -789,13 +815,33 @@ void HistoryService::createFromMtp(const MTPDmessage &message) {
void HistoryService::createFromMtp(const MTPDmessageService &message) {
if (message.vaction().type() == mtpc_messageActionGameScore) {
const auto &data = message.vaction().c_messageActionGameScore();
UpdateComponents(HistoryServiceGameScore::Bit());
Get<HistoryServiceGameScore>()->score = message.vaction().c_messageActionGameScore().vscore().v;
Get<HistoryServiceGameScore>()->score = data.vscore().v;
} else if (message.vaction().type() == mtpc_messageActionPaymentSent) {
const auto &data = message.vaction().c_messageActionPaymentSent();
UpdateComponents(HistoryServicePayment::Bit());
auto amount = message.vaction().c_messageActionPaymentSent().vtotal_amount().v;
auto currency = qs(message.vaction().c_messageActionPaymentSent().vcurrency());
const auto amount = data.vtotal_amount().v;
const auto currency = qs(data.vcurrency());
Get<HistoryServicePayment>()->amount = Ui::FillAmountAndCurrency(amount, currency);
} else if (message.vaction().type() == mtpc_messageActionGroupCall) {
const auto &data = message.vaction().c_messageActionGroupCall();
if (data.vduration()) {
RemoveComponents(HistoryServiceOngoingCall::Bit());
} else {
UpdateComponents(HistoryServiceOngoingCall::Bit());
const auto call = Get<HistoryServiceOngoingCall>();
const auto id = data.vcall().c_inputGroupCall().vid().v;
call->lifetime.destroy();
history()->owner().groupCallDiscards(
) | rpl::filter([=](Data::Session::GroupCallDiscard discard) {
return (discard.id == id);
}) | rpl::start_with_next([=](
Data::Session::GroupCallDiscard discard) {
RemoveComponents(HistoryServiceOngoingCall::Bit());
updateText(prepareDiscardedCallText(discard.duration));
}, call->lifetime);
}
}
if (const auto replyTo = message.vreply_to()) {
replyTo->match([&](const MTPDmessageReplyHeader &data) {
@ -852,7 +898,7 @@ Storage::SharedMediaTypesMask HistoryService::sharedMediaTypes() const {
}
void HistoryService::updateDependentText() {
auto text = PreparedText {};
auto text = PreparedText{};
if (Has<HistoryServicePinned>()) {
text = preparePinnedText();
} else if (Has<HistoryServiceGameScore>()) {
@ -862,7 +908,10 @@ void HistoryService::updateDependentText() {
} else {
return;
}
updateText(std::move(text));
}
void HistoryService::updateText(PreparedText &&text) {
setServiceText(text);
history()->owner().requestItemResize(this);
const auto inDialogsHistory = history()->migrateToOrMe();

View File

@ -20,24 +20,24 @@ struct HistoryServiceDependentData {
};
struct HistoryServicePinned
: public RuntimeComponent<HistoryServicePinned, HistoryItem>
, public HistoryServiceDependentData {
: public RuntimeComponent<HistoryServicePinned, HistoryItem>
, public HistoryServiceDependentData {
};
struct HistoryServiceGameScore
: public RuntimeComponent<HistoryServiceGameScore, HistoryItem>
, public HistoryServiceDependentData {
: public RuntimeComponent<HistoryServiceGameScore, HistoryItem>
, public HistoryServiceDependentData {
int score = 0;
};
struct HistoryServicePayment
: public RuntimeComponent<HistoryServicePayment, HistoryItem>
, public HistoryServiceDependentData {
: public RuntimeComponent<HistoryServicePayment, HistoryItem>
, public HistoryServiceDependentData {
QString amount;
};
struct HistoryServiceSelfDestruct
: public RuntimeComponent<HistoryServiceSelfDestruct, HistoryItem> {
: public RuntimeComponent<HistoryServiceSelfDestruct, HistoryItem> {
enum class Type {
Photo,
Video,
@ -47,6 +47,12 @@ struct HistoryServiceSelfDestruct
crl::time destructAt = 0;
};
struct HistoryServiceOngoingCall
: public RuntimeComponent<HistoryServiceOngoingCall, HistoryItem> {
uint64 id = 0;
rpl::lifetime lifetime;
};
namespace HistoryView {
class ServiceMessagePainter;
} // namespace HistoryView
@ -136,6 +142,7 @@ private:
}
bool updateDependent(bool force = false);
void updateDependentText();
void updateText(PreparedText &&text);
void clearDependency();
void createFromMtp(const MTPDmessage &message);
@ -149,6 +156,7 @@ private:
PreparedText preparePinnedText();
PreparedText prepareGameScoreText();
PreparedText preparePaymentSentText();
PreparedText prepareDiscardedCallText(int duration);
friend class HistoryView::Service;