mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Allow to rejoin with changing of 'join_as'.
This commit is contained in:
parent
4d093f78e2
commit
b670ca2a51
13 changed files with 235 additions and 123 deletions
|
@ -287,7 +287,7 @@ updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
|
||||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||||
updateDeleteMessages#a20db0e5 messages:Vector<int> pts:int pts_count:int = Update;
|
updateDeleteMessages#a20db0e5 messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
|
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
|
||||||
updateChatUserTyping#9a65ea1f chat_id:int user_id:int action:SendMessageAction = Update;
|
updateChatUserTyping#86cadb6c chat_id:int from_id:Peer action:SendMessageAction = Update;
|
||||||
updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
||||||
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
||||||
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
||||||
|
@ -364,7 +364,7 @@ updateChannelMessageForwards#6e8a84df channel_id:int id:int forwards:int = Updat
|
||||||
updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int read_max_id:int broadcast_id:flags.0?int broadcast_post:flags.0?int = Update;
|
updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int read_max_id:int broadcast_id:flags.0?int broadcast_post:flags.0?int = Update;
|
||||||
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
|
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
|
||||||
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
|
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
|
||||||
updateChannelUserTyping#ff2abe9f flags:# channel_id:int top_msg_id:flags.0?int user_id:int action:SendMessageAction = Update;
|
updateChannelUserTyping#6b171718 flags:# channel_id:int top_msg_id:flags.0?int from_id:Peer action:SendMessageAction = Update;
|
||||||
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
|
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateChat#1330a196 chat_id:int = Update;
|
updateChat#1330a196 chat_id:int = Update;
|
||||||
|
@ -1207,7 +1207,7 @@ groupCall#c0c2052e flags:# join_muted:flags.1?true can_change_join_muted:flags.2
|
||||||
|
|
||||||
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
|
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
|
||||||
|
|
||||||
groupCallParticipant#7c48057b flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true peer:Peer date:int active_date:flags.3?int source:flags.12?int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long = GroupCallParticipant;
|
groupCallParticipant#19adba89 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long = GroupCallParticipant;
|
||||||
|
|
||||||
phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall;
|
phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall;
|
||||||
|
|
||||||
|
@ -1611,14 +1611,14 @@ phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall durati
|
||||||
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
||||||
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
||||||
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
|
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
|
||||||
phone.createGroupCall#7c068f5 peer:InputPeer join_as:InputPeer random_id:int = Updates;
|
phone.createGroupCall#bd3dabe0 peer:InputPeer random_id:int = Updates;
|
||||||
phone.joinGroupCall#3633a5b0 flags:# muted:flags.0?true call:InputGroupCall join_as:InputPeer params:DataJSON = Updates;
|
phone.joinGroupCall#3633a5b0 flags:# muted:flags.0?true call:InputGroupCall join_as:InputPeer params:DataJSON = Updates;
|
||||||
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
|
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
|
||||||
phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector<InputUser> = Updates;
|
phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector<InputUser> = Updates;
|
||||||
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
|
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
|
||||||
phone.toggleGroupCallSettings#74bbb43d flags:# call:InputGroupCall join_muted:flags.0?Bool = Updates;
|
phone.toggleGroupCallSettings#74bbb43d flags:# call:InputGroupCall join_muted:flags.0?Bool = Updates;
|
||||||
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
|
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
|
||||||
phone.getGroupParticipants#c9f1d285 call:InputGroupCall ids:Vector<int> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
|
phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector<InputPeer> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
|
||||||
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool;
|
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool;
|
||||||
phone.toggleGroupCallRecord#c02a66d7 flags:# start:flags.0?true call:InputGroupCall title:flags.1?string = Updates;
|
phone.toggleGroupCallRecord#c02a66d7 flags:# start:flags.0?true call:InputGroupCall title:flags.1?string = Updates;
|
||||||
phone.editGroupCallParticipant#d975eb80 flags:# muted:flags.0?true call:InputGroupCall participant:InputPeer volume:flags.1?int raise_hand:flags.2?Bool = Updates;
|
phone.editGroupCallParticipant#d975eb80 flags:# muted:flags.0?true call:InputGroupCall participant:InputPeer volume:flags.1?int raise_hand:flags.2?Bool = Updates;
|
||||||
|
|
|
@ -240,16 +240,16 @@ Updates::Updates(not_null<Main::Session*> session)
|
||||||
) | rpl::filter([](not_null<PeerData*> peer) {
|
) | rpl::filter([](not_null<PeerData*> peer) {
|
||||||
return peer->isChat() || peer->isMegagroup();
|
return peer->isChat() || peer->isMegagroup();
|
||||||
}) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
}) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
||||||
if (const auto users = _pendingSpeakingCallMembers.take(peer)) {
|
if (const auto list = _pendingSpeakingCallParticipants.take(peer)) {
|
||||||
if (const auto call = peer->groupCall()) {
|
if (const auto call = peer->groupCall()) {
|
||||||
for (const auto [userId, when] : *users) {
|
for (const auto [participantPeerId, when] : *list) {
|
||||||
call->applyActiveUpdate(
|
call->applyActiveUpdate(
|
||||||
userId,
|
participantPeerId,
|
||||||
Data::LastSpokeTimes{
|
Data::LastSpokeTimes{
|
||||||
.anything = when,
|
.anything = when,
|
||||||
.voice = when
|
.voice = when
|
||||||
},
|
},
|
||||||
peer->owner().userLoaded(userId));
|
peer->owner().peerLoaded(participantPeerId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -915,16 +915,16 @@ bool Updates::isQuitPrevent() {
|
||||||
void Updates::handleSendActionUpdate(
|
void Updates::handleSendActionUpdate(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
MsgId rootId,
|
MsgId rootId,
|
||||||
UserId userId,
|
PeerId fromId,
|
||||||
const MTPSendMessageAction &action) {
|
const MTPSendMessageAction &action) {
|
||||||
const auto history = session().data().historyLoaded(peerId);
|
const auto history = session().data().historyLoaded(peerId);
|
||||||
if (!history) {
|
if (!history) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto peer = history->peer;
|
const auto peer = history->peer;
|
||||||
const auto user = (userId == session().userId())
|
const auto from = (fromId == session().userPeerId())
|
||||||
? session().user().get()
|
? session().user().get()
|
||||||
: session().data().userLoaded(userId);
|
: session().data().peerLoaded(fromId);
|
||||||
const auto isSpeakingInCall = (action.type()
|
const auto isSpeakingInCall = (action.type()
|
||||||
== mtpc_speakingInGroupCallAction);
|
== mtpc_speakingInGroupCallAction);
|
||||||
if (isSpeakingInCall) {
|
if (isSpeakingInCall) {
|
||||||
|
@ -935,9 +935,9 @@ void Updates::handleSendActionUpdate(
|
||||||
const auto now = crl::now();
|
const auto now = crl::now();
|
||||||
if (call) {
|
if (call) {
|
||||||
call->applyActiveUpdate(
|
call->applyActiveUpdate(
|
||||||
userId,
|
fromId,
|
||||||
Data::LastSpokeTimes{ .anything = now, .voice = now },
|
Data::LastSpokeTimes{ .anything = now, .voice = now },
|
||||||
user);
|
from);
|
||||||
} else {
|
} else {
|
||||||
const auto chat = peer->asChat();
|
const auto chat = peer->asChat();
|
||||||
const auto channel = peer->asChannel();
|
const auto channel = peer->asChannel();
|
||||||
|
@ -945,13 +945,15 @@ void Updates::handleSendActionUpdate(
|
||||||
? (chat->flags() & MTPDchat::Flag::f_call_active)
|
? (chat->flags() & MTPDchat::Flag::f_call_active)
|
||||||
: (channel->flags() & MTPDchannel::Flag::f_call_active);
|
: (channel->flags() & MTPDchannel::Flag::f_call_active);
|
||||||
if (active) {
|
if (active) {
|
||||||
_pendingSpeakingCallMembers.emplace(
|
_pendingSpeakingCallParticipants.emplace(
|
||||||
peer).first->second[userId] = now;
|
peer).first->second[fromId] = now;
|
||||||
session().api().requestFullPeer(peer);
|
if (peerIsUser(fromId)) {
|
||||||
|
session().api().requestFullPeer(peer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!user || user->isSelf()) {
|
if (!from || !from->isUser() || from->isSelf()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto when = requestingDifference()
|
const auto when = requestingDifference()
|
||||||
|
@ -960,7 +962,7 @@ void Updates::handleSendActionUpdate(
|
||||||
session().data().registerSendAction(
|
session().data().registerSendAction(
|
||||||
history,
|
history,
|
||||||
rootId,
|
rootId,
|
||||||
user,
|
from->asUser(),
|
||||||
action,
|
action,
|
||||||
when);
|
when);
|
||||||
}
|
}
|
||||||
|
@ -1642,19 +1644,21 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
||||||
|
|
||||||
case mtpc_updateChatUserTyping: {
|
case mtpc_updateChatUserTyping: {
|
||||||
auto &d = update.c_updateChatUserTyping();
|
auto &d = update.c_updateChatUserTyping();
|
||||||
|
const auto fromId = peerFromMTP(d.vfrom_id());
|
||||||
handleSendActionUpdate(
|
handleSendActionUpdate(
|
||||||
peerFromChat(d.vchat_id()),
|
peerFromChat(d.vchat_id()),
|
||||||
0,
|
0,
|
||||||
d.vuser_id().v,
|
fromId,
|
||||||
d.vaction());
|
d.vaction());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_updateChannelUserTyping: {
|
case mtpc_updateChannelUserTyping: {
|
||||||
const auto &d = update.c_updateChannelUserTyping();
|
const auto &d = update.c_updateChannelUserTyping();
|
||||||
|
const auto fromId = peerFromMTP(d.vfrom_id());
|
||||||
handleSendActionUpdate(
|
handleSendActionUpdate(
|
||||||
peerFromChannel(d.vchannel_id()),
|
peerFromChannel(d.vchannel_id()),
|
||||||
d.vtop_msg_id().value_or_empty(),
|
d.vtop_msg_id().value_or_empty(),
|
||||||
d.vuser_id().v,
|
fromId,
|
||||||
d.vaction());
|
d.vaction());
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ private:
|
||||||
void handleSendActionUpdate(
|
void handleSendActionUpdate(
|
||||||
PeerId peerId,
|
PeerId peerId,
|
||||||
MsgId rootId,
|
MsgId rootId,
|
||||||
UserId userId,
|
PeerId fromId,
|
||||||
const MTPSendMessageAction &action);
|
const MTPSendMessageAction &action);
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
@ -168,7 +168,7 @@ private:
|
||||||
base::flat_map<int, ActiveChatTracker> _activeChats;
|
base::flat_map<int, ActiveChatTracker> _activeChats;
|
||||||
base::flat_map<
|
base::flat_map<
|
||||||
not_null<PeerData*>,
|
not_null<PeerData*>,
|
||||||
base::flat_map<UserId, crl::time>> _pendingSpeakingCallMembers;
|
base::flat_map<PeerId, crl::time>> _pendingSpeakingCallParticipants;
|
||||||
|
|
||||||
mtpRequestId _onlineRequest = 0;
|
mtpRequestId _onlineRequest = 0;
|
||||||
base::Timer _idleFinishTimer;
|
base::Timer _idleFinishTimer;
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "calls/calls_choose_join_as.h"
|
#include "calls/calls_choose_join_as.h"
|
||||||
|
|
||||||
|
#include "calls/calls_group_common.h"
|
||||||
#include "data/data_peer.h"
|
#include "data/data_peer.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
|
@ -18,8 +19,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "boxes/peer_list_box.h"
|
#include "boxes/peer_list_box.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_calls.h"
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls::Group {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using Context = ChooseJoinAsProcess::Context;
|
using Context = ChooseJoinAsProcess::Context;
|
||||||
|
@ -107,9 +109,8 @@ not_null<PeerData*> ListController::selected() const {
|
||||||
void ChooseJoinAsBox(
|
void ChooseJoinAsBox(
|
||||||
not_null<Ui::GenericBox*> box,
|
not_null<Ui::GenericBox*> box,
|
||||||
Context context,
|
Context context,
|
||||||
std::vector<not_null<PeerData*>> list,
|
JoinInfo info,
|
||||||
not_null<PeerData*> selected,
|
Fn<void(JoinInfo)> done) {
|
||||||
Fn<void(not_null<PeerData*>)> done) {
|
|
||||||
box->setTitle([&] {
|
box->setTitle([&] {
|
||||||
switch (context) {
|
switch (context) {
|
||||||
case Context::Create: return tr::lng_group_call_start_as_header();
|
case Context::Create: return tr::lng_group_call_start_as_header();
|
||||||
|
@ -121,23 +122,31 @@ void ChooseJoinAsBox(
|
||||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||||
box,
|
box,
|
||||||
tr::lng_group_call_join_as_about(),
|
tr::lng_group_call_join_as_about(),
|
||||||
st::confirmPhoneAboutLabel));
|
(context == Context::Switch
|
||||||
|
? st::groupCallBoxLabel
|
||||||
|
: st::confirmPhoneAboutLabel)));
|
||||||
|
|
||||||
auto &lifetime = box->lifetime();
|
auto &lifetime = box->lifetime();
|
||||||
const auto delegate = lifetime.make_state<
|
const auto delegate = lifetime.make_state<
|
||||||
PeerListContentDelegateSimple
|
PeerListContentDelegateSimple
|
||||||
>();
|
>();
|
||||||
const auto controller = lifetime.make_state<ListController>(
|
const auto controller = lifetime.make_state<ListController>(
|
||||||
std::move(list),
|
info.possibleJoinAs,
|
||||||
selected);
|
info.joinAs);
|
||||||
//controller->setStyleOverrides();
|
if (context == Context::Switch) {
|
||||||
|
controller->setStyleOverrides(
|
||||||
|
&st::groupCallInviteMembersList,
|
||||||
|
&st::groupCallMultiSelect);
|
||||||
|
}
|
||||||
const auto content = box->addRow(
|
const auto content = box->addRow(
|
||||||
object_ptr<PeerListContent>(box, controller),
|
object_ptr<PeerListContent>(box, controller),
|
||||||
style::margins());
|
style::margins());
|
||||||
delegate->setContent(content);
|
delegate->setContent(content);
|
||||||
controller->setDelegate(delegate);
|
controller->setDelegate(delegate);
|
||||||
box->addButton(tr::lng_continue(), [=] {
|
box->addButton(tr::lng_continue(), [=] {
|
||||||
done(controller->selected());
|
auto copy = info;
|
||||||
|
copy.joinAs = controller->selected();
|
||||||
|
done(std::move(copy));
|
||||||
});
|
});
|
||||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
}
|
}
|
||||||
|
@ -153,13 +162,16 @@ ChooseJoinAsProcess::~ChooseJoinAsProcess() {
|
||||||
void ChooseJoinAsProcess::start(
|
void ChooseJoinAsProcess::start(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Context context,
|
Context context,
|
||||||
Fn<void(not_null<PeerData*>, not_null<PeerData*>)> done) {
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
|
||||||
|
Fn<void(JoinInfo)> done,
|
||||||
|
PeerData *currentJoinAs) {
|
||||||
Expects(done != nullptr);
|
Expects(done != nullptr);
|
||||||
|
|
||||||
const auto session = &peer->session();
|
const auto session = &peer->session();
|
||||||
if (_request) {
|
if (_request) {
|
||||||
const auto already = _request->peer;
|
const auto already = _request->peer;
|
||||||
_request->context = context;
|
_request->context = context;
|
||||||
|
_request->showBox = std::move(showBox);
|
||||||
_request->done = std::move(done);
|
_request->done = std::move(done);
|
||||||
if (already == peer) {
|
if (already == peer) {
|
||||||
return;
|
return;
|
||||||
|
@ -173,6 +185,7 @@ void ChooseJoinAsProcess::start(
|
||||||
_request = std::make_unique<ChannelsListRequest>(
|
_request = std::make_unique<ChannelsListRequest>(
|
||||||
ChannelsListRequest{
|
ChannelsListRequest{
|
||||||
.peer = peer,
|
.peer = peer,
|
||||||
|
.showBox = std::move(showBox),
|
||||||
.done = std::move(done),
|
.done = std::move(done),
|
||||||
.context = context });
|
.context = context });
|
||||||
session->account().sessionChanges(
|
session->account().sessionChanges(
|
||||||
|
@ -180,12 +193,12 @@ void ChooseJoinAsProcess::start(
|
||||||
_request = nullptr;
|
_request = nullptr;
|
||||||
}, _request->lifetime);
|
}, _request->lifetime);
|
||||||
|
|
||||||
const auto finish = [=](not_null<PeerData*> joinAs) {
|
const auto finish = [=](JoinInfo info) {
|
||||||
const auto peer = _request->peer;
|
const auto peer = _request->peer;
|
||||||
const auto done = std::move(_request->done);
|
const auto done = std::move(_request->done);
|
||||||
const auto box = _request->box;
|
const auto box = _request->box;
|
||||||
_request = nullptr;
|
_request = nullptr;
|
||||||
done(peer, joinAs);
|
done(std::move(info));
|
||||||
if (const auto strong = box.data()) {
|
if (const auto strong = box.data()) {
|
||||||
strong->closeBox();
|
strong->closeBox();
|
||||||
}
|
}
|
||||||
|
@ -200,8 +213,9 @@ void ChooseJoinAsProcess::start(
|
||||||
});
|
});
|
||||||
const auto peer = _request->peer;
|
const auto peer = _request->peer;
|
||||||
const auto self = peer->session().user();
|
const auto self = peer->session().user();
|
||||||
|
auto info = JoinInfo{ .peer = peer, .joinAs = self };
|
||||||
if (chats.size() == 1) {
|
if (chats.size() == 1) {
|
||||||
finish(self);
|
finish(info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto list = std::vector<not_null<PeerData*>>();
|
auto list = std::vector<not_null<PeerData*>>();
|
||||||
|
@ -210,8 +224,8 @@ void ChooseJoinAsProcess::start(
|
||||||
for (const auto &chat : chats) {
|
for (const auto &chat : chats) {
|
||||||
list.push_back(session->data().processChat(chat));
|
list.push_back(session->data().processChat(chat));
|
||||||
}
|
}
|
||||||
const auto selectedId = peer->groupCallDefaultJoinAs();
|
const auto selected = [&]() -> PeerData* {
|
||||||
const auto selected = [&]() -> not_null<PeerData*> {
|
const auto selectedId = peer->groupCallDefaultJoinAs();
|
||||||
if (!selectedId) {
|
if (!selectedId) {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -220,22 +234,27 @@ void ChooseJoinAsProcess::start(
|
||||||
? not_null(loaded)
|
? not_null(loaded)
|
||||||
: self;
|
: self;
|
||||||
}();
|
}();
|
||||||
_request->box = Ui::show(
|
|
||||||
Box(
|
|
||||||
ChooseJoinAsBox,
|
|
||||||
_request->context,
|
|
||||||
std::move(list),
|
|
||||||
selected,
|
|
||||||
crl::guard(&_request->guard, finish)),
|
|
||||||
Ui::LayerOption::KeepOther);
|
|
||||||
|
|
||||||
_request->box->boxClosing(
|
info.joinAs = currentJoinAs ? currentJoinAs : selected;
|
||||||
|
info.possibleJoinAs = std::move(list);
|
||||||
|
auto box = Box(
|
||||||
|
ChooseJoinAsBox,
|
||||||
|
context,
|
||||||
|
std::move(info),
|
||||||
|
crl::guard(&_request->guard, finish));
|
||||||
|
box->boxClosing(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
_request = nullptr;
|
_request = nullptr;
|
||||||
}, _request->lifetime);
|
}, _request->lifetime);
|
||||||
|
|
||||||
|
_request->box = box.data();
|
||||||
|
_request->showBox(std::move(box));
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
finish(session->user());
|
finish({
|
||||||
|
.peer = _request->peer,
|
||||||
|
.joinAs = _request->peer->session().user(),
|
||||||
|
});
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Calls
|
} // namespace Calls::Group
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
class PeerData;
|
class PeerData;
|
||||||
|
|
||||||
|
@ -15,7 +16,9 @@ namespace Ui {
|
||||||
class BoxContent;
|
class BoxContent;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls::Group {
|
||||||
|
|
||||||
|
struct JoinInfo;
|
||||||
|
|
||||||
class ChooseJoinAsProcess final {
|
class ChooseJoinAsProcess final {
|
||||||
public:
|
public:
|
||||||
|
@ -31,12 +34,15 @@ public:
|
||||||
void start(
|
void start(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Context context,
|
Context context,
|
||||||
Fn<void(not_null<PeerData*> peer, not_null<PeerData*> joinAs)> done);
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
|
||||||
|
Fn<void(JoinInfo)> done,
|
||||||
|
PeerData *currentJoinAs = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ChannelsListRequest {
|
struct ChannelsListRequest {
|
||||||
not_null<PeerData*> peer;
|
not_null<PeerData*> peer;
|
||||||
Fn<void(not_null<PeerData*>, not_null<PeerData*>)> done;
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox;
|
||||||
|
Fn<void(JoinInfo)> done;
|
||||||
base::has_weak_ptr guard;
|
base::has_weak_ptr guard;
|
||||||
QPointer<Ui::BoxContent> box;
|
QPointer<Ui::BoxContent> box;
|
||||||
rpl::lifetime lifetime;
|
rpl::lifetime lifetime;
|
||||||
|
@ -47,4 +53,4 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Calls
|
} // namespace Calls::Group
|
||||||
|
|
|
@ -102,14 +102,14 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
|
||||||
|
|
||||||
GroupCall::GroupCall(
|
GroupCall::GroupCall(
|
||||||
not_null<Delegate*> delegate,
|
not_null<Delegate*> delegate,
|
||||||
not_null<PeerData*> peer,
|
Group::JoinInfo info,
|
||||||
const MTPInputGroupCall &inputCall,
|
const MTPInputGroupCall &inputCall)
|
||||||
not_null<PeerData*> joinAs)
|
|
||||||
: _delegate(delegate)
|
: _delegate(delegate)
|
||||||
, _peer(peer)
|
, _peer(info.peer)
|
||||||
, _history(peer->owner().history(peer))
|
, _history(_peer->owner().history(_peer))
|
||||||
, _joinAs(joinAs)
|
, _api(&_peer->session().mtp())
|
||||||
, _api(&peer->session().mtp())
|
, _joinAs(info.joinAs)
|
||||||
|
, _possibleJoinAs(std::move(info.possibleJoinAs))
|
||||||
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
|
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
|
||||||
, _checkJoinedTimer([=] { checkJoined(); })
|
, _checkJoinedTimer([=] { checkJoined(); })
|
||||||
, _pushToTalkCancelTimer([=] { pushToTalkCancel(); })
|
, _pushToTalkCancelTimer([=] { pushToTalkCancel(); })
|
||||||
|
@ -247,7 +247,6 @@ void GroupCall::playConnectingSoundOnce() {
|
||||||
void GroupCall::start() {
|
void GroupCall::start() {
|
||||||
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
||||||
_peer->input,
|
_peer->input,
|
||||||
_joinAs->input,
|
|
||||||
MTP_int(openssl::RandomValue<int32>())
|
MTP_int(openssl::RandomValue<int32>())
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
_acceptFields = true;
|
_acceptFields = true;
|
||||||
|
@ -499,6 +498,21 @@ void GroupCall::discard() {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCall::rejoinAs(Group::JoinInfo info) {
|
||||||
|
_possibleJoinAs = std::move(info.possibleJoinAs);
|
||||||
|
if (info.joinAs == _joinAs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto event = Group::RejoinEvent{
|
||||||
|
.wasJoinAs = _joinAs,
|
||||||
|
.nowJoinAs = info.joinAs,
|
||||||
|
};
|
||||||
|
_joinAs = info.joinAs;
|
||||||
|
setState(State::Joining);
|
||||||
|
rejoin();
|
||||||
|
_rejoinEvents.fire_copy(event);
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::finish(FinishType type) {
|
void GroupCall::finish(FinishType type) {
|
||||||
Expects(type != FinishType::None);
|
Expects(type != FinishType::None);
|
||||||
|
|
||||||
|
@ -667,15 +681,15 @@ void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) {
|
||||||
handleOtherParticipants(data);
|
handleOtherParticipants(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.is_left() && data.vsource().value_or_empty() == _mySsrc) {
|
if (data.is_left() && data.vsource().v == _mySsrc) {
|
||||||
// I was removed from the call, rejoin.
|
// I was removed from the call, rejoin.
|
||||||
LOG(("Call Info: Rejoin after got 'left' with my ssrc."));
|
LOG(("Call Info: Rejoin after got 'left' with my ssrc."));
|
||||||
setState(State::Joining);
|
setState(State::Joining);
|
||||||
rejoin();
|
rejoin();
|
||||||
} else if (!data.is_left() && data.vsource().value_or_empty() != _mySsrc) {
|
} else if (!data.is_left() && data.vsource().v != _mySsrc) {
|
||||||
// I joined from another device, hangup.
|
// I joined from another device, hangup.
|
||||||
LOG(("Call Info: Hangup after '!left' with ssrc %1, my %2."
|
LOG(("Call Info: Hangup after '!left' with ssrc %1, my %2."
|
||||||
).arg(data.vsource().value_or_empty()
|
).arg(data.vsource().v
|
||||||
).arg(_mySsrc));
|
).arg(_mySsrc));
|
||||||
_mySsrc = 0;
|
_mySsrc = 0;
|
||||||
hangup();
|
hangup();
|
||||||
|
|
|
@ -39,6 +39,8 @@ namespace Group {
|
||||||
struct MuteRequest;
|
struct MuteRequest;
|
||||||
struct VolumeRequest;
|
struct VolumeRequest;
|
||||||
struct ParticipantState;
|
struct ParticipantState;
|
||||||
|
struct JoinInfo;
|
||||||
|
struct RejoinEvent;
|
||||||
} // namespace Group
|
} // namespace Group
|
||||||
|
|
||||||
enum class MuteState {
|
enum class MuteState {
|
||||||
|
@ -88,9 +90,8 @@ public:
|
||||||
|
|
||||||
GroupCall(
|
GroupCall(
|
||||||
not_null<Delegate*> delegate,
|
not_null<Delegate*> delegate,
|
||||||
not_null<PeerData*> peer,
|
Group::JoinInfo info,
|
||||||
const MTPInputGroupCall &inputCall,
|
const MTPInputGroupCall &inputCall);
|
||||||
not_null<PeerData*> joinAs);
|
|
||||||
~GroupCall();
|
~GroupCall();
|
||||||
|
|
||||||
[[nodiscard]] uint64 id() const {
|
[[nodiscard]] uint64 id() const {
|
||||||
|
@ -102,10 +103,15 @@ public:
|
||||||
[[nodiscard]] not_null<PeerData*> joinAs() const {
|
[[nodiscard]] not_null<PeerData*> joinAs() const {
|
||||||
return _joinAs;
|
return _joinAs;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] auto possibleJoinAs() const
|
||||||
|
-> const std::vector<not_null<PeerData*>>& {
|
||||||
|
return _possibleJoinAs;
|
||||||
|
}
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void hangup();
|
void hangup();
|
||||||
void discard();
|
void discard();
|
||||||
|
void rejoinAs(Group::JoinInfo info);
|
||||||
void join(const MTPInputGroupCall &inputCall);
|
void join(const MTPInputGroupCall &inputCall);
|
||||||
void handleUpdate(const MTPGroupCall &call);
|
void handleUpdate(const MTPGroupCall &call);
|
||||||
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
|
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
|
||||||
|
@ -142,6 +148,9 @@ public:
|
||||||
[[nodiscard]] rpl::producer<LevelUpdate> levelUpdates() const {
|
[[nodiscard]] rpl::producer<LevelUpdate> levelUpdates() const {
|
||||||
return _levelUpdates.events();
|
return _levelUpdates.events();
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] rpl::producer<Group::RejoinEvent> rejoinEvents() const {
|
||||||
|
return _rejoinEvents.events();
|
||||||
|
}
|
||||||
static constexpr auto kSpeakLevelThreshold = 0.2;
|
static constexpr auto kSpeakLevelThreshold = 0.2;
|
||||||
|
|
||||||
void setCurrentAudioDevice(bool input, const QString &deviceId);
|
void setCurrentAudioDevice(bool input, const QString &deviceId);
|
||||||
|
@ -211,11 +220,13 @@ private:
|
||||||
const not_null<Delegate*> _delegate;
|
const not_null<Delegate*> _delegate;
|
||||||
not_null<PeerData*> _peer; // Can change in legacy group migration.
|
not_null<PeerData*> _peer; // Can change in legacy group migration.
|
||||||
not_null<History*> _history; // Can change in legacy group migration.
|
not_null<History*> _history; // Can change in legacy group migration.
|
||||||
not_null<PeerData*> _joinAs;
|
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
rpl::variable<State> _state = State::Creating;
|
rpl::variable<State> _state = State::Creating;
|
||||||
bool _instanceConnected = false;
|
bool _instanceConnected = false;
|
||||||
|
|
||||||
|
not_null<PeerData*> _joinAs;
|
||||||
|
std::vector<not_null<PeerData*>> _possibleJoinAs;
|
||||||
|
|
||||||
rpl::variable<MuteState> _muted = MuteState::Muted;
|
rpl::variable<MuteState> _muted = MuteState::Muted;
|
||||||
bool _acceptFields = false;
|
bool _acceptFields = false;
|
||||||
|
|
||||||
|
@ -230,6 +241,7 @@ private:
|
||||||
std::unique_ptr<tgcalls::GroupInstanceImpl> _instance;
|
std::unique_ptr<tgcalls::GroupInstanceImpl> _instance;
|
||||||
rpl::event_stream<LevelUpdate> _levelUpdates;
|
rpl::event_stream<LevelUpdate> _levelUpdates;
|
||||||
base::flat_map<uint32, Data::LastSpokeTimes> _lastSpoke;
|
base::flat_map<uint32, Data::LastSpokeTimes> _lastSpoke;
|
||||||
|
rpl::event_stream<Group::RejoinEvent> _rejoinEvents;
|
||||||
base::Timer _lastSpokeCheckTimer;
|
base::Timer _lastSpokeCheckTimer;
|
||||||
base::Timer _checkJoinedTimer;
|
base::Timer _checkJoinedTimer;
|
||||||
|
|
||||||
|
|
|
@ -34,4 +34,15 @@ struct ParticipantState {
|
||||||
bool locallyOnly = false;
|
bool locallyOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RejoinEvent {
|
||||||
|
not_null<PeerData*> wasJoinAs;
|
||||||
|
not_null<PeerData*> nowJoinAs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JoinInfo {
|
||||||
|
not_null<PeerData*> peer;
|
||||||
|
not_null<PeerData*> joinAs;
|
||||||
|
std::vector<not_null<PeerData*>> possibleJoinAs;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Calls::Group
|
} // namespace Calls::Group
|
||||||
|
|
|
@ -855,6 +855,29 @@ void MembersController::setupListChangeViewers(not_null<GroupCall*> call) {
|
||||||
updateRowLevel(i->second, update.value);
|
updateRowLevel(i->second, update.value);
|
||||||
}
|
}
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
|
|
||||||
|
call->rejoinEvents(
|
||||||
|
) | rpl::start_with_next([=](const Group::RejoinEvent &event) {
|
||||||
|
const auto guard = gsl::finally([&] {
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
});
|
||||||
|
if (const auto row = findRow(event.wasJoinAs)) {
|
||||||
|
if (row->state() != Row::State::Invited) {
|
||||||
|
if (const auto min = _fullCountMin.current()) {
|
||||||
|
_fullCountMin = min - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeRow(row);
|
||||||
|
}
|
||||||
|
if (findRow(event.nowJoinAs)) {
|
||||||
|
return;
|
||||||
|
} else if (auto row = createRowForMe()) {
|
||||||
|
if (row->state() != Row::State::Invited) {
|
||||||
|
_fullCountMin = _fullCountMin.current() + 1;
|
||||||
|
}
|
||||||
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MembersController::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
void MembersController::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||||
|
|
|
@ -9,7 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "calls/calls_group_call.h"
|
#include "calls/calls_group_call.h"
|
||||||
#include "calls/calls_group_panel.h" // LeaveGroupCallBox.
|
#include "calls/calls_group_panel.h" // LeaveGroupCallBox.
|
||||||
|
#include "calls/calls_group_common.h"
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
|
#include "calls/calls_choose_join_as.h"
|
||||||
#include "ui/widgets/level_meter.h"
|
#include "ui/widgets/level_meter.h"
|
||||||
#include "ui/widgets/continuous_sliders.h"
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
@ -100,6 +102,7 @@ void GroupCallSettingsBox(
|
||||||
float micLevel = 0.;
|
float micLevel = 0.;
|
||||||
Ui::Animations::Simple micLevelAnimation;
|
Ui::Animations::Simple micLevelAnimation;
|
||||||
base::Timer levelUpdateTimer;
|
base::Timer levelUpdateTimer;
|
||||||
|
Group::ChooseJoinAsProcess joinAsProcess;
|
||||||
bool generatingLink = false;
|
bool generatingLink = false;
|
||||||
};
|
};
|
||||||
const auto state = box->lifetime().make_state<State>();
|
const auto state = box->lifetime().make_state<State>();
|
||||||
|
@ -115,16 +118,40 @@ void GroupCallSettingsBox(
|
||||||
const auto joinMuted = goodReal ? real->joinMuted() : false;
|
const auto joinMuted = goodReal ? real->joinMuted() : false;
|
||||||
const auto canChangeJoinMuted = (goodReal && real->canChangeJoinMuted());
|
const auto canChangeJoinMuted = (goodReal && real->canChangeJoinMuted());
|
||||||
const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted);
|
const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted);
|
||||||
if (addCheck) {
|
const auto addEditJoinAs = (call->possibleJoinAs().size() > 1);
|
||||||
|
if (addCheck || addEditJoinAs) {
|
||||||
AddSkip(layout);
|
AddSkip(layout);
|
||||||
}
|
}
|
||||||
|
const auto editJoinAs = addEditJoinAs
|
||||||
|
? AddButton(
|
||||||
|
layout,
|
||||||
|
tr::lng_group_call_display_as_header(),
|
||||||
|
st::groupCallSettingsButton).get()
|
||||||
|
: nullptr;
|
||||||
|
if (editJoinAs) {
|
||||||
|
editJoinAs->setClickedCallback([=] {
|
||||||
|
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
|
||||||
|
const auto callback = [=](Group::JoinInfo info) {
|
||||||
|
call->rejoinAs(info);
|
||||||
|
};
|
||||||
|
auto showBox = [=](object_ptr<Ui::BoxContent> next) {
|
||||||
|
box->getDelegate()->show(std::move(next));
|
||||||
|
};
|
||||||
|
state->joinAsProcess.start(
|
||||||
|
peer,
|
||||||
|
context,
|
||||||
|
showBox,
|
||||||
|
callback,
|
||||||
|
call->joinAs());
|
||||||
|
});
|
||||||
|
}
|
||||||
const auto muteJoined = addCheck
|
const auto muteJoined = addCheck
|
||||||
? AddButton(
|
? AddButton(
|
||||||
layout,
|
layout,
|
||||||
tr::lng_group_call_new_muted(),
|
tr::lng_group_call_new_muted(),
|
||||||
st::groupCallSettingsButton)->toggleOn(rpl::single(joinMuted))
|
st::groupCallSettingsButton)->toggleOn(rpl::single(joinMuted))
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (addCheck) {
|
if (addCheck || addEditJoinAs) {
|
||||||
AddSkip(layout);
|
AddSkip(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
|
|
||||||
|
#include "calls/calls_group_common.h"
|
||||||
#include "mtproto/mtproto_dh_utils.h"
|
#include "mtproto/mtproto_dh_utils.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -61,27 +62,18 @@ void Instance::startOutgoingCall(not_null<UserData*> user, bool video) {
|
||||||
|
|
||||||
void Instance::startOrJoinGroupCall(not_null<PeerData*> peer) {
|
void Instance::startOrJoinGroupCall(not_null<PeerData*> peer) {
|
||||||
const auto context = peer->groupCall()
|
const auto context = peer->groupCall()
|
||||||
? ChooseJoinAsProcess::Context::Join
|
? Group::ChooseJoinAsProcess::Context::Join
|
||||||
: ChooseJoinAsProcess::Context::Create;
|
: Group::ChooseJoinAsProcess::Context::Create;
|
||||||
_chooseJoinAs.start(peer, context, [=](
|
_chooseJoinAs.start(peer, context, [=](object_ptr<Ui::BoxContent> box) {
|
||||||
not_null<PeerData*> peer,
|
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
|
||||||
not_null<PeerData*> joinAs) {
|
}, [=](Group::JoinInfo info) {
|
||||||
startOrJoinGroupCall(peer, joinAs);
|
const auto call = info.peer->groupCall();
|
||||||
|
createGroupCall(
|
||||||
|
std::move(info),
|
||||||
|
call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::startOrJoinGroupCall(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
not_null<PeerData*> joinAs) {
|
|
||||||
destroyCurrentCall();
|
|
||||||
|
|
||||||
const auto call = peer->groupCall();
|
|
||||||
createGroupCall(
|
|
||||||
peer,
|
|
||||||
call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()),
|
|
||||||
joinAs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Instance::callFinished(not_null<Call*> call) {
|
void Instance::callFinished(not_null<Call*> call) {
|
||||||
crl::on_main(call, [=] {
|
crl::on_main(call, [=] {
|
||||||
destroyCall(call);
|
destroyCall(call);
|
||||||
|
@ -208,19 +200,17 @@ void Instance::destroyGroupCall(not_null<GroupCall*> call) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::createGroupCall(
|
void Instance::createGroupCall(
|
||||||
not_null<PeerData*> peer,
|
Group::JoinInfo info,
|
||||||
const MTPInputGroupCall &inputCall,
|
const MTPInputGroupCall &inputCall) {
|
||||||
not_null<PeerData*> joinAs) {
|
|
||||||
destroyCurrentCall();
|
destroyCurrentCall();
|
||||||
|
|
||||||
auto call = std::make_unique<GroupCall>(
|
auto call = std::make_unique<GroupCall>(
|
||||||
getGroupCallDelegate(),
|
getGroupCallDelegate(),
|
||||||
peer,
|
std::move(info),
|
||||||
inputCall,
|
inputCall);
|
||||||
joinAs);
|
|
||||||
const auto raw = call.get();
|
const auto raw = call.get();
|
||||||
|
|
||||||
peer->session().account().sessionChanges(
|
info.peer->session().account().sessionChanges(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
destroyGroupCall(raw);
|
destroyGroupCall(raw);
|
||||||
}, raw->lifetime());
|
}, raw->lifetime());
|
||||||
|
|
|
@ -16,16 +16,18 @@ namespace Platform {
|
||||||
enum class PermissionType;
|
enum class PermissionType;
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
||||||
namespace Media {
|
namespace Media::Audio {
|
||||||
namespace Audio {
|
|
||||||
class Track;
|
class Track;
|
||||||
} // namespace Audio
|
} // namespace Media::Audio
|
||||||
} // namespace Media
|
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
|
||||||
|
namespace Calls::Group {
|
||||||
|
struct JoinInfo;
|
||||||
|
} // namespace Calls::Group
|
||||||
|
|
||||||
namespace Calls {
|
namespace Calls {
|
||||||
|
|
||||||
class Panel;
|
class Panel;
|
||||||
|
@ -42,9 +44,6 @@ public:
|
||||||
|
|
||||||
void startOutgoingCall(not_null<UserData*> user, bool video);
|
void startOutgoingCall(not_null<UserData*> user, bool video);
|
||||||
void startOrJoinGroupCall(not_null<PeerData*> peer);
|
void startOrJoinGroupCall(not_null<PeerData*> peer);
|
||||||
void startOrJoinGroupCall(
|
|
||||||
not_null<PeerData*> peer,
|
|
||||||
not_null<PeerData*> joinAs);
|
|
||||||
void handleUpdate(
|
void handleUpdate(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPUpdate &update);
|
const MTPUpdate &update);
|
||||||
|
@ -107,9 +106,8 @@ private:
|
||||||
void destroyCall(not_null<Call*> call);
|
void destroyCall(not_null<Call*> call);
|
||||||
|
|
||||||
void createGroupCall(
|
void createGroupCall(
|
||||||
not_null<PeerData*> peer,
|
Group::JoinInfo info,
|
||||||
const MTPInputGroupCall &inputCall,
|
const MTPInputGroupCall &inputCall);
|
||||||
not_null<PeerData*> joinAs);
|
|
||||||
void destroyGroupCall(not_null<GroupCall*> call);
|
void destroyGroupCall(not_null<GroupCall*> call);
|
||||||
|
|
||||||
void requestPermissionOrFail(
|
void requestPermissionOrFail(
|
||||||
|
@ -150,7 +148,7 @@ private:
|
||||||
|
|
||||||
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
|
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
|
||||||
|
|
||||||
ChooseJoinAsProcess _chooseJoinAs;
|
Group::ChooseJoinAsProcess _chooseJoinAs;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ void GroupCall::requestParticipants() {
|
||||||
}
|
}
|
||||||
_participantsRequestId = api().request(MTPphone_GetGroupParticipants(
|
_participantsRequestId = api().request(MTPphone_GetGroupParticipants(
|
||||||
input(),
|
input(),
|
||||||
MTP_vector<MTPint>(), // ids
|
MTP_vector<MTPInputPeer>(), // ids
|
||||||
MTP_vector<MTPint>(), // ssrcs
|
MTP_vector<MTPint>(), // ssrcs
|
||||||
MTP_string(_nextOffset),
|
MTP_string(_nextOffset),
|
||||||
MTP_int(kRequestPerPage)
|
MTP_int(kRequestPerPage)
|
||||||
|
@ -296,7 +296,7 @@ void GroupCall::applyParticipantsSlice(
|
||||||
.peer = participantPeer,
|
.peer = participantPeer,
|
||||||
.date = data.vdate().v,
|
.date = data.vdate().v,
|
||||||
.lastActive = lastActive,
|
.lastActive = lastActive,
|
||||||
.ssrc = uint32(data.vsource().value_or_empty()),
|
.ssrc = uint32(data.vsource().v),
|
||||||
.volume = volume,
|
.volume = volume,
|
||||||
.applyVolumeFromMin = applyVolumeFromMin,
|
.applyVolumeFromMin = applyVolumeFromMin,
|
||||||
.speaking = canSelfUnmute && (was ? was->speaking : false),
|
.speaking = canSelfUnmute && (was ? was->speaking : false),
|
||||||
|
@ -469,7 +469,7 @@ void GroupCall::requestUnknownParticipants() {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}();
|
}();
|
||||||
const auto peerIds = [&] {
|
const auto participantPeerIds = [&] {
|
||||||
if (_unknownSpokenPeerIds.size() + ssrcs.size() < kRequestPerPage) {
|
if (_unknownSpokenPeerIds.size() + ssrcs.size() < kRequestPerPage) {
|
||||||
return base::take(_unknownSpokenPeerIds);
|
return base::take(_unknownSpokenPeerIds);
|
||||||
}
|
}
|
||||||
|
@ -478,8 +478,9 @@ void GroupCall::requestUnknownParticipants() {
|
||||||
if (available > 0) {
|
if (available > 0) {
|
||||||
result.reserve(available);
|
result.reserve(available);
|
||||||
while (result.size() < available) {
|
while (result.size() < available) {
|
||||||
const auto [userId, when] = _unknownSpokenPeerIds.back();
|
const auto &back = _unknownSpokenPeerIds.back();
|
||||||
result.emplace(userId, when);
|
const auto [participantPeerId, when] = back;
|
||||||
|
result.emplace(participantPeerId, when);
|
||||||
_unknownSpokenPeerIds.erase(_unknownSpokenPeerIds.end() - 1);
|
_unknownSpokenPeerIds.erase(_unknownSpokenPeerIds.end() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,16 +491,23 @@ void GroupCall::requestUnknownParticipants() {
|
||||||
for (const auto [ssrc, when] : ssrcs) {
|
for (const auto [ssrc, when] : ssrcs) {
|
||||||
ssrcInputs.push_back(MTP_int(ssrc));
|
ssrcInputs.push_back(MTP_int(ssrc));
|
||||||
}
|
}
|
||||||
auto uidInputs = QVector<MTPint>();
|
auto peerInputs = QVector<MTPInputPeer>();
|
||||||
uidInputs.reserve(peerIds.size());
|
peerInputs.reserve(participantPeerIds.size());
|
||||||
for (const auto [peerId, when] : peerIds) {
|
for (const auto [participantPeerId, when] : participantPeerIds) {
|
||||||
Assert(peerIsUser(peerId)); // #TODO calls
|
if (const auto userId = peerToUser(participantPeerId)) {
|
||||||
uidInputs.push_back(MTP_int(peerToUser(peerId)));
|
peerInputs.push_back(
|
||||||
|
MTP_inputPeerUser(MTP_int(userId), MTP_long(0)));
|
||||||
|
} else if (const auto chatId = peerToChat(participantPeerId)) {
|
||||||
|
peerInputs.push_back(MTP_inputPeerChat(MTP_int(chatId)));
|
||||||
|
} else if (const auto channelId = peerToChannel(participantPeerId)) {
|
||||||
|
peerInputs.push_back(
|
||||||
|
MTP_inputPeerChannel(MTP_int(channelId), MTP_long(0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_unknownParticipantPeersRequestId = api().request(
|
_unknownParticipantPeersRequestId = api().request(
|
||||||
MTPphone_GetGroupParticipants(
|
MTPphone_GetGroupParticipants(
|
||||||
input(),
|
input(),
|
||||||
MTP_vector<MTPint>(uidInputs),
|
MTP_vector<MTPInputPeer>(peerInputs),
|
||||||
MTP_vector<MTPint>(ssrcInputs),
|
MTP_vector<MTPint>(ssrcInputs),
|
||||||
MTP_string(QString()),
|
MTP_string(QString()),
|
||||||
MTP_int(kRequestPerPage)
|
MTP_int(kRequestPerPage)
|
||||||
|
@ -517,17 +525,17 @@ void GroupCall::requestUnknownParticipants() {
|
||||||
applyLastSpoke(ssrc, when, now);
|
applyLastSpoke(ssrc, when, now);
|
||||||
_unknownSpokenSsrcs.remove(ssrc);
|
_unknownSpokenSsrcs.remove(ssrc);
|
||||||
}
|
}
|
||||||
for (const auto [peerId, when] : peerIds) {
|
for (const auto [id, when] : participantPeerIds) {
|
||||||
if (const auto participantPeer = _peer->owner().peerLoaded(peerId)) {
|
if (const auto participantPeer = _peer->owner().peerLoaded(id)) {
|
||||||
const auto isParticipant = ranges::contains(
|
const auto isParticipant = ranges::contains(
|
||||||
_participants,
|
_participants,
|
||||||
not_null{ participantPeer },
|
not_null{ participantPeer },
|
||||||
&Participant::peer);
|
&Participant::peer);
|
||||||
if (isParticipant) {
|
if (isParticipant) {
|
||||||
applyActiveUpdate(peerId, when, participantPeer);
|
applyActiveUpdate(id, when, participantPeer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_unknownSpokenPeerIds.remove(peerId);
|
_unknownSpokenPeerIds.remove(id);
|
||||||
}
|
}
|
||||||
requestUnknownParticipants();
|
requestUnknownParticipants();
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
|
@ -535,8 +543,8 @@ void GroupCall::requestUnknownParticipants() {
|
||||||
for (const auto [ssrc, when] : ssrcs) {
|
for (const auto [ssrc, when] : ssrcs) {
|
||||||
_unknownSpokenSsrcs.remove(ssrc);
|
_unknownSpokenSsrcs.remove(ssrc);
|
||||||
}
|
}
|
||||||
for (const auto [peerId, when] : peerIds) {
|
for (const auto [participantPeerId, when] : participantPeerIds) {
|
||||||
_unknownSpokenPeerIds.remove(peerId);
|
_unknownSpokenPeerIds.remove(participantPeerId);
|
||||||
}
|
}
|
||||||
requestUnknownParticipants();
|
requestUnknownParticipants();
|
||||||
}).send();
|
}).send();
|
||||||
|
|
Loading…
Add table
Reference in a new issue