Show leave confirmation when starting an RTMP stream.

This commit is contained in:
John Preston 2022-08-08 18:19:04 +03:00
parent d8743ec0e6
commit 72ed3bfab9
11 changed files with 204 additions and 148 deletions

View File

@ -202,43 +202,90 @@ void Instance::startOutgoingCall(not_null<UserData*> user, bool video) {
}), video);
}
void Instance::showStartOrJoinGroupCall(
void Instance::startOrJoinGroupCall(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer,
const StartGroupCallArgs &args) {
using JoinConfirm = StartGroupCallArgs::JoinConfirm;
const auto context = (args.confirm == JoinConfirm::Always)
? Group::ChooseJoinAsProcess::Context::JoinWithConfirm
: peer->groupCall()
? Group::ChooseJoinAsProcess::Context::Join
: args.scheduleNeeded
? Group::ChooseJoinAsProcess::Context::CreateScheduled
: Group::ChooseJoinAsProcess::Context::Create;
_chooseJoinAs->start(peer, context, [=](object_ptr<Ui::BoxContent> box) {
show->showBox(std::move(box), Ui::LayerOption::KeepOther);
}, [=](QString text) {
Ui::Toast::Show(show->toastParent(), text);
}, [=](Group::JoinInfo info) {
const auto call = info.peer->groupCall();
info.joinHash = args.joinHash;
if (call) {
info.rtmp = call->rtmp();
}
createGroupCall(
std::move(info),
call ? call->input() : MTP_inputGroupCall({}, {}));
StartGroupCallArgs args) {
confirmLeaveCurrent(show, peer, args, [=](StartGroupCallArgs args) {
using JoinConfirm = Calls::StartGroupCallArgs::JoinConfirm;
const auto context = (args.confirm == JoinConfirm::Always)
? Group::ChooseJoinAsProcess::Context::JoinWithConfirm
: peer->groupCall()
? Group::ChooseJoinAsProcess::Context::Join
: args.scheduleNeeded
? Group::ChooseJoinAsProcess::Context::CreateScheduled
: Group::ChooseJoinAsProcess::Context::Create;
_chooseJoinAs->start(peer, context, show, [=](Group::JoinInfo info) {
const auto call = info.peer->groupCall();
info.joinHash = args.joinHash;
if (call) {
info.rtmp = call->rtmp();
}
createGroupCall(
std::move(info),
call ? call->input() : MTP_inputGroupCall({}, {}));
});
});
}
void Instance::confirmLeaveCurrent(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer,
StartGroupCallArgs args,
Fn<void(StartGroupCallArgs)> confirmed) {
using JoinConfirm = Calls::StartGroupCallArgs::JoinConfirm;
auto confirmedArgs = args;
confirmedArgs.confirm = JoinConfirm::None;
const auto askConfirmation = [&](QString text, QString button) {
show->showBox(Ui::MakeConfirmBox({
.text = text,
.confirmed = [=] {
show->hideLayer();
confirmed(confirmedArgs);
},
.confirmText = button,
}));
};
if (args.confirm != JoinConfirm::None && inCall()) {
// Do you want to leave your active voice chat
// to join a voice chat in this group?
askConfirmation(
(peer->isBroadcast()
? tr::lng_call_leave_to_other_sure_channel
: tr::lng_call_leave_to_other_sure)(tr::now),
tr::lng_call_bar_hangup(tr::now));
} else if (args.confirm != JoinConfirm::None && inGroupCall()) {
const auto now = currentGroupCall()->peer();
if (now == peer) {
activateCurrentCall(args.joinHash);
} else if (currentGroupCall()->scheduleDate()) {
confirmed(confirmedArgs);
} else {
askConfirmation(
((peer->isBroadcast() && now->isBroadcast())
? tr::lng_group_call_leave_channel_to_other_sure_channel
: now->isBroadcast()
? tr::lng_group_call_leave_channel_to_other_sure
: peer->isBroadcast()
? tr::lng_group_call_leave_to_other_sure_channel
: tr::lng_group_call_leave_to_other_sure)(tr::now),
tr::lng_group_call_leave(tr::now));
}
} else {
confirmed(args);
}
}
void Instance::showStartWithRtmp(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer) {
_startWithRtmp->start(peer, [=](object_ptr<Ui::BoxContent> box) {
show->showBox(std::move(box), Ui::LayerOption::KeepOther);
}, [=](QString text) {
Ui::Toast::Show(show->toastParent(), text);
}, [=](Group::JoinInfo info) {
createGroupCall(std::move(info), MTP_inputGroupCall({}, {}));
_startWithRtmp->start(peer, show, [=](Group::JoinInfo info) {
confirmLeaveCurrent(show, peer, {}, [=](auto) {
_startWithRtmp->close();
createGroupCall(std::move(info), MTP_inputGroupCall({}, {}));
});
});
}

View File

@ -65,10 +65,10 @@ public:
~Instance();
void startOutgoingCall(not_null<UserData*> user, bool video);
void showStartOrJoinGroupCall(
void startOrJoinGroupCall(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer,
const StartGroupCallArgs &args);
StartGroupCallArgs args);
void showStartWithRtmp(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer);
@ -120,6 +120,11 @@ private:
Group::JoinInfo info,
const MTPInputGroupCall &inputCall);
void destroyGroupCall(not_null<GroupCall*> call);
void confirmLeaveCurrent(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer,
StartGroupCallArgs args,
Fn<void(StartGroupCallArgs)> confirmed);
void requestPermissionOrFail(
Platform::PermissionType type,

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
#include "ui/boxes/choose_date_time.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "boxes/peer_list_box.h"
#include "base/unixtime.h"
#include "base/timer_rpl.h"
@ -308,8 +309,7 @@ ChooseJoinAsProcess::~ChooseJoinAsProcess() {
void ChooseJoinAsProcess::start(
not_null<PeerData*> peer,
Context context,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
Fn<void(JoinInfo)> done,
PeerData *changingJoinAsFrom) {
Expects(done != nullptr);
@ -320,8 +320,7 @@ void ChooseJoinAsProcess::start(
if (_request) {
if (_request->peer == peer && !isScheduled) {
_request->context = context;
_request->showBox = std::move(showBox);
_request->showToast = std::move(showToast);
_request->show = std::move(show);
_request->done = std::move(done);
_request->changingJoinAsFrom = changingJoinAsFrom;
return;
@ -330,13 +329,10 @@ void ChooseJoinAsProcess::start(
_request = nullptr;
}
const auto createRequest = [=,
showToast = std::move(showToast),
done = std::move(done)] {
const auto createRequest = [=, done = std::move(done)] {
_request = std::make_unique<ChannelsListRequest>(ChannelsListRequest{
.peer = peer,
.showBox = showBox,
.showToast = std::move(showToast),
.show = show,
.done = std::move(done),
.context = context,
.changingJoinAsFrom = changingJoinAsFrom });
@ -350,7 +346,7 @@ void ChooseJoinAsProcess::start(
createRequest();
finish(info);
});
showBox(std::move(box));
show->showBox(std::move(box));
return;
}
@ -411,7 +407,9 @@ void ChooseJoinAsProcess::processList(
auto info = JoinInfo{ .peer = peer, .joinAs = self };
const auto selectedId = peer->groupCallDefaultJoinAs();
if (list.empty()) {
_request->showToast(Lang::Hard::ServerError());
Ui::Toast::Show(
_request->show->toastParent(),
Lang::Hard::ServerError());
return;
}
info.joinAs = [&]() -> not_null<PeerData*> {
@ -464,7 +462,7 @@ void ChooseJoinAsProcess::processList(
const auto safeFinish = crl::guard(guard, [=] { finish(info); });
const auto filter = [=](const auto &...) {
if (guard) {
_request->showBox(Box(
_request->show->showBox(Box(
ScheduleGroupCallBox,
info,
crl::guard(guard, [=](auto info) { finish(info); })));
@ -485,7 +483,7 @@ void ChooseJoinAsProcess::processList(
}, _request->lifetime);
_request->box = box.data();
_request->showBox(std::move(box));
_request->show->showBox(std::move(box));
return;
}
auto box = Box(
@ -499,7 +497,7 @@ void ChooseJoinAsProcess::processList(
}, _request->lifetime);
_request->box = box.data();
_request->showBox(std::move(box));
_request->show->showBox(std::move(box));
}
} // namespace Calls::Group

View File

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class PeerData;
namespace Ui {
class Show;
class BoxContent;
} // namespace Ui
@ -36,8 +37,7 @@ public:
void start(
not_null<PeerData*> peer,
Context context,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
Fn<void(JoinInfo)> done,
PeerData *changingJoinAsFrom = nullptr);
@ -48,8 +48,7 @@ private:
struct ChannelsListRequest {
not_null<PeerData*> peer;
Fn<void(object_ptr<Ui::BoxContent>)> showBox;
Fn<void(QString)> showToast;
std::shared_ptr<Ui::Show> show;
Fn<void(JoinInfo)> done;
base::has_weak_ptr guard;
QPointer<Ui::BoxContent> box;

View File

@ -1328,8 +1328,7 @@ void Panel::chooseJoinAs() {
_joinAsProcess.start(
_peer,
context,
showBoxCallback,
showToastCallback,
std::make_shared<Show>(this),
callback,
_call->joinAs());
}
@ -1470,6 +1469,10 @@ void Panel::showBox(
_layerBg->showBox(std::move(box), options, animated);
}
void Panel::hideLayer(anim::type animated) {
_layerBg->hideAll(animated);
}
void Panel::kickParticipantSure(not_null<PeerData*> participantPeer) {
if (const auto chat = _peer->asChat()) {
chat->session().api().chatParticipants().kick(chat, participantPeer);
@ -2555,4 +2558,38 @@ not_null<Ui::RpWidget*> Panel::widget() const {
return _window.widget();
}
Show::Show(not_null<Panel*> panel)
: _panel(base::make_weak(panel.get())) {
}
Show::~Show() = default;
void Show::showBox(
object_ptr<Ui::BoxContent> content,
Ui::LayerOptions options) const {
if (const auto panel = _panel.get()) {
panel->showBox(std::move(content), options);
}
}
void Show::hideLayer() const {
if (const auto panel = _panel.get()) {
panel->hideLayer();
}
}
not_null<QWidget*> Show::toastParent() const {
const auto panel = _panel.get();
Assert(panel != nullptr);
return panel->widget();
}
bool Show::valid() const {
return !_panel.empty();
}
Show::operator bool() const {
return valid();
}
} // namespace Calls::Group

View File

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/group/ui/desktop_capture_choose_source.h"
#include "ui/effects/animations.h"
#include "ui/gl/gl_window.h"
#include "ui/layers/show.h"
#include "ui/rp_widget.h"
class Image;
@ -74,11 +75,14 @@ enum class PanelMode;
enum class StickedTooltip;
class MicLevelTester;
class Panel final : private Ui::DesktopCapture::ChooseSourceDelegate {
class Panel final
: public base::has_weak_ptr
, private Ui::DesktopCapture::ChooseSourceDelegate {
public:
Panel(not_null<GroupCall*> call);
~Panel();
[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
[[nodiscard]] not_null<GroupCall*> call() const;
[[nodiscard]] bool isActive() const;
@ -88,6 +92,7 @@ public:
object_ptr<Ui::BoxContent> box,
Ui::LayerOptions options,
anim::type animated = anim::type::normal);
void hideLayer(anim::type animated = anim::type::normal);
void minimize();
void close();
@ -111,7 +116,6 @@ private:
};
[[nodiscard]] not_null<Ui::RpWindow*> window() const;
[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
[[nodiscard]] PanelMode mode() const;
@ -269,4 +273,21 @@ private:
};
class Show : public Ui::Show {
public:
explicit Show(not_null<Panel*> panel);
~Show();
void showBox(
object_ptr<Ui::BoxContent> content,
Ui::LayerOptions options = Ui::LayerOption::KeepOther) const override;
void hideLayer() const override;
[[nodiscard]] not_null<QWidget*> toastParent() const override;
[[nodiscard]] bool valid() const override;
operator bool() const override;
private:
const base::weak_ptr<Panel> _panel;
};
} // namespace Calls::Group

View File

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/boxes/confirm_box.h"
#include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/wrap/vertical_layout.h"
@ -39,8 +40,7 @@ void StartWithBox(
not_null<Ui::GenericBox*> box,
Fn<void()> done,
Fn<void()> revoke,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
rpl::producer<RtmpInfo> &&data) {
struct State {
base::unique_qptr<Ui::PopupMenu> menu;
@ -50,8 +50,7 @@ void StartWithBox(
StartRtmpProcess::FillRtmpRows(
box->verticalLayout(),
true,
std::move(showBox),
std::move(showToast),
std::move(show),
std::move(data),
&st::boxLabel,
&st::groupCallRtmpShowButton,
@ -97,23 +96,19 @@ void StartWithBox(
} // namespace
StartRtmpProcess::~StartRtmpProcess() {
if (_request) {
_request->peer->session().api().request(_request->id).cancel();
}
close();
}
void StartRtmpProcess::start(
not_null<PeerData*> peer,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
Fn<void(JoinInfo)> done) {
Expects(done != nullptr);
const auto session = &peer->session();
if (_request) {
if (_request->peer == peer) {
_request->showBox = std::move(showBox);
_request->showToast = std::move(showToast);
_request->show = std::move(show);
_request->done = std::move(done);
return;
}
@ -123,9 +118,9 @@ void StartRtmpProcess::start(
_request = std::make_unique<RtmpRequest>(
RtmpRequest{
.peer = peer,
.showBox = std::move(showBox),
.showToast = std::move(showToast),
.done = std::move(done) });
.show = std::move(show),
.done = std::move(done),
});
session->account().sessionChanges(
) | rpl::start_with_next([=] {
_request = nullptr;
@ -134,6 +129,16 @@ void StartRtmpProcess::start(
requestUrl(false);
}
void StartRtmpProcess::close() {
if (_request) {
_request->peer->session().api().request(_request->id).cancel();
if (const auto strong = _request->box.data()) {
strong->closeBox();
}
_request = nullptr;
}
}
void StartRtmpProcess::requestUrl(bool revoke) {
const auto session = &_request->peer->session();
_request->id = session->api().request(MTPphone_GetGroupCallStreamRtmpUrl(
@ -146,7 +151,9 @@ void StartRtmpProcess::requestUrl(bool revoke) {
});
processUrl(std::move(data));
}).fail([=] {
_request->showToast(Lang::Hard::ServerError());
Ui::Toast::Show(
_request->show->toastParent(),
Lang::Hard::ServerError());
}).send();
}
@ -158,15 +165,8 @@ void StartRtmpProcess::processUrl(RtmpInfo data) {
}
void StartRtmpProcess::finish(JoinInfo info) {
const auto done = std::move(_request->done);
const auto box = _request->box;
const auto current = _request->data.current();
_request = nullptr;
info.rtmpInfo = current;
done(std::move(info));
if (const auto strong = box.data()) {
strong->closeBox();
}
info.rtmpInfo = _request->data.current();
_request->done(std::move(info));
}
void StartRtmpProcess::createBox() {
@ -176,7 +176,7 @@ void StartRtmpProcess::createBox() {
};
auto revoke = [=] {
const auto guard = base::make_weak(&_request->guard);
_request->showBox(Ui::MakeConfirmBox({
_request->show->showBox(Ui::MakeConfirmBox({
.text = tr::lng_group_call_rtmp_revoke_sure(),
.confirmed = crl::guard(guard, [=](Fn<void()> &&close) {
requestUrl(true);
@ -189,22 +189,20 @@ void StartRtmpProcess::createBox() {
StartWithBox,
std::move(done),
std::move(revoke),
_request->showBox,
_request->showToast,
_request->show,
_request->data.value());
object->boxClosing(
) | rpl::start_with_next([=] {
_request = nullptr;
}, _request->lifetime);
_request->box = Ui::MakeWeak(object.data());
_request->showBox(std::move(object));
_request->show->showBox(std::move(object));
}
void StartRtmpProcess::FillRtmpRows(
not_null<Ui::VerticalLayout*> container,
bool divider,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
rpl::producer<RtmpInfo> &&data,
const style::FlatLabel *labelStyle,
const style::IconButton *showButtonStyle,
@ -230,6 +228,9 @@ void StartRtmpProcess::FillRtmpRows(
data
) | rpl::map([=](const auto &d) { return d.url; });
const auto showToast = [=](const QString &text) {
Ui::Toast::Show(show->toastParent(), text);
};
const auto addButton = [&](
bool key,
rpl::producer<QString> &&text) {
@ -332,7 +333,7 @@ void StartRtmpProcess::FillRtmpRows(
newValue);
};
if (!state->warned && state->hidden.current()) {
showBox(Ui::MakeConfirmBox({
show->showBox(Ui::MakeConfirmBox({
.text = tr::lng_group_call_rtmp_key_warning(
Ui::Text::RichLangValue),
.confirmed = [=](Fn<void()> &&close) {

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class PeerData;
namespace Ui {
class Show;
class BoxContent;
class VerticalLayout;
} // namespace Ui
@ -36,15 +37,14 @@ public:
void start(
not_null<PeerData*> peer,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
Fn<void(JoinInfo)> done);
void close();
static void FillRtmpRows(
not_null<Ui::VerticalLayout*> container,
bool divider,
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(QString)> showToast,
std::shared_ptr<Ui::Show> show,
rpl::producer<RtmpInfo> &&data,
const style::FlatLabel *labelStyle,
const style::IconButton *showButtonStyle,
@ -61,8 +61,7 @@ private:
struct RtmpRequest {
not_null<PeerData*> peer;
rpl::variable<RtmpInfo> data;
Fn<void(object_ptr<Ui::BoxContent>)> showBox;
Fn<void(QString)> showToast;
std::shared_ptr<Ui::Show> show;
Fn<void(JoinInfo)> done;
base::has_weak_ptr guard;
QPointer<Ui::BoxContent> box;

View File

@ -733,18 +733,10 @@ void SettingsBox(
return true;
});
StartRtmpProcess::FillRtmpRows(
layout,
false,
[=](object_ptr<Ui::BoxContent> &&object) {
box->getDelegate()->show(std::move(object));
},
[=](QString text) {
Ui::Toast::Show(
box->getDelegate()->outerContainer(),
text);
},
std::make_shared<Ui::BoxShow>(box),
state->data.events(),
&st::groupCallBoxLabel,
&st::groupCallSettingsRtmpShowButton,

View File

@ -1273,54 +1273,11 @@ void SessionController::showPeer(not_null<PeerData*> peer, MsgId msgId) {
void SessionController::startOrJoinGroupCall(
not_null<PeerData*> peer,
const Calls::StartGroupCallArgs &args) {
using JoinConfirm = Calls::StartGroupCallArgs::JoinConfirm;
auto &calls = Core::App().calls();
auto confirmedArgs = args;
confirmedArgs.confirm = JoinConfirm::None;
const auto askConfirmation = [&](QString text, QString button) {
show(Ui::MakeConfirmBox({
.text = text,
.confirmed = crl::guard(this,[=] {
hideLayer();
startOrJoinGroupCall(peer, confirmedArgs);
}),
.confirmText = button,
}));
};
if (args.confirm != JoinConfirm::None && calls.inCall()) {
// Do you want to leave your active voice chat
// to join a voice chat in this group?
askConfirmation(
(peer->isBroadcast()
? tr::lng_call_leave_to_other_sure_channel
: tr::lng_call_leave_to_other_sure)(tr::now),
tr::lng_call_bar_hangup(tr::now));
} else if (args.confirm != JoinConfirm::None
&& calls.inGroupCall()) {
const auto now = calls.currentGroupCall()->peer();
if (now == peer) {
calls.activateCurrentCall(args.joinHash);
} else if (calls.currentGroupCall()->scheduleDate()) {
startOrJoinGroupCall(peer, confirmedArgs);
} else {
askConfirmation(
((peer->isBroadcast() && now->isBroadcast())
? tr::lng_group_call_leave_channel_to_other_sure_channel
: now->isBroadcast()
? tr::lng_group_call_leave_channel_to_other_sure
: peer->isBroadcast()
? tr::lng_group_call_leave_to_other_sure_channel
: tr::lng_group_call_leave_to_other_sure)(tr::now),
tr::lng_group_call_leave(tr::now));
}
} else {
calls.showStartOrJoinGroupCall(
std::make_shared<Show>(this),
peer,
args);
}
Calls::StartGroupCallArgs args) {
Core::App().calls().startOrJoinGroupCall(
std::make_shared<Show>(this),
peer,
args);
}
void SessionController::showCalendar(Dialogs::Key chat, QDate requestedDate) {

View File

@ -387,7 +387,7 @@ public:
void startOrJoinGroupCall(
not_null<PeerData*> peer,
const Calls::StartGroupCallArgs &args);
Calls::StartGroupCallArgs args);
void showSection(
std::shared_ptr<SectionMemento> memento,