mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 07:37:11 +02:00
Make 'voice chat' links clickable in service messages.
This commit is contained in:
parent
a61567e1a8
commit
33fc3fe354
3 changed files with 185 additions and 50 deletions
|
@ -1062,11 +1062,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_duration_minsec_seconds#other" = "{count} sec";
|
||||
"lng_duration_minutes_seconds" = "{minutes_count} {seconds_count}";
|
||||
|
||||
"lng_action_invite_user" = "{from} invited {user} to the voice chat";
|
||||
"lng_action_invite_users_many" = "{from} invited {users} to the voice chat";
|
||||
"lng_action_invite_user" = "{from} invited {user} to {chat}";
|
||||
"lng_action_invite_users_many" = "{from} invited {users} to {chat}";
|
||||
"lng_action_invite_user_chat" = "the voice chat";
|
||||
"lng_action_invite_users_and_one" = "{accumulated}, {user}";
|
||||
"lng_action_invite_users_and_last" = "{accumulated} and {user}";
|
||||
"lng_action_group_call_started" = "{from} started a voice chat";
|
||||
"lng_action_group_call_started" = "{from} started {chat}";
|
||||
"lng_action_group_call_started_chat" = "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}";
|
||||
|
@ -1142,13 +1144,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_profile_migrate_body" = "To add more members, you can upgrade your group to a supergroup.";
|
||||
"lng_profile_migrate_learn_more" = "Learn more »";
|
||||
"lng_profile_migrate_button" = "Upgrade to supergroup";
|
||||
"lng_profile_convert_title" = "Convert to supergroup";
|
||||
"lng_profile_convert_feature1" = "— New members see the full message history";
|
||||
"lng_profile_convert_feature2" = "— Messages are deleted for all members";
|
||||
"lng_profile_convert_feature3" = "— Admins can pin important messages";
|
||||
"lng_profile_convert_feature4" = "— Creator can set a public link for the group";
|
||||
"lng_profile_convert_warning" = "{bold_start}Note:{bold_end} This action can not be undone";
|
||||
"lng_profile_convert_confirm" = "Convert";
|
||||
"lng_profile_add_more_after_create" = "You will be able to add more members after you create the group.";
|
||||
|
||||
"lng_channel_not_accessible" = "Sorry, this channel is not accessible.";
|
||||
|
|
|
@ -24,7 +24,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_group_call.h" // Data::GroupCall::id().
|
||||
#include "core/application.h"
|
||||
#include "calls/calls_instance.h" // Core::App().calls().joinGroupCall.
|
||||
#include "window/notifications_manager.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
|
@ -35,6 +37,44 @@ namespace {
|
|||
|
||||
constexpr auto kPinnedMessageTextLimit = 16;
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> ChannelHasThisCallValue(
|
||||
not_null<ChannelData*> channel,
|
||||
uint64 id) {
|
||||
return channel->session().changes().peerFlagsValue(
|
||||
channel,
|
||||
Data::PeerUpdate::Flag::GroupCall
|
||||
) | rpl::filter([=] {
|
||||
return (channel->call() != nullptr)
|
||||
|| !(channel->flags()
|
||||
& MTPDchannel::Flag::f_call_active);
|
||||
}) | rpl::map([=] {
|
||||
const auto call = channel->call();
|
||||
return (call && call->id() == id);
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::take_while([=](bool hasThisCall) {
|
||||
return hasThisCall;
|
||||
}) | rpl::then(
|
||||
rpl::single(false)
|
||||
);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<bool> ChannelHasThisCall(
|
||||
not_null<ChannelData*> channel,
|
||||
uint64 id) {
|
||||
const auto call = channel->call();
|
||||
return call
|
||||
? std::make_optional(call->id() == id)
|
||||
: (channel->flags() & MTPDchannel::Flag::f_call_active)
|
||||
? std::nullopt
|
||||
: std::make_optional(false);
|
||||
}
|
||||
|
||||
[[nodiscard]] uint64 CallIdFromInput(const MTPInputGroupCall &data) {
|
||||
return data.match([&](const MTPDinputGroupCall &data) {
|
||||
return data.vid().v;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void HistoryService::setMessageByAction(const MTPmessageAction &action) {
|
||||
|
@ -278,53 +318,32 @@ void HistoryService::setMessageByAction(const MTPmessageAction &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;
|
||||
const auto callId = CallIdFromInput(action.vcall());
|
||||
const auto channel = history()->peer->asChannel();
|
||||
const auto linkCallId = !channel
|
||||
? 0
|
||||
: ChannelHasThisCall(channel, callId).value_or(false)
|
||||
? callId
|
||||
: 0;
|
||||
return prepareStartedCallText(linkCallId);
|
||||
};
|
||||
|
||||
auto prepareInviteToGroupCall = [this](const MTPDmessageActionInviteToGroupCall &action) {
|
||||
const auto channel = history()->peer->asChannel();
|
||||
const auto callId = action.vcall().match([&](const MTPDinputGroupCall &data) {
|
||||
return data.vid().v;
|
||||
});
|
||||
const auto callId = CallIdFromInput(action.vcall());
|
||||
const auto owner = &history()->owner();
|
||||
const auto registerUser = [&](UserId userId) {
|
||||
const auto user = owner->user(userId);
|
||||
const auto channel = history()->peer->asChannel();
|
||||
for (const auto id : action.vusers().v) {
|
||||
const auto user = owner->user(id.v);
|
||||
if (channel && callId) {
|
||||
owner->registerInvitedToCallUser(callId, channel, user);
|
||||
}
|
||||
return user;
|
||||
};
|
||||
auto result = PreparedText{};
|
||||
auto &users = action.vusers().v;
|
||||
if (users.size() == 1) {
|
||||
auto user = registerUser(users[0].v);
|
||||
result.links.push_back(fromLink());
|
||||
result.links.push_back(user->createOpenLink());
|
||||
result.text = tr::lng_action_invite_user(tr::now, lt_from, fromLinkText(), lt_user, textcmdLink(2, user->name));
|
||||
} else if (users.isEmpty()) {
|
||||
result.links.push_back(fromLink());
|
||||
result.text = tr::lng_action_invite_user(tr::now, lt_from, fromLinkText(), lt_user, qsl("somebody"));
|
||||
} else {
|
||||
result.links.push_back(fromLink());
|
||||
for (auto i = 0, l = users.size(); i != l; ++i) {
|
||||
auto user = registerUser(users[i].v);
|
||||
result.links.push_back(user->createOpenLink());
|
||||
|
||||
auto linkText = textcmdLink(i + 2, user->name);
|
||||
if (i == 0) {
|
||||
result.text = linkText;
|
||||
} else if (i + 1 == l) {
|
||||
result.text = tr::lng_action_invite_users_and_last(tr::now, lt_accumulated, result.text, lt_user, linkText);
|
||||
} else {
|
||||
result.text = tr::lng_action_invite_users_and_one(tr::now, lt_accumulated, result.text, lt_user, linkText);
|
||||
}
|
||||
}
|
||||
result.text = tr::lng_action_invite_users_many(tr::now, lt_from, fromLinkText(), lt_users, result.text);
|
||||
}
|
||||
return result;
|
||||
const auto linkCallId = !channel
|
||||
? 0
|
||||
: ChannelHasThisCall(channel, callId).value_or(false)
|
||||
? callId
|
||||
: 0;
|
||||
return prepareInvitedToCallText(action.vusers().v, linkCallId);
|
||||
};
|
||||
|
||||
const auto messageText = action.match([&](
|
||||
|
@ -492,6 +511,73 @@ HistoryService::PreparedText HistoryService::prepareDiscardedCallText(
|
|||
return PreparedText{ tr::lng_action_group_call_finished(tr::now, lt_duration, text) };
|
||||
}
|
||||
|
||||
HistoryService::PreparedText HistoryService::prepareStartedCallText(
|
||||
uint64 linkCallId) {
|
||||
auto result = PreparedText{};
|
||||
result.links.push_back(fromLink());
|
||||
const auto channel = history()->peer->asChannel();
|
||||
auto chatText = tr::lng_action_group_call_started_chat(tr::now);
|
||||
if (channel && linkCallId) {
|
||||
result.links.push_back(std::make_shared<LambdaClickHandler>([=] {
|
||||
const auto call = channel->call();
|
||||
if (call && call->id() == linkCallId) {
|
||||
Core::App().calls().joinGroupCall(channel, call->input());
|
||||
}
|
||||
}));
|
||||
chatText = textcmdLink(2, chatText);
|
||||
}
|
||||
result.text = tr::lng_action_group_call_started(
|
||||
tr::now,
|
||||
lt_from,
|
||||
fromLinkText(),
|
||||
lt_chat,
|
||||
chatText);
|
||||
return result;
|
||||
}
|
||||
|
||||
HistoryService::PreparedText HistoryService::prepareInvitedToCallText(
|
||||
const QVector<MTPint> &users,
|
||||
uint64 linkCallId) {
|
||||
const auto channel = history()->peer->asChannel();
|
||||
const auto owner = &channel->owner();
|
||||
auto chatText = tr::lng_action_invite_user_chat(tr::now);
|
||||
auto result = PreparedText{};
|
||||
result.links.push_back(fromLink());
|
||||
auto linkIndex = 1;
|
||||
if (channel && linkCallId) {
|
||||
result.links.push_back(std::make_shared<LambdaClickHandler>([=] {
|
||||
const auto call = channel->call();
|
||||
if (call && call->id() == linkCallId) {
|
||||
Core::App().calls().joinGroupCall(channel, call->input());
|
||||
}
|
||||
}));
|
||||
chatText = textcmdLink(++linkIndex, chatText);
|
||||
}
|
||||
if (users.size() == 1) {
|
||||
auto user = owner->user(users[0].v);
|
||||
result.links.push_back(user->createOpenLink());
|
||||
result.text = tr::lng_action_invite_user(tr::now, lt_from, fromLinkText(), lt_user, textcmdLink(++linkIndex, user->name), lt_chat, chatText);
|
||||
} else if (users.isEmpty()) {
|
||||
result.text = tr::lng_action_invite_user(tr::now, lt_from, fromLinkText(), lt_user, qsl("somebody"), lt_chat, chatText);
|
||||
} else {
|
||||
for (auto i = 0, l = users.size(); i != l; ++i) {
|
||||
auto user = owner->user(users[i].v);
|
||||
result.links.push_back(user->createOpenLink());
|
||||
|
||||
auto linkText = textcmdLink(++linkIndex, user->name);
|
||||
if (i == 0) {
|
||||
result.text = linkText;
|
||||
} else if (i + 1 == l) {
|
||||
result.text = tr::lng_action_invite_users_and_last(tr::now, lt_accumulated, result.text, lt_user, linkText);
|
||||
} else {
|
||||
result.text = tr::lng_action_invite_users_and_one(tr::now, lt_accumulated, result.text, lt_user, linkText);
|
||||
}
|
||||
}
|
||||
result.text = tr::lng_action_invite_users_many(tr::now, lt_from, fromLinkText(), lt_users, result.text, lt_chat, chatText);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HistoryService::PreparedText HistoryService::preparePinnedText() {
|
||||
auto result = PreparedText {};
|
||||
auto pinned = Get<HistoryServicePinned>();
|
||||
|
@ -831,8 +917,9 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
|||
} else {
|
||||
UpdateComponents(HistoryServiceOngoingCall::Bit());
|
||||
const auto call = Get<HistoryServiceOngoingCall>();
|
||||
const auto id = data.vcall().c_inputGroupCall().vid().v;
|
||||
const auto id = CallIdFromInput(data.vcall());
|
||||
call->lifetime.destroy();
|
||||
|
||||
history()->owner().groupCallDiscards(
|
||||
) | rpl::filter([=](Data::Session::GroupCallDiscard discard) {
|
||||
return (discard.id == id);
|
||||
|
@ -841,6 +928,55 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
|||
RemoveComponents(HistoryServiceOngoingCall::Bit());
|
||||
updateText(prepareDiscardedCallText(discard.duration));
|
||||
}, call->lifetime);
|
||||
|
||||
if (const auto channel = history()->peer->asChannel()) {
|
||||
const auto has = ChannelHasThisCall(channel, id);
|
||||
if (!has.has_value()) {
|
||||
ChannelHasThisCallValue(
|
||||
channel,
|
||||
id
|
||||
) | rpl::start_with_next([=](bool has) {
|
||||
updateText(prepareStartedCallText(has ? id : 0));
|
||||
}, call->lifetime);
|
||||
} else if (*has) {
|
||||
ChannelHasThisCallValue(
|
||||
channel,
|
||||
id
|
||||
) | rpl::skip(1) | rpl::start_with_next([=](bool has) {
|
||||
Assert(!has);
|
||||
updateText(prepareStartedCallText(0));
|
||||
}, call->lifetime);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (message.vaction().type() == mtpc_messageActionInviteToGroupCall) {
|
||||
const auto &data = message.vaction().c_messageActionInviteToGroupCall();
|
||||
const auto id = CallIdFromInput(data.vcall());
|
||||
const auto channel = history()->peer->asChannel();
|
||||
const auto has = channel
|
||||
? ChannelHasThisCall(channel, id)
|
||||
: std::make_optional(false);
|
||||
auto hasLink = !has.has_value()
|
||||
? ChannelHasThisCallValue(channel, id)
|
||||
: (*has)
|
||||
? ChannelHasThisCallValue(
|
||||
channel,
|
||||
id) | rpl::skip(1) | rpl::type_erased()
|
||||
: rpl::producer<bool>();
|
||||
if (!hasLink) {
|
||||
RemoveComponents(HistoryServiceOngoingCall::Bit());
|
||||
} else {
|
||||
UpdateComponents(HistoryServiceOngoingCall::Bit());
|
||||
const auto call = Get<HistoryServiceOngoingCall>();
|
||||
call->lifetime.destroy();
|
||||
|
||||
const auto users = data.vusers().v;
|
||||
std::move(hasLink) | rpl::start_with_next([=](bool has) {
|
||||
updateText(prepareInvitedToCallText(users, has ? id : 0));
|
||||
if (!has) {
|
||||
RemoveComponents(HistoryServiceOngoingCall::Bit());
|
||||
}
|
||||
}, call->lifetime);
|
||||
}
|
||||
}
|
||||
if (const auto replyTo = message.vreply_to()) {
|
||||
|
|
|
@ -157,6 +157,10 @@ private:
|
|||
PreparedText prepareGameScoreText();
|
||||
PreparedText preparePaymentSentText();
|
||||
PreparedText prepareDiscardedCallText(int duration);
|
||||
PreparedText prepareStartedCallText(uint64 linkCallId);
|
||||
PreparedText prepareInvitedToCallText(
|
||||
const QVector<MTPint> &users,
|
||||
uint64 linkCallId);
|
||||
|
||||
friend class HistoryView::Service;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue