mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support joining to voice chats as a channel.
This commit is contained in:
parent
02517f7221
commit
02e9b8fd18
18 changed files with 391 additions and 26 deletions
|
@ -263,6 +263,8 @@ PRIVATE
|
||||||
calls/calls_box_controller.h
|
calls/calls_box_controller.h
|
||||||
calls/calls_call.cpp
|
calls/calls_call.cpp
|
||||||
calls/calls_call.h
|
calls/calls_call.h
|
||||||
|
calls/calls_choose_join_as.cpp
|
||||||
|
calls/calls_choose_join_as.h
|
||||||
calls/calls_group_call.cpp
|
calls/calls_group_call.cpp
|
||||||
calls/calls_group_call.h
|
calls/calls_group_call.h
|
||||||
calls/calls_group_common.h
|
calls/calls_group_common.h
|
||||||
|
|
|
@ -1984,6 +1984,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_group_call_mac_accessibility" = "Please allow **Accessibility** for Telegram in Privacy Settings.\n\nApp restart may be required.";
|
"lng_group_call_mac_accessibility" = "Please allow **Accessibility** for Telegram in Privacy Settings.\n\nApp restart may be required.";
|
||||||
"lng_group_call_mac_settings" = "Open Settings";
|
"lng_group_call_mac_settings" = "Open Settings";
|
||||||
|
|
||||||
|
"lng_group_call_start_as_header" = "Start Voice Chat as...";
|
||||||
|
"lng_group_call_join_as_header" = "Join Voice Chat as...";
|
||||||
|
"lng_group_call_display_as_header" = "Display me as...";
|
||||||
|
"lng_group_call_join_as_about" = "Choose whether you want to be displayed as your personal account or as your channel.";
|
||||||
|
"lng_group_call_join_as_personal" = "personal account";
|
||||||
|
"lng_group_call_edit_title" = "Edit voice chat title";
|
||||||
|
"lng_group_call_switch_done" = "Members of this voice chat will now see you as **{user}**";
|
||||||
|
"lng_group_call_edit_title_header" = "Voice chat title";
|
||||||
|
"lng_group_call_recording_start" = "Start recording";
|
||||||
|
"lng_group_call_recording_stop" = "Stop recording";
|
||||||
|
"lng_group_call_recording_started" = "Voice chat recording started.";
|
||||||
|
"lng_group_call_recording_stopped" = "Voice chat recording stopped.";
|
||||||
|
|
||||||
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
||||||
|
|
||||||
"lng_player_message_today" = "Today at {time}";
|
"lng_player_message_today" = "Today at {time}";
|
||||||
|
|
|
@ -260,9 +260,9 @@ void Controller::addHeaderBlock(not_null<Ui::VerticalLayout*> container) {
|
||||||
const auto editLink = crl::guard(weak, [=] {
|
const auto editLink = crl::guard(weak, [=] {
|
||||||
EditLink(_peer, _data.current());
|
EditLink(_peer, _data.current());
|
||||||
});
|
});
|
||||||
const auto deleteLink = [=] {
|
const auto deleteLink = crl::guard(weak, [=] {
|
||||||
DeleteLink(_peer, admin, link);
|
DeleteLink(_peer, admin, link);
|
||||||
};
|
});
|
||||||
|
|
||||||
const auto createMenu = [=] {
|
const auto createMenu = [=] {
|
||||||
auto result = base::make_unique_q<Ui::PopupMenu>(container);
|
auto result = base::make_unique_q<Ui::PopupMenu>(container);
|
||||||
|
|
|
@ -730,8 +730,8 @@ groupCallTitleCloseIconOver: icon {
|
||||||
};
|
};
|
||||||
groupCallTitle: WindowTitle(defaultWindowTitle) {
|
groupCallTitle: WindowTitle(defaultWindowTitle) {
|
||||||
height: 0px;
|
height: 0px;
|
||||||
bg: transparent;
|
bg: groupCallBg;
|
||||||
bgActive: transparent;
|
bgActive: groupCallBg;
|
||||||
fg: transparent;
|
fg: transparent;
|
||||||
fgActive: transparent;
|
fgActive: transparent;
|
||||||
minimize: IconButton(groupCallTitleButton) {
|
minimize: IconButton(groupCallTitleButton) {
|
||||||
|
|
233
Telegram/SourceFiles/calls/calls_choose_join_as.cpp
Normal file
233
Telegram/SourceFiles/calls/calls_choose_join_as.cpp
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "calls/calls_choose_join_as.h"
|
||||||
|
|
||||||
|
#include "data/data_peer.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "main/main_account.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "boxes/peer_list_box.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
|
namespace Calls {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using Context = ChooseJoinAsProcess::Context;
|
||||||
|
|
||||||
|
class ListController : public PeerListController {
|
||||||
|
public:
|
||||||
|
ListController(
|
||||||
|
std::vector<not_null<PeerData*>> list,
|
||||||
|
not_null<PeerData*> selected);
|
||||||
|
|
||||||
|
Main::Session &session() const override;
|
||||||
|
void prepare() override;
|
||||||
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
|
[[nodiscard]] not_null<PeerData*> selected() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<PeerListRow> createRow(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
std::vector<not_null<PeerData*>> _list;
|
||||||
|
not_null<PeerData*> _selected;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ListController::ListController(
|
||||||
|
std::vector<not_null<PeerData*>> list,
|
||||||
|
not_null<PeerData*> selected)
|
||||||
|
: PeerListController()
|
||||||
|
, _list(std::move(list))
|
||||||
|
, _selected(selected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Main::Session &ListController::session() const {
|
||||||
|
return _selected->session();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<PeerListRow> ListController::createRow(
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
|
auto result = std::make_unique<PeerListRow>(peer);
|
||||||
|
if (peer->isSelf()) {
|
||||||
|
result->setCustomStatus(
|
||||||
|
tr::lng_group_call_join_as_personal(tr::now));
|
||||||
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
|
result->setCustomStatus(
|
||||||
|
(channel->isMegagroup()
|
||||||
|
? tr::lng_chat_status_members
|
||||||
|
: tr::lng_chat_status_subscribers)(
|
||||||
|
tr::now,
|
||||||
|
lt_count,
|
||||||
|
channel->membersCount()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListController::prepare() {
|
||||||
|
delegate()->peerListSetSearchMode(PeerListSearchMode::Disabled);
|
||||||
|
for (const auto &peer : _list) {
|
||||||
|
auto row = createRow(peer);
|
||||||
|
const auto raw = row.get();
|
||||||
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
|
if (peer == _selected) {
|
||||||
|
delegate()->peerListSetRowChecked(raw, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
const auto peer = row->peer();
|
||||||
|
if (peer == _selected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto previous = delegate()->peerListFindRow(_selected->id);
|
||||||
|
Assert(previous != nullptr);
|
||||||
|
delegate()->peerListSetRowChecked(previous, false);
|
||||||
|
delegate()->peerListSetRowChecked(row, true);
|
||||||
|
_selected = peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<PeerData*> ListController::selected() const {
|
||||||
|
return _selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChooseJoinAsBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
Context context,
|
||||||
|
std::vector<not_null<PeerData*>> list,
|
||||||
|
not_null<PeerData*> selected,
|
||||||
|
Fn<void(not_null<PeerData*>)> done) {
|
||||||
|
box->setTitle([&] {
|
||||||
|
switch (context) {
|
||||||
|
case Context::Create: return tr::lng_group_call_start_as_header();
|
||||||
|
case Context::Join: return tr::lng_group_call_join_as_header();
|
||||||
|
case Context::Switch: return tr::lng_group_call_display_as_header();
|
||||||
|
}
|
||||||
|
Unexpected("Context in ChooseJoinAsBox.");
|
||||||
|
}());
|
||||||
|
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||||
|
box,
|
||||||
|
tr::lng_group_call_join_as_about(),
|
||||||
|
st::confirmPhoneAboutLabel));
|
||||||
|
|
||||||
|
auto &lifetime = box->lifetime();
|
||||||
|
const auto delegate = lifetime.make_state<
|
||||||
|
PeerListContentDelegateSimple
|
||||||
|
>();
|
||||||
|
const auto controller = lifetime.make_state<ListController>(
|
||||||
|
std::move(list),
|
||||||
|
selected);
|
||||||
|
//controller->setStyleOverrides();
|
||||||
|
const auto content = box->addRow(
|
||||||
|
object_ptr<PeerListContent>(box, controller),
|
||||||
|
style::margins());
|
||||||
|
delegate->setContent(content);
|
||||||
|
controller->setDelegate(delegate);
|
||||||
|
box->addButton(tr::lng_continue(), [=] {
|
||||||
|
const auto selected = controller->selected();
|
||||||
|
box->closeBox();
|
||||||
|
done(selected);
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ChooseJoinAsProcess::~ChooseJoinAsProcess() {
|
||||||
|
if (_request) {
|
||||||
|
_request->peer->session().api().request(_request->id).cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChooseJoinAsProcess::start(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Context context,
|
||||||
|
Fn<void(not_null<PeerData*>, not_null<PeerData*>)> done) {
|
||||||
|
Expects(done != nullptr);
|
||||||
|
|
||||||
|
const auto session = &peer->session();
|
||||||
|
if (_request) {
|
||||||
|
const auto already = _request->peer;
|
||||||
|
_request->context = context;
|
||||||
|
_request->done = std::move(done);
|
||||||
|
if (already == peer) {
|
||||||
|
return;
|
||||||
|
} else if (&already->session() == session) {
|
||||||
|
_request->peer = peer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
session->api().request(_request->id).cancel();
|
||||||
|
_request = nullptr;
|
||||||
|
}
|
||||||
|
_request = std::make_unique<ChannelsListRequest>(
|
||||||
|
ChannelsListRequest{
|
||||||
|
.peer = peer,
|
||||||
|
.done = std::move(done),
|
||||||
|
.context = context });
|
||||||
|
session->account().sessionChanges(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
_request = nullptr;
|
||||||
|
}, _request->lifetime);
|
||||||
|
|
||||||
|
const auto finish = [=](not_null<PeerData*> joinAs) {
|
||||||
|
const auto peer = _request->peer;
|
||||||
|
const auto done = std::move(_request->done);
|
||||||
|
_request = nullptr;
|
||||||
|
done(peer, joinAs);
|
||||||
|
};
|
||||||
|
using Flag = MTPchannels_GetAdminedPublicChannels::Flag;
|
||||||
|
_request->id = session->api().request(
|
||||||
|
MTPchannels_GetAdminedPublicChannels(
|
||||||
|
MTP_flags(Flag::f_for_groupcall))
|
||||||
|
).done([=](const MTPmessages_Chats &result) {
|
||||||
|
const auto &chats = result.match([](const auto &data) {
|
||||||
|
return data.vchats().v;
|
||||||
|
});
|
||||||
|
const auto peer = _request->peer;
|
||||||
|
const auto self = peer->session().user();
|
||||||
|
if (chats.size() == 1) {
|
||||||
|
finish(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto list = std::vector<not_null<PeerData*>>();
|
||||||
|
list.reserve(chats.size() + 1);
|
||||||
|
list.push_back(self);
|
||||||
|
for (const auto &chat : chats) {
|
||||||
|
list.push_back(session->data().processChat(chat));
|
||||||
|
}
|
||||||
|
const auto selectedId = peer->groupCallDefaultJoinAs();
|
||||||
|
const auto selected = [&]() -> not_null<PeerData*> {
|
||||||
|
if (!selectedId) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
const auto loaded = session->data().peerLoaded(selectedId);
|
||||||
|
return (loaded && ranges::contains(list, not_null{ loaded }))
|
||||||
|
? not_null(loaded)
|
||||||
|
: self;
|
||||||
|
}();
|
||||||
|
Ui::show(
|
||||||
|
Box(
|
||||||
|
ChooseJoinAsBox,
|
||||||
|
_request->context,
|
||||||
|
std::move(list),
|
||||||
|
selected,
|
||||||
|
crl::guard(&_request->guard, finish)),
|
||||||
|
Ui::LayerOption::KeepOther);
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
finish(session->user());
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Calls
|
45
Telegram/SourceFiles/calls/calls_choose_join_as.h
Normal file
45
Telegram/SourceFiles/calls/calls_choose_join_as.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/weak_ptr.h"
|
||||||
|
|
||||||
|
class PeerData;
|
||||||
|
|
||||||
|
namespace Calls {
|
||||||
|
|
||||||
|
class ChooseJoinAsProcess final {
|
||||||
|
public:
|
||||||
|
ChooseJoinAsProcess() = default;
|
||||||
|
~ChooseJoinAsProcess();
|
||||||
|
|
||||||
|
enum class Context {
|
||||||
|
Create,
|
||||||
|
Join,
|
||||||
|
Switch,
|
||||||
|
};
|
||||||
|
|
||||||
|
void start(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Context context,
|
||||||
|
Fn<void(not_null<PeerData*> peer, not_null<PeerData*> joinAs)> done);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ChannelsListRequest {
|
||||||
|
not_null<PeerData*> peer;
|
||||||
|
Fn<void(not_null<PeerData*>, not_null<PeerData*>)> done;
|
||||||
|
base::has_weak_ptr guard;
|
||||||
|
rpl::lifetime lifetime;
|
||||||
|
Context context = Context();
|
||||||
|
mtpRequestId id = 0;
|
||||||
|
};
|
||||||
|
std::unique_ptr<ChannelsListRequest> _request;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Calls
|
|
@ -103,10 +103,12 @@ 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,
|
not_null<PeerData*> peer,
|
||||||
const MTPInputGroupCall &inputCall)
|
const MTPInputGroupCall &inputCall,
|
||||||
|
not_null<PeerData*> joinAs)
|
||||||
: _delegate(delegate)
|
: _delegate(delegate)
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _history(peer->owner().history(peer))
|
, _history(peer->owner().history(peer))
|
||||||
|
, _joinAs(joinAs)
|
||||||
, _api(&peer->session().mtp())
|
, _api(&peer->session().mtp())
|
||||||
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
|
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
|
||||||
, _checkJoinedTimer([=] { checkJoined(); })
|
, _checkJoinedTimer([=] { checkJoined(); })
|
||||||
|
@ -244,9 +246,9 @@ void GroupCall::playConnectingSoundOnce() {
|
||||||
|
|
||||||
void GroupCall::start() {
|
void GroupCall::start() {
|
||||||
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
||||||
MTP_flags(0),
|
MTP_flags(MTPphone_CreateGroupCall::Flag::f_join_as),
|
||||||
_peer->input,
|
_peer->input,
|
||||||
MTPInputPeer(), // #TODO calls join_as
|
_joinAs->input,
|
||||||
MTP_int(openssl::RandomValue<int32>())
|
MTP_int(openssl::RandomValue<int32>())
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
_acceptFields = true;
|
_acceptFields = true;
|
||||||
|
@ -351,11 +353,12 @@ void GroupCall::rejoin() {
|
||||||
const auto wasMuteState = muted();
|
const auto wasMuteState = muted();
|
||||||
using Flag = MTPphone_JoinGroupCall::Flag;
|
using Flag = MTPphone_JoinGroupCall::Flag;
|
||||||
_api.request(MTPphone_JoinGroupCall(
|
_api.request(MTPphone_JoinGroupCall(
|
||||||
MTP_flags((wasMuteState != MuteState::Active)
|
MTP_flags(Flag::f_join_as
|
||||||
? Flag::f_muted
|
| (wasMuteState != MuteState::Active
|
||||||
: Flag(0)),
|
? Flag::f_muted
|
||||||
|
: Flag(0))),
|
||||||
inputCall(),
|
inputCall(),
|
||||||
MTPInputPeer(), // #TODO calls join_as
|
_joinAs->input,
|
||||||
MTP_dataJSON(MTP_bytes(json))
|
MTP_dataJSON(MTP_bytes(json))
|
||||||
)).done([=](const MTPUpdates &updates) {
|
)).done([=](const MTPUpdates &updates) {
|
||||||
_mySsrc = ssrc;
|
_mySsrc = ssrc;
|
||||||
|
|
|
@ -89,7 +89,8 @@ public:
|
||||||
GroupCall(
|
GroupCall(
|
||||||
not_null<Delegate*> delegate,
|
not_null<Delegate*> delegate,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const MTPInputGroupCall &inputCall);
|
const MTPInputGroupCall &inputCall,
|
||||||
|
not_null<PeerData*> joinAs);
|
||||||
~GroupCall();
|
~GroupCall();
|
||||||
|
|
||||||
[[nodiscard]] uint64 id() const {
|
[[nodiscard]] uint64 id() const {
|
||||||
|
@ -207,6 +208,7 @@ 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;
|
||||||
|
|
|
@ -1346,21 +1346,26 @@ base::unique_qptr<Ui::PopupMenu> MembersController::createRowContextMenu(
|
||||||
result->addAction(
|
result->addAction(
|
||||||
tr::lng_context_view_profile(tr::now),
|
tr::lng_context_view_profile(tr::now),
|
||||||
showProfile);
|
showProfile);
|
||||||
result->addAction(
|
if (participantPeer->isUser()) {
|
||||||
tr::lng_context_send_message(tr::now),
|
result->addAction(
|
||||||
showHistory);
|
tr::lng_context_send_message(tr::now),
|
||||||
|
showHistory);
|
||||||
|
}
|
||||||
const auto canKick = [&] {
|
const auto canKick = [&] {
|
||||||
const auto user = participantPeer->asUser();
|
const auto user = participantPeer->asUser();
|
||||||
|
if (!user) {
|
||||||
|
return false; // #TODO calls can kick
|
||||||
|
}
|
||||||
if (static_cast<Row*>(row.get())->state() == Row::State::Invited) {
|
if (static_cast<Row*>(row.get())->state() == Row::State::Invited) {
|
||||||
return false;
|
return false;
|
||||||
} else if (const auto chat = _peer->asChat()) {
|
} else if (const auto chat = _peer->asChat()) {
|
||||||
return chat->amCreator()
|
return chat->amCreator()
|
||||||
|| (user
|
|| (user
|
||||||
&& chat->canBanMembers()
|
&& chat->canBanMembers()
|
||||||
&& !chat->admins.contains(user)); // #TODO calls can kick
|
&& !chat->admins.contains(user));
|
||||||
} else if (const auto group = _peer->asMegagroup()) {
|
} else if (const auto group = _peer->asMegagroup()) {
|
||||||
return group->amCreator()
|
return group->amCreator()
|
||||||
|| (user && group->canRestrictUser(user)); // #TODO calls can kick
|
|| (user && group->canRestrictUser(user));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -60,12 +60,26 @@ 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()
|
||||||
|
? ChooseJoinAsProcess::Context::Join
|
||||||
|
: ChooseJoinAsProcess::Context::Create;
|
||||||
|
_chooseJoinAs.start(peer, context, [=](
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
not_null<PeerData*> joinAs) {
|
||||||
|
startOrJoinGroupCall(peer, joinAs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Instance::startOrJoinGroupCall(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
not_null<PeerData*> joinAs) {
|
||||||
destroyCurrentCall();
|
destroyCurrentCall();
|
||||||
|
|
||||||
const auto call = peer->groupCall();
|
const auto call = peer->groupCall();
|
||||||
createGroupCall(
|
createGroupCall(
|
||||||
peer,
|
peer,
|
||||||
call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()));
|
call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()),
|
||||||
|
joinAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::callFinished(not_null<Call*> call) {
|
void Instance::callFinished(not_null<Call*> call) {
|
||||||
|
@ -195,13 +209,15 @@ void Instance::destroyGroupCall(not_null<GroupCall*> call) {
|
||||||
|
|
||||||
void Instance::createGroupCall(
|
void Instance::createGroupCall(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
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,
|
peer,
|
||||||
inputCall);
|
inputCall,
|
||||||
|
joinAs);
|
||||||
const auto raw = call.get();
|
const auto raw = call.get();
|
||||||
|
|
||||||
peer->session().account().sessionChanges(
|
peer->session().account().sessionChanges(
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "calls/calls_call.h"
|
#include "calls/calls_call.h"
|
||||||
#include "calls/calls_group_call.h"
|
#include "calls/calls_group_call.h"
|
||||||
|
#include "calls/calls_choose_join_as.h"
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
enum class PermissionType;
|
enum class PermissionType;
|
||||||
|
@ -41,6 +42,9 @@ 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);
|
||||||
|
@ -104,7 +108,8 @@ private:
|
||||||
|
|
||||||
void createGroupCall(
|
void createGroupCall(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
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(
|
||||||
|
@ -145,6 +150,8 @@ 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Calls
|
} // namespace Calls
|
||||||
|
|
|
@ -713,6 +713,14 @@ void ChannelData::clearGroupCall() {
|
||||||
| MTPDchannel::Flag::f_call_not_empty);
|
| MTPDchannel::Flag::f_call_not_empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelData::setGroupCallDefaultJoinAs(PeerId peerId) {
|
||||||
|
_callDefaultJoinAs = peerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerId ChannelData::groupCallDefaultJoinAs() const {
|
||||||
|
return _callDefaultJoinAs;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
void ApplyMigration(
|
void ApplyMigration(
|
||||||
|
@ -759,6 +767,11 @@ void ApplyChannelUpdate(
|
||||||
} else {
|
} else {
|
||||||
channel->clearGroupCall();
|
channel->clearGroupCall();
|
||||||
}
|
}
|
||||||
|
if (const auto as = update.vgroupcall_default_join_as()) {
|
||||||
|
channel->setGroupCallDefaultJoinAs(peerFromMTP(*as));
|
||||||
|
} else {
|
||||||
|
channel->setGroupCallDefaultJoinAs(0);
|
||||||
|
}
|
||||||
|
|
||||||
channel->setMessagesTTL(update.vttl_period().value_or_empty());
|
channel->setMessagesTTL(update.vttl_period().value_or_empty());
|
||||||
channel->setFullFlags(update.vflags().v);
|
channel->setFullFlags(update.vflags().v);
|
||||||
|
|
|
@ -410,6 +410,8 @@ public:
|
||||||
void migrateCall(std::unique_ptr<Data::GroupCall> call);
|
void migrateCall(std::unique_ptr<Data::GroupCall> call);
|
||||||
void setGroupCall(const MTPInputGroupCall &call);
|
void setGroupCall(const MTPInputGroupCall &call);
|
||||||
void clearGroupCall();
|
void clearGroupCall();
|
||||||
|
void setGroupCallDefaultJoinAs(PeerId peerId);
|
||||||
|
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
|
||||||
|
|
||||||
// Still public data members.
|
// Still public data members.
|
||||||
uint64 access = 0;
|
uint64 access = 0;
|
||||||
|
@ -458,6 +460,7 @@ private:
|
||||||
std::optional<ChannelData*> _linkedChat;
|
std::optional<ChannelData*> _linkedChat;
|
||||||
|
|
||||||
std::unique_ptr<Data::GroupCall> _call;
|
std::unique_ptr<Data::GroupCall> _call;
|
||||||
|
PeerId _callDefaultJoinAs = 0;
|
||||||
|
|
||||||
int _slowmodeSeconds = 0;
|
int _slowmodeSeconds = 0;
|
||||||
TimeId _slowmodeLastMessage = 0;
|
TimeId _slowmodeLastMessage = 0;
|
||||||
|
|
|
@ -237,6 +237,14 @@ void ChatData::clearGroupCall() {
|
||||||
| MTPDchat::Flag::f_call_not_empty);
|
| MTPDchat::Flag::f_call_not_empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatData::setGroupCallDefaultJoinAs(PeerId peerId) {
|
||||||
|
_callDefaultJoinAs = peerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerId ChatData::groupCallDefaultJoinAs() const {
|
||||||
|
return _callDefaultJoinAs;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
void ApplyChatUpdate(
|
void ApplyChatUpdate(
|
||||||
|
@ -376,6 +384,11 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
|
||||||
} else {
|
} else {
|
||||||
chat->clearGroupCall();
|
chat->clearGroupCall();
|
||||||
}
|
}
|
||||||
|
if (const auto as = update.vgroupcall_default_join_as()) {
|
||||||
|
chat->setGroupCallDefaultJoinAs(peerFromMTP(*as));
|
||||||
|
} else {
|
||||||
|
chat->setGroupCallDefaultJoinAs(0);
|
||||||
|
}
|
||||||
|
|
||||||
chat->setMessagesTTL(update.vttl_period().value_or_empty());
|
chat->setMessagesTTL(update.vttl_period().value_or_empty());
|
||||||
if (const auto info = update.vbot_info()) {
|
if (const auto info = update.vbot_info()) {
|
||||||
|
|
|
@ -170,6 +170,8 @@ public:
|
||||||
}
|
}
|
||||||
void setGroupCall(const MTPInputGroupCall &call);
|
void setGroupCall(const MTPInputGroupCall &call);
|
||||||
void clearGroupCall();
|
void clearGroupCall();
|
||||||
|
void setGroupCallDefaultJoinAs(PeerId peerId);
|
||||||
|
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
|
||||||
|
|
||||||
// Still public data members.
|
// Still public data members.
|
||||||
const MTPint inputChat;
|
const MTPint inputChat;
|
||||||
|
@ -195,6 +197,7 @@ private:
|
||||||
int _version = 0;
|
int _version = 0;
|
||||||
|
|
||||||
std::unique_ptr<Data::GroupCall> _call;
|
std::unique_ptr<Data::GroupCall> _call;
|
||||||
|
PeerId _callDefaultJoinAs = 0;
|
||||||
|
|
||||||
ChannelData *_migratedTo = nullptr;
|
ChannelData *_migratedTo = nullptr;
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
|
@ -920,6 +920,15 @@ Data::GroupCall *PeerData::groupCall() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeerId PeerData::groupCallDefaultJoinAs() const {
|
||||||
|
if (const auto chat = asChat()) {
|
||||||
|
return chat->groupCallDefaultJoinAs();
|
||||||
|
} else if (const auto group = asMegagroup()) {
|
||||||
|
return group->groupCallDefaultJoinAs();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PeerData::setIsBlocked(bool is) {
|
void PeerData::setIsBlocked(bool is) {
|
||||||
const auto status = is
|
const auto status = is
|
||||||
? BlockStatus::Blocked
|
? BlockStatus::Blocked
|
||||||
|
|
|
@ -386,6 +386,7 @@ public:
|
||||||
void setMessagesTTL(TimeId period);
|
void setMessagesTTL(TimeId period);
|
||||||
|
|
||||||
[[nodiscard]] Data::GroupCall *groupCall() const;
|
[[nodiscard]] Data::GroupCall *groupCall() const;
|
||||||
|
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
|
||||||
|
|
||||||
const PeerId id;
|
const PeerId id;
|
||||||
QString name;
|
QString name;
|
||||||
|
|
|
@ -949,7 +949,8 @@ void SessionController::startOrJoinGroupCall(
|
||||||
})));
|
})));
|
||||||
};
|
};
|
||||||
if (!confirmedLeaveOther && calls.inCall()) {
|
if (!confirmedLeaveOther && calls.inCall()) {
|
||||||
// Do you want to leave your active voice chat to join a voice chat in this group?
|
// Do you want to leave your active voice chat
|
||||||
|
// to join a voice chat in this group?
|
||||||
confirm(
|
confirm(
|
||||||
tr::lng_call_leave_to_other_sure(tr::now),
|
tr::lng_call_leave_to_other_sure(tr::now),
|
||||||
tr::lng_call_bar_hangup(tr::now));
|
tr::lng_call_bar_hangup(tr::now));
|
||||||
|
@ -961,10 +962,6 @@ void SessionController::startOrJoinGroupCall(
|
||||||
tr::lng_group_call_leave_to_other_sure(tr::now),
|
tr::lng_group_call_leave_to_other_sure(tr::now),
|
||||||
tr::lng_group_call_leave(tr::now));
|
tr::lng_group_call_leave(tr::now));
|
||||||
}
|
}
|
||||||
} else if (!confirmedLeaveOther && !peer->groupCall()) {
|
|
||||||
confirm(
|
|
||||||
tr::lng_group_call_create_sure(tr::now),
|
|
||||||
tr::lng_continue(tr::now));
|
|
||||||
} else {
|
} else {
|
||||||
calls.startOrJoinGroupCall(peer);
|
calls.startOrJoinGroupCall(peer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue