mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 14:38:15 +00:00
Add creating of a scheduled group call.
This commit is contained in:
@@ -18,15 +18,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "lang/lang_keys.h"
|
||||
#include "apiwrap.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/boxes/choose_date_time.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "boxes/peer_list_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/timer_rpl.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_calls.h"
|
||||
|
||||
namespace Calls::Group {
|
||||
namespace {
|
||||
|
||||
constexpr auto kDefaultScheduleDuration = 60 * TimeId(60);
|
||||
constexpr auto kLabelRefreshInterval = 10 * crl::time(1000);
|
||||
|
||||
using Context = ChooseJoinAsProcess::Context;
|
||||
|
||||
class ListController : public PeerListController {
|
||||
@@ -109,6 +115,60 @@ not_null<PeerData*> ListController::selected() const {
|
||||
return _selected;
|
||||
}
|
||||
|
||||
void ScheduleGroupCallBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
const JoinInfo &info,
|
||||
Fn<void(JoinInfo)> done) {
|
||||
const auto send = [=](TimeId date) {
|
||||
box->closeBox();
|
||||
|
||||
auto copy = info;
|
||||
copy.scheduleDate = date;
|
||||
done(std::move(copy));
|
||||
};
|
||||
const auto duration = box->lifetime().make_state<
|
||||
rpl::variable<QString>>();
|
||||
auto description = (info.peer->isBroadcast()
|
||||
? tr::lng_group_call_schedule_notified_channel
|
||||
: tr::lng_group_call_schedule_notified_group)(
|
||||
lt_duration,
|
||||
duration->value());
|
||||
auto descriptor = Ui::ChooseDateTimeBox(
|
||||
box,
|
||||
tr::lng_group_call_schedule_title(),
|
||||
tr::lng_schedule_button(),
|
||||
send,
|
||||
base::unixtime::now() + kDefaultScheduleDuration,
|
||||
std::move(description));
|
||||
|
||||
using namespace rpl::mappers;
|
||||
*duration = rpl::combine(
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(base::timer_each(kLabelRefreshInterval)),
|
||||
std::move(descriptor.values) | rpl::filter(_1 != 0),
|
||||
_2
|
||||
) | rpl::map([](TimeId date) {
|
||||
const auto now = base::unixtime::now();
|
||||
const auto duration = (date - now);
|
||||
if (duration >= 24 * 60 * 60) {
|
||||
return tr::lng_signin_reset_days(
|
||||
tr::now,
|
||||
lt_count,
|
||||
duration / (24 * 60 * 60));
|
||||
} else if (duration >= 60 * 60) {
|
||||
return tr::lng_signin_reset_hours(
|
||||
tr::now,
|
||||
lt_count,
|
||||
duration / (60 * 60));
|
||||
}
|
||||
return tr::lng_signin_reset_minutes(
|
||||
tr::now,
|
||||
lt_count,
|
||||
std::max(duration / 60, 1));
|
||||
});
|
||||
}
|
||||
|
||||
void ChooseJoinAsBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
Context context,
|
||||
@@ -124,12 +184,13 @@ void ChooseJoinAsBox(
|
||||
}
|
||||
Unexpected("Context in ChooseJoinAsBox.");
|
||||
}());
|
||||
const auto &labelSt = (context == Context::Switch)
|
||||
? st::groupCallJoinAsLabel
|
||||
: st::confirmPhoneAboutLabel;
|
||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
tr::lng_group_call_join_as_about(),
|
||||
(context == Context::Switch
|
||||
? st::groupCallJoinAsLabel
|
||||
: st::confirmPhoneAboutLabel)));
|
||||
labelSt));
|
||||
|
||||
auto &lifetime = box->lifetime();
|
||||
const auto delegate = lifetime.make_state<
|
||||
@@ -155,6 +216,27 @@ void ChooseJoinAsBox(
|
||||
auto next = (context == Context::Switch)
|
||||
? tr::lng_settings_save()
|
||||
: tr::lng_continue();
|
||||
if (context == Context::Create) {
|
||||
const auto makeLink = [](const QString &text) {
|
||||
return Ui::Text::Link(text);
|
||||
};
|
||||
const auto label = box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
tr::lng_group_call_or_schedule(
|
||||
lt_link,
|
||||
tr::lng_group_call_schedule(makeLink),
|
||||
Ui::Text::WithEntities),
|
||||
labelSt));
|
||||
label->setClickHandlerFilter([=](const auto&...) {
|
||||
auto withJoinAs = info;
|
||||
withJoinAs.joinAs = controller->selected();
|
||||
box->getDelegate()->show(Box(
|
||||
ScheduleGroupCallBox,
|
||||
withJoinAs,
|
||||
done));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
box->addButton(std::move(next), [=] {
|
||||
auto copy = info;
|
||||
copy.joinAs = controller->selected();
|
||||
|
@@ -184,6 +184,7 @@ GroupCall::GroupCall(
|
||||
, _joinAs(info.joinAs)
|
||||
, _possibleJoinAs(std::move(info.possibleJoinAs))
|
||||
, _joinHash(info.joinHash)
|
||||
, _scheduleDate(info.scheduleDate)
|
||||
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
|
||||
, _checkJoinedTimer([=] { checkJoined(); })
|
||||
, _pushToTalkCancelTimer([=] { pushToTalkCancel(); })
|
||||
@@ -218,14 +219,14 @@ GroupCall::GroupCall(
|
||||
const auto id = inputCall.c_inputGroupCall().vid().v;
|
||||
if (id) {
|
||||
if (const auto call = _peer->groupCall(); call && call->id() == id) {
|
||||
_scheduleDate = call->scheduleDate();
|
||||
if (!_peer->canManageGroupCall() && call->joinMuted()) {
|
||||
_muted = MuteState::ForceMuted;
|
||||
}
|
||||
}
|
||||
_state = State::Joining;
|
||||
join(inputCall);
|
||||
} else {
|
||||
start();
|
||||
start(info.scheduleDate);
|
||||
}
|
||||
|
||||
_mediaDevices->audioInputId(
|
||||
@@ -326,13 +327,14 @@ bool GroupCall::showChooseJoinAs() const {
|
||||
&& !_possibleJoinAs.front()->isSelf());
|
||||
}
|
||||
|
||||
void GroupCall::start() {
|
||||
void GroupCall::start(TimeId scheduleDate) {
|
||||
using Flag = MTPphone_CreateGroupCall::Flag;
|
||||
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
||||
MTP_flags(0),
|
||||
MTP_flags(scheduleDate ? Flag::f_schedule_date : Flag(0)),
|
||||
_peer->input,
|
||||
MTP_int(openssl::RandomValue<int32>()),
|
||||
MTPstring(), // title
|
||||
MTPint() // schedule_date
|
||||
MTP_int(scheduleDate)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_acceptFields = true;
|
||||
_peer->session().api().applyUpdates(result);
|
||||
@@ -350,6 +352,15 @@ void GroupCall::start() {
|
||||
}
|
||||
|
||||
void GroupCall::join(const MTPInputGroupCall &inputCall) {
|
||||
inputCall.match([&](const MTPDinputGroupCall &data) {
|
||||
_id = data.vid().v;
|
||||
_accessHash = data.vaccess_hash().v;
|
||||
});
|
||||
if (_scheduleDate) {
|
||||
setState(State::Waiting);
|
||||
return;
|
||||
}
|
||||
|
||||
setState(State::Joining);
|
||||
if (const auto chat = _peer->asChat()) {
|
||||
chat->setGroupCall(inputCall);
|
||||
@@ -358,12 +369,7 @@ void GroupCall::join(const MTPInputGroupCall &inputCall) {
|
||||
} else {
|
||||
Unexpected("Peer type in GroupCall::join.");
|
||||
}
|
||||
|
||||
inputCall.match([&](const MTPDinputGroupCall &data) {
|
||||
_id = data.vid().v;
|
||||
_accessHash = data.vaccess_hash().v;
|
||||
rejoin();
|
||||
});
|
||||
rejoin();
|
||||
|
||||
using Update = Data::GroupCall::ParticipantUpdate;
|
||||
_peer->groupCall()->participantUpdated(
|
||||
@@ -646,8 +652,10 @@ void GroupCall::rejoinAs(Group::JoinInfo info) {
|
||||
.wasJoinAs = _joinAs,
|
||||
.nowJoinAs = info.joinAs,
|
||||
};
|
||||
setState(State::Joining);
|
||||
rejoin(info.joinAs);
|
||||
if (!_scheduleDate) {
|
||||
setState(State::Joining);
|
||||
rejoin(info.joinAs);
|
||||
}
|
||||
_rejoinEvents.fire_copy(event);
|
||||
}
|
||||
|
||||
@@ -734,6 +742,9 @@ void GroupCall::handlePossibleCreateOrJoinResponse(
|
||||
|
||||
void GroupCall::handlePossibleCreateOrJoinResponse(
|
||||
const MTPDgroupCall &data) {
|
||||
if (const auto date = data.vschedule_date()) {
|
||||
_scheduleDate = date->v;
|
||||
}
|
||||
if (_acceptFields) {
|
||||
if (!_instance && !_id) {
|
||||
join(MTP_inputGroupCall(data.vid(), data.vaccess_hash()));
|
||||
|
@@ -109,8 +109,11 @@ public:
|
||||
return _joinAs;
|
||||
}
|
||||
[[nodiscard]] bool showChooseJoinAs() const;
|
||||
[[nodiscard]] TimeId scheduleDate() const {
|
||||
return _scheduleDate;
|
||||
}
|
||||
|
||||
void start();
|
||||
void start(TimeId scheduleDate);
|
||||
void hangup();
|
||||
void discard();
|
||||
void rejoinAs(Group::JoinInfo info);
|
||||
@@ -138,6 +141,7 @@ public:
|
||||
|
||||
enum State {
|
||||
Creating,
|
||||
Waiting,
|
||||
Joining,
|
||||
Connecting,
|
||||
Joined,
|
||||
@@ -310,6 +314,7 @@ private:
|
||||
uint64 _id = 0;
|
||||
uint64 _accessHash = 0;
|
||||
uint32 _mySsrc = 0;
|
||||
TimeId _scheduleDate = 0;
|
||||
base::flat_set<uint32> _mySsrcs;
|
||||
mtpRequestId _createRequestId = 0;
|
||||
mtpRequestId _updateMuteRequestId = 0;
|
||||
|
@@ -44,6 +44,7 @@ struct JoinInfo {
|
||||
not_null<PeerData*> joinAs;
|
||||
std::vector<not_null<PeerData*>> possibleJoinAs;
|
||||
QString joinHash;
|
||||
TimeId scheduleDate = 0;
|
||||
};
|
||||
|
||||
} // namespace Calls::Group
|
||||
|
@@ -259,7 +259,7 @@ Panel::Panel(not_null<GroupCall*> call)
|
||||
_window->body(),
|
||||
st::groupCallTitle))
|
||||
#endif // !Q_OS_MAC
|
||||
, _members(widget(), call)
|
||||
, _scheduleDate(call->scheduleDate())
|
||||
, _settings(widget(), st::groupCallSettings)
|
||||
, _mute(std::make_unique<Ui::CallMuteButton>(
|
||||
widget(),
|
||||
@@ -286,30 +286,7 @@ Panel::Panel(not_null<GroupCall*> call)
|
||||
showAndActivate();
|
||||
setupJoinAsChangedToasts();
|
||||
setupTitleChangedToasts();
|
||||
|
||||
call->allowedToSpeakNotifications(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (isActive()) {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = widget(),
|
||||
.text = { tr::lng_group_call_can_speak_here(tr::now) },
|
||||
});
|
||||
} else {
|
||||
const auto real = _peer->groupCall();
|
||||
const auto name = (real
|
||||
&& (real->id() == call->id())
|
||||
&& !real->title().isEmpty())
|
||||
? real->title()
|
||||
: _peer->name;
|
||||
Ui::ShowMultilineToast({
|
||||
.text = tr::lng_group_call_can_speak(
|
||||
tr::now,
|
||||
lt_chat,
|
||||
Ui::Text::Bold(name),
|
||||
Ui::Text::WithEntities),
|
||||
});
|
||||
}
|
||||
}, widget()->lifetime());
|
||||
setupAllowedToSpeakToasts();
|
||||
}
|
||||
|
||||
Panel::~Panel() {
|
||||
@@ -326,7 +303,7 @@ void Panel::setupRealCallViewers(not_null<GroupCall*> call) {
|
||||
) | rpl::map([=] {
|
||||
return peer->groupCall();
|
||||
}) | rpl::filter([=](Data::GroupCall *real) {
|
||||
return _call && real && (real->id() == _call->id());
|
||||
return real && (real->id() == _call->id());
|
||||
}) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=](not_null<Data::GroupCall*> real) {
|
||||
@@ -393,11 +370,9 @@ void Panel::initWindow() {
|
||||
} else if (e->type() == QEvent::KeyPress
|
||||
|| e->type() == QEvent::KeyRelease) {
|
||||
if (static_cast<QKeyEvent*>(e.get())->key() == Qt::Key_Space) {
|
||||
if (_call) {
|
||||
_call->pushToTalk(
|
||||
e->type() == QEvent::KeyPress,
|
||||
kSpacePushToTalkDelay);
|
||||
}
|
||||
_call->pushToTalk(
|
||||
e->type() == QEvent::KeyPress,
|
||||
kSpacePushToTalkDelay);
|
||||
}
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
@@ -439,9 +414,7 @@ void Panel::initWidget() {
|
||||
}
|
||||
|
||||
void Panel::endCall() {
|
||||
if (!_call) {
|
||||
return;
|
||||
} else if (!_call->peer()->canManageGroupCall()) {
|
||||
if (!_call->peer()->canManageGroupCall()) {
|
||||
_call->hangup();
|
||||
return;
|
||||
}
|
||||
@@ -455,7 +428,7 @@ void Panel::endCall() {
|
||||
void Panel::initControls() {
|
||||
_mute->clicks(
|
||||
) | rpl::filter([=](Qt::MouseButton button) {
|
||||
return (button == Qt::LeftButton) && (_call != nullptr);
|
||||
return (button == Qt::LeftButton);
|
||||
}) | rpl::start_with_next([=] {
|
||||
const auto oldState = _call->muted();
|
||||
const auto newState = (oldState == MuteState::ForceMuted)
|
||||
@@ -470,32 +443,17 @@ void Panel::initControls() {
|
||||
|
||||
_hangup->setClickedCallback([=] { endCall(); });
|
||||
_settings->setClickedCallback([=] {
|
||||
if (_call) {
|
||||
_layerBg->showBox(Box(SettingsBox, _call));
|
||||
}
|
||||
_layerBg->showBox(Box(SettingsBox, _call));
|
||||
});
|
||||
|
||||
_settings->setText(tr::lng_group_call_settings());
|
||||
_hangup->setText(tr::lng_group_call_leave());
|
||||
|
||||
_members->desiredHeightValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateControlsGeometry();
|
||||
}, _members->lifetime());
|
||||
|
||||
initWithCall(_call);
|
||||
}
|
||||
|
||||
void Panel::initWithCall(GroupCall *call) {
|
||||
_callLifetime.destroy();
|
||||
_call = call;
|
||||
if (!_call) {
|
||||
return;
|
||||
if (!_call->scheduleDate()) {
|
||||
setupMembers();
|
||||
}
|
||||
|
||||
_peer = _call->peer();
|
||||
|
||||
call->stateValue(
|
||||
_call->stateValue(
|
||||
) | rpl::filter([](State state) {
|
||||
return (state == State::HangingUp)
|
||||
|| (state == State::Ended)
|
||||
@@ -505,59 +463,13 @@ void Panel::initWithCall(GroupCall *call) {
|
||||
closeBeforeDestroy();
|
||||
}, _callLifetime);
|
||||
|
||||
call->levelUpdates(
|
||||
_call->levelUpdates(
|
||||
) | rpl::filter([=](const LevelUpdate &update) {
|
||||
return update.me;
|
||||
}) | rpl::start_with_next([=](const LevelUpdate &update) {
|
||||
_mute->setLevel(update.value);
|
||||
}, _callLifetime);
|
||||
|
||||
_members->toggleMuteRequests(
|
||||
) | rpl::start_with_next([=](MuteRequest request) {
|
||||
if (_call) {
|
||||
_call->toggleMute(request);
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
_members->changeVolumeRequests(
|
||||
) | rpl::start_with_next([=](VolumeRequest request) {
|
||||
if (_call) {
|
||||
_call->changeVolume(request);
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
_members->kickParticipantRequests(
|
||||
) | rpl::start_with_next([=](not_null<PeerData*> participantPeer) {
|
||||
kickParticipant(participantPeer);
|
||||
}, _callLifetime);
|
||||
|
||||
const auto showBox = [=](object_ptr<Ui::BoxContent> next) {
|
||||
_layerBg->showBox(std::move(next));
|
||||
};
|
||||
const auto showToast = [=](QString text) {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = widget(),
|
||||
.text = { text },
|
||||
});
|
||||
};
|
||||
auto [shareLinkCallback, shareLinkLifetime] = ShareInviteLinkAction(
|
||||
_peer,
|
||||
showBox,
|
||||
showToast);
|
||||
auto shareLink = std::move(shareLinkCallback);
|
||||
_members->lifetime().add(std::move(shareLinkLifetime));
|
||||
|
||||
_members->addMembersRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (_call) {
|
||||
if (_peer->isBroadcast() && _peer->asChannel()->hasUsername()) {
|
||||
shareLink();
|
||||
} else {
|
||||
addMembers();
|
||||
}
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
using namespace rpl::mappers;
|
||||
rpl::combine(
|
||||
_call->mutedValue() | MapPushToTalkToActive(),
|
||||
@@ -600,6 +512,61 @@ void Panel::initWithCall(GroupCall *call) {
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
void Panel::setupMembers() {
|
||||
Expects(!_members);
|
||||
|
||||
_members.create(widget(), _call);
|
||||
|
||||
_members->desiredHeightValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateMembersGeometry();
|
||||
}, _members->lifetime());
|
||||
|
||||
_members->toggleMuteRequests(
|
||||
) | rpl::start_with_next([=](MuteRequest request) {
|
||||
if (_call) {
|
||||
_call->toggleMute(request);
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
_members->changeVolumeRequests(
|
||||
) | rpl::start_with_next([=](VolumeRequest request) {
|
||||
if (_call) {
|
||||
_call->changeVolume(request);
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
_members->kickParticipantRequests(
|
||||
) | rpl::start_with_next([=](not_null<PeerData*> participantPeer) {
|
||||
kickParticipant(participantPeer);
|
||||
}, _callLifetime);
|
||||
|
||||
const auto showBox = [=](object_ptr<Ui::BoxContent> next) {
|
||||
_layerBg->showBox(std::move(next));
|
||||
};
|
||||
const auto showToast = [=](QString text) {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = widget(),
|
||||
.text = { text },
|
||||
});
|
||||
};
|
||||
auto [shareLinkCallback, shareLinkLifetime] = ShareInviteLinkAction(
|
||||
_peer,
|
||||
showBox,
|
||||
showToast);
|
||||
auto shareLink = std::move(shareLinkCallback);
|
||||
_members->lifetime().add(std::move(shareLinkLifetime));
|
||||
|
||||
_members->addMembersRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (_peer->isBroadcast() && _peer->asChannel()->hasUsername()) {
|
||||
shareLink();
|
||||
} else {
|
||||
addMembers();
|
||||
}
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
void Panel::setupJoinAsChangedToasts() {
|
||||
_call->rejoinEvents(
|
||||
) | rpl::filter([](RejoinEvent event) {
|
||||
@@ -623,7 +590,8 @@ void Panel::setupJoinAsChangedToasts() {
|
||||
void Panel::setupTitleChangedToasts() {
|
||||
_call->titleChanged(
|
||||
) | rpl::filter([=] {
|
||||
return _peer->groupCall() && _peer->groupCall()->id() == _call->id();
|
||||
const auto real = _peer->groupCall();
|
||||
return real && (real->id() == _call->id());
|
||||
}) | rpl::map([=] {
|
||||
return _peer->groupCall()->title().isEmpty()
|
||||
? _peer->name
|
||||
@@ -640,8 +608,44 @@ void Panel::setupTitleChangedToasts() {
|
||||
}, widget()->lifetime());
|
||||
}
|
||||
|
||||
void Panel::setupAllowedToSpeakToasts() {
|
||||
_call->allowedToSpeakNotifications(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (isActive()) {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = widget(),
|
||||
.text = { tr::lng_group_call_can_speak_here(tr::now) },
|
||||
});
|
||||
} else {
|
||||
const auto real = _peer->groupCall();
|
||||
const auto name = (real
|
||||
&& (real->id() == _call->id())
|
||||
&& !real->title().isEmpty())
|
||||
? real->title()
|
||||
: _peer->name;
|
||||
Ui::ShowMultilineToast({
|
||||
.text = tr::lng_group_call_can_speak(
|
||||
tr::now,
|
||||
lt_chat,
|
||||
Ui::Text::Bold(name),
|
||||
Ui::Text::WithEntities),
|
||||
});
|
||||
}
|
||||
}, widget()->lifetime());
|
||||
}
|
||||
|
||||
void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||
if (!_members) {
|
||||
real->scheduleDateValue(
|
||||
) | rpl::filter([=](TimeId scheduleDate) {
|
||||
return !scheduleDate;
|
||||
}) | rpl::take(1) | rpl::start_with_next([=] {
|
||||
setupMembers();
|
||||
}, _callLifetime);
|
||||
}
|
||||
|
||||
_titleText = real->titleValue();
|
||||
_scheduleDate = real->scheduleDateValue();
|
||||
|
||||
const auto validateRecordingMark = [=](bool recording) {
|
||||
if (!recording && _recordingMark) {
|
||||
@@ -702,7 +706,7 @@ void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||
.parentOverride = widget(),
|
||||
.text = (recorded
|
||||
? tr::lng_group_call_recording_started
|
||||
: (_call && _call->recordingStoppedByMe())
|
||||
: _call->recordingStoppedByMe()
|
||||
? tr::lng_group_call_recording_saved
|
||||
: tr::lng_group_call_recording_stopped)(
|
||||
tr::now,
|
||||
@@ -751,9 +755,7 @@ void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||
void Panel::chooseJoinAs() {
|
||||
const auto context = ChooseJoinAsProcess::Context::Switch;
|
||||
const auto callback = [=](JoinInfo info) {
|
||||
if (_call) {
|
||||
_call->rejoinAs(info);
|
||||
}
|
||||
_call->rejoinAs(info);
|
||||
};
|
||||
const auto showBox = [=](object_ptr<Ui::BoxContent> next) {
|
||||
_layerBg->showBox(std::move(next));
|
||||
@@ -774,7 +776,7 @@ void Panel::chooseJoinAs() {
|
||||
}
|
||||
|
||||
void Panel::showMainMenu() {
|
||||
if (_menu || !_call) {
|
||||
if (_menu) {
|
||||
return;
|
||||
}
|
||||
_menu.create(widget(), st::groupCallDropdownMenu);
|
||||
@@ -822,7 +824,7 @@ void Panel::showMainMenu() {
|
||||
|
||||
void Panel::addMembers() {
|
||||
const auto real = _peer->groupCall();
|
||||
if (!_call || !real || real->id() != _call->id()) {
|
||||
if (!real || real->id() != _call->id()) {
|
||||
return;
|
||||
}
|
||||
auto alreadyIn = _peer->owner().invitedToCallUsers(real->id());
|
||||
@@ -848,7 +850,7 @@ void Panel::addMembers() {
|
||||
&st::groupCallInviteMembersList,
|
||||
&st::groupCallMultiSelect);
|
||||
|
||||
const auto weak = base::make_weak(_call);
|
||||
const auto weak = base::make_weak(_call.get());
|
||||
const auto invite = [=](const std::vector<not_null<UserData*>> &users) {
|
||||
const auto call = weak.get();
|
||||
if (!call) {
|
||||
@@ -1031,7 +1033,7 @@ void Panel::showControls() {
|
||||
|
||||
void Panel::closeBeforeDestroy() {
|
||||
_window->close();
|
||||
initWithCall(nullptr);
|
||||
_callLifetime.destroy();
|
||||
}
|
||||
|
||||
void Panel::initGeometry() {
|
||||
@@ -1066,28 +1068,8 @@ void Panel::updateControlsGeometry() {
|
||||
if (widget()->size().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const auto desiredHeight = _members->desiredHeight();
|
||||
const auto membersWidthAvailable = widget()->width()
|
||||
- st::groupCallMembersMargin.left()
|
||||
- st::groupCallMembersMargin.right();
|
||||
const auto membersWidthMin = st::groupCallWidth
|
||||
- st::groupCallMembersMargin.left()
|
||||
- st::groupCallMembersMargin.right();
|
||||
const auto membersWidth = std::clamp(
|
||||
membersWidthAvailable,
|
||||
membersWidthMin,
|
||||
st::groupCallMembersWidthMax);
|
||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||
const auto buttonsTop = widget()->height() - st::groupCallButtonBottomSkip;
|
||||
const auto membersTop = st::groupCallMembersTop;
|
||||
const auto availableHeight = muteTop
|
||||
- membersTop
|
||||
- st::groupCallMembersMargin.bottom();
|
||||
_members->setGeometry(
|
||||
(widget()->width() - membersWidth) / 2,
|
||||
membersTop,
|
||||
membersWidth,
|
||||
std::min(desiredHeight, availableHeight));
|
||||
const auto muteSize = _mute->innerSize().width();
|
||||
const auto fullWidth = muteSize
|
||||
+ 2 * _settings->width()
|
||||
@@ -1095,6 +1077,8 @@ void Panel::updateControlsGeometry() {
|
||||
_mute->moveInner({ (widget()->width() - muteSize) / 2, muteTop });
|
||||
_settings->moveToLeft((widget()->width() - fullWidth) / 2, buttonsTop);
|
||||
_hangup->moveToRight((widget()->width() - fullWidth) / 2, buttonsTop);
|
||||
|
||||
updateMembersGeometry();
|
||||
refreshTitle();
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
@@ -1120,6 +1104,33 @@ void Panel::updateControlsGeometry() {
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::updateMembersGeometry() {
|
||||
if (!_members) {
|
||||
return;
|
||||
}
|
||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||
const auto membersTop = st::groupCallMembersTop;
|
||||
const auto availableHeight = muteTop
|
||||
- membersTop
|
||||
- st::groupCallMembersMargin.bottom();
|
||||
const auto desiredHeight = _members->desiredHeight();
|
||||
const auto membersWidthAvailable = widget()->width()
|
||||
- st::groupCallMembersMargin.left()
|
||||
- st::groupCallMembersMargin.right();
|
||||
const auto membersWidthMin = st::groupCallWidth
|
||||
- st::groupCallMembersMargin.left()
|
||||
- st::groupCallMembersMargin.right();
|
||||
const auto membersWidth = std::clamp(
|
||||
membersWidthAvailable,
|
||||
membersWidthMin,
|
||||
st::groupCallMembersWidthMax);
|
||||
_members->setGeometry(
|
||||
(widget()->width() - membersWidth) / 2,
|
||||
membersTop,
|
||||
membersWidth,
|
||||
std::min(desiredHeight, availableHeight));
|
||||
}
|
||||
|
||||
void Panel::refreshTitle() {
|
||||
if (!_title) {
|
||||
auto text = rpl::combine(
|
||||
@@ -1143,11 +1154,16 @@ void Panel::refreshTitle() {
|
||||
if (!_subtitle) {
|
||||
_subtitle.create(
|
||||
widget(),
|
||||
tr::lng_group_call_members(
|
||||
lt_count_decimal,
|
||||
_members->fullCountValue() | rpl::map([](int value) {
|
||||
return (value > 0) ? float64(value) : 1.;
|
||||
})),
|
||||
_scheduleDate.value(
|
||||
) | rpl::map([=](TimeId scheduleDate) {
|
||||
return scheduleDate
|
||||
? tr::lng_group_call_scheduled_status()
|
||||
: tr::lng_group_call_members(
|
||||
lt_count_decimal,
|
||||
_members->fullCountValue() | rpl::map([](int value) {
|
||||
return (value > 0) ? float64(value) : 1.;
|
||||
}));
|
||||
}) | rpl::flatten_latest(),
|
||||
st::groupCallSubtitleLabel);
|
||||
_subtitle->show();
|
||||
_subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
@@ -73,15 +73,17 @@ private:
|
||||
void initWindow();
|
||||
void initWidget();
|
||||
void initControls();
|
||||
void initWithCall(GroupCall *call);
|
||||
void initLayout();
|
||||
void initGeometry();
|
||||
void setupMembers();
|
||||
void setupJoinAsChangedToasts();
|
||||
void setupTitleChangedToasts();
|
||||
void setupAllowedToSpeakToasts();
|
||||
|
||||
bool handleClose();
|
||||
|
||||
void updateControlsGeometry();
|
||||
void updateMembersGeometry();
|
||||
void showControls();
|
||||
|
||||
void endCall();
|
||||
@@ -100,7 +102,7 @@ private:
|
||||
void migrate(not_null<ChannelData*> channel);
|
||||
void subscribeToPeerChanges();
|
||||
|
||||
GroupCall *_call = nullptr;
|
||||
const not_null<GroupCall*> _call;
|
||||
not_null<PeerData*> _peer;
|
||||
|
||||
const std::unique_ptr<Ui::Window> _window;
|
||||
@@ -118,8 +120,9 @@ private:
|
||||
object_ptr<Ui::IconButton> _menuToggle = { nullptr };
|
||||
object_ptr<Ui::DropdownMenu> _menu = { nullptr };
|
||||
object_ptr<Ui::AbstractButton> _joinAsToggle = { nullptr };
|
||||
object_ptr<Members> _members;
|
||||
object_ptr<Members> _members = { nullptr };
|
||||
rpl::variable<QString> _titleText;
|
||||
rpl::variable<TimeId> _scheduleDate;
|
||||
ChooseJoinAsProcess _joinAsProcess;
|
||||
|
||||
object_ptr<Ui::CallButton> _settings;
|
||||
|
Reference in New Issue
Block a user