Add video/screencast pinned/unpinned toasts.

This commit is contained in:
John Preston 2021-05-31 17:10:30 +04:00
parent bcdfd2150d
commit ba6cee6f81
10 changed files with 298 additions and 180 deletions

View file

@ -287,6 +287,8 @@ PRIVATE
calls/group/calls_group_panel.h calls/group/calls_group_panel.h
calls/group/calls_group_settings.cpp calls/group/calls_group_settings.cpp
calls/group/calls_group_settings.h calls/group/calls_group_settings.h
calls/group/calls_group_toasts.cpp
calls/group/calls_group_toasts.h
calls/group/calls_group_viewport.cpp calls/group/calls_group_viewport.cpp
calls/group/calls_group_viewport.h calls/group/calls_group_viewport.h
calls/group/calls_group_viewport_opengl.cpp calls/group/calls_group_viewport_opengl.cpp

View file

@ -2130,6 +2130,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_recording_started" = "Voice chat recording started."; "lng_group_call_recording_started" = "Voice chat recording started.";
"lng_group_call_recording_stopped" = "Voice chat recording stopped."; "lng_group_call_recording_stopped" = "Voice chat recording stopped.";
"lng_group_call_recording_saved" = "Audio saved to Saved Messages."; "lng_group_call_recording_saved" = "Audio saved to Saved Messages.";
"lng_group_call_pinned_camera_me" = "Your video is pinned.";
"lng_group_call_pinned_screen_me" = "Your screencast is pinned.";
"lng_group_call_pinned_camera" = "{user}'s video is pinned.";
"lng_group_call_pinned_screen" = "{user}'s screencast is pinned.";
"lng_group_call_unpinned_camera_me" = "Your video is unpinned.";
"lng_group_call_unpinned_screen_me" = "Your screencast is unpinned.";
"lng_group_call_unpinned_camera" = "{user}'s video is unpinned.";
"lng_group_call_unpinned_screen" = "{user}'s screencast is unpinned.";
"lng_group_call_sure_screencast" = "{user} is screensharing. This action will make your screencast pinned for all participants.";
"lng_group_call_recording_start_sure" = "Do you want to start recording this chat and save the result into an audio file?\n\nOther members will see the chat is being recorded."; "lng_group_call_recording_start_sure" = "Do you want to start recording this chat and save the result into an audio file?\n\nOther members will see the chat is being recorded.";
"lng_group_call_recording_stop_sure" = "Do you want to stop recording this chat?"; "lng_group_call_recording_stop_sure" = "Do you want to stop recording this chat?";
"lng_group_call_recording_start_field" = "Recording Title"; "lng_group_call_recording_start_field" = "Recording Title";

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/group/calls_group_settings.h" #include "calls/group/calls_group_settings.h"
#include "calls/group/calls_group_menu.h" #include "calls/group/calls_group_menu.h"
#include "calls/group/calls_group_viewport.h" #include "calls/group/calls_group_viewport.h"
#include "calls/group/calls_group_toasts.h"
#include "calls/group/ui/desktop_capture_choose_source.h" #include "calls/group/ui/desktop_capture_choose_source.h"
#include "ui/platform/ui_platform_window_title.h" #include "ui/platform/ui_platform_window_title.h"
#include "ui/platform/ui_platform_utility.h" #include "ui/platform/ui_platform_utility.h"
@ -27,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/layer_manager.h" #include "ui/layers/layer_manager.h"
#include "ui/layers/generic_box.h" #include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h" #include "ui/toasts/common_toasts.h"
#include "ui/round_rect.h" #include "ui/round_rect.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
@ -68,7 +70,6 @@ constexpr auto kRecordingOpacity = 0.6;
constexpr auto kStartNoConfirmation = TimeId(10); constexpr auto kStartNoConfirmation = TimeId(10);
constexpr auto kControlsBackgroundOpacity = 0.8; constexpr auto kControlsBackgroundOpacity = 0.8;
constexpr auto kOverrideActiveColorBgAlpha = 172; constexpr auto kOverrideActiveColorBgAlpha = 172;
constexpr auto kErrorDuration = 2 * crl::time(1000);
class InviteController final : public ParticipantsBoxController { class InviteController final : public ParticipantsBoxController {
public: public:
@ -421,7 +422,8 @@ Panel::Panel(not_null<GroupCall*> call)
? Ui::CallMuteButtonType::ScheduledNotify ? Ui::CallMuteButtonType::ScheduledNotify
: Ui::CallMuteButtonType::ScheduledSilent), : Ui::CallMuteButtonType::ScheduledSilent),
})) }))
, _hangup(widget(), st::groupCallHangup) { , _hangup(widget(), st::groupCallHangup)
, _toasts(std::make_unique<Toasts>(this)) {
_layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox); _layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox);
_layerBg->setHideByBackgroundClick(true); _layerBg->setHideByBackgroundClick(true);
@ -441,7 +443,6 @@ Panel::Panel(not_null<GroupCall*> call)
initControls(); initControls();
initLayout(); initLayout();
showAndActivate(); showAndActivate();
setupToasts();
} }
Panel::~Panel() { Panel::~Panel() {
@ -456,12 +457,27 @@ void Panel::setupRealCallViewers() {
}, _window->lifetime()); }, _window->lifetime());
} }
not_null<GroupCall*> Panel::call() const {
return _call;
}
bool Panel::isActive() const { bool Panel::isActive() const {
return _window->isActiveWindow() return _window->isActiveWindow()
&& _window->isVisible() && _window->isVisible()
&& !(_window->windowState() & Qt::WindowMinimized); && !(_window->windowState() & Qt::WindowMinimized);
} }
void Panel::showToast(TextWithEntities &&text, crl::time duration) {
if (const auto strong = _lastToast.get()) {
strong->hideAnimated();
}
_lastToast = Ui::ShowMultilineToast({
.parentOverride = widget(),
.text = std::move(text),
.duration = duration,
});
}
void Panel::minimize() { void Panel::minimize() {
_window->setWindowState(_window->windowState() | Qt::WindowMinimized); _window->setWindowState(_window->windowState() | Qt::WindowMinimized);
} }
@ -814,19 +830,16 @@ void Panel::refreshVideoButtons(std::optional<bool> overrideWideMode) {
} }
void Panel::initShareAction() { void Panel::initShareAction() {
const auto showBox = [=](object_ptr<Ui::BoxContent> next) { const auto showBoxCallback = [=](object_ptr<Ui::BoxContent> next) {
_layerBg->showBox(std::move(next)); _layerBg->showBox(std::move(next));
}; };
const auto showToast = [=](QString text) { const auto showToastCallback = [=](QString text) {
Ui::ShowMultilineToast({ showToast({ text });
.parentOverride = widget(),
.text = { text },
});
}; };
auto [shareLinkCallback, shareLinkLifetime] = ShareInviteLinkAction( auto [shareLinkCallback, shareLinkLifetime] = ShareInviteLinkAction(
_peer, _peer,
showBox, showBoxCallback,
showToast); showToastCallback);
_callShareLinkCallback = [=, callback = std::move(shareLinkCallback)] { _callShareLinkCallback = [=, callback = std::move(shareLinkCallback)] {
if (_call->lookupReal()) { if (_call->lookupReal()) {
callback(); callback();
@ -1199,118 +1212,6 @@ void Panel::toggleWideControls(bool shown) {
}); });
} }
void Panel::setupToasts() {
setupJoinAsChangedToasts();
setupTitleChangedToasts();
setupRequestedToSpeakToasts();
setupAllowedToSpeakToasts();
setupErrorToasts();
}
void Panel::setupJoinAsChangedToasts() {
_call->rejoinEvents(
) | rpl::filter([](RejoinEvent event) {
return (event.wasJoinAs != event.nowJoinAs);
}) | rpl::map([=] {
return _call->stateValue() | rpl::filter([](State state) {
return (state == State::Joined);
}) | rpl::take(1);
}) | rpl::flatten_latest() | rpl::start_with_next([=] {
Ui::ShowMultilineToast({
.parentOverride = widget(),
.text = tr::lng_group_call_join_as_changed(
tr::now,
lt_name,
Ui::Text::Bold(_call->joinAs()->name),
Ui::Text::WithEntities),
});
}, widget()->lifetime());
}
void Panel::setupTitleChangedToasts() {
_call->titleChanged(
) | rpl::filter([=] {
return (_call->lookupReal() != nullptr);
}) | rpl::map([=] {
return _peer->groupCall()->title().isEmpty()
? _peer->name
: _peer->groupCall()->title();
}) | rpl::start_with_next([=](const QString &title) {
Ui::ShowMultilineToast({
.parentOverride = widget(),
.text = tr::lng_group_call_title_changed(
tr::now,
lt_title,
Ui::Text::Bold(title),
Ui::Text::WithEntities),
});
}, 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 = _call->lookupReal();
const auto name = (real && !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::setupRequestedToSpeakToasts() {
_call->mutedValue(
) | rpl::combine_previous(
) | rpl::start_with_next([=](MuteState was, MuteState now) {
if (was == MuteState::ForceMuted && now == MuteState::RaisedHand) {
Ui::ShowMultilineToast({
.parentOverride = widget(),
.text = tr::lng_group_call_tooltip_raised_hand(tr::now),
});
}
}, widget()->lifetime());
}
void Panel::setupErrorToasts() {
_call->errors(
) | rpl::start_with_next([=](Error error) {
const auto key = [&] {
switch (error) {
case Error::NoCamera: return tr::lng_call_error_no_camera;
case Error::ScreenFailed:
return tr::lng_group_call_failed_screen;
case Error::MutedNoCamera:
return tr::lng_group_call_muted_no_camera;
case Error::MutedNoScreen:
return tr::lng_group_call_muted_no_screen;
case Error::DisabledNoCamera:
return tr::lng_group_call_chat_no_camera;
case Error::DisabledNoScreen:
return tr::lng_group_call_chat_no_screen;
}
Unexpected("Error in Calls::Group::Panel::setupErrorToasts.");
}();
Ui::ShowMultilineToast({
.parentOverride = widget(),
.text = { key(tr::now) },
.duration = kErrorDuration,
});
}, widget()->lifetime());
}
void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) { void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
const auto validateRecordingMark = [=](bool recording) { const auto validateRecordingMark = [=](bool recording) {
if (!recording && _recordingMark) { if (!recording && _recordingMark) {
@ -1328,10 +1229,7 @@ void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
const auto skip = st::groupCallRecordingMarkSkip; const auto skip = st::groupCallRecordingMarkSkip;
_recordingMark->resize(size + 2 * skip, size + 2 * skip); _recordingMark->resize(size + 2 * skip, size + 2 * skip);
_recordingMark->setClickedCallback([=] { _recordingMark->setClickedCallback([=] {
Ui::ShowMultilineToast({ showToast({ tr::lng_group_call_is_recorded(tr::now) });
.parentOverride = widget(),
.text = { tr::lng_group_call_is_recorded(tr::now) },
});
}); });
const auto animate = [=] { const auto animate = [=] {
const auto opaque = state->opaque; const auto opaque = state->opaque;
@ -1367,16 +1265,13 @@ void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
) | rpl::distinct_until_changed( ) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool recorded) { ) | rpl::start_with_next([=](bool recorded) {
validateRecordingMark(recorded); validateRecordingMark(recorded);
Ui::ShowMultilineToast({ showToast((recorded
.parentOverride = widget(),
.text = (recorded
? tr::lng_group_call_recording_started ? tr::lng_group_call_recording_started
: _call->recordingStoppedByMe() : _call->recordingStoppedByMe()
? tr::lng_group_call_recording_saved ? tr::lng_group_call_recording_saved
: tr::lng_group_call_recording_stopped)( : tr::lng_group_call_recording_stopped)(
tr::now, tr::now,
Ui::Text::RichLangValue), Ui::Text::RichLangValue));
});
}, widget()->lifetime()); }, widget()->lifetime());
validateRecordingMark(real->recordStartDate() != 0); validateRecordingMark(real->recordStartDate() != 0);
@ -1448,20 +1343,17 @@ void Panel::chooseJoinAs() {
const auto callback = [=](JoinInfo info) { const auto callback = [=](JoinInfo info) {
_call->rejoinAs(info); _call->rejoinAs(info);
}; };
const auto showBox = [=](object_ptr<Ui::BoxContent> next) { const auto showBoxCallback = [=](object_ptr<Ui::BoxContent> next) {
_layerBg->showBox(std::move(next)); _layerBg->showBox(std::move(next));
}; };
const auto showToast = [=](QString text) { const auto showToastCallback = [=](QString text) {
Ui::ShowMultilineToast({ showToast({ text });
.parentOverride = widget(),
.text = { text },
});
}; };
_joinAsProcess.start( _joinAsProcess.start(
_peer, _peer,
context, context,
showBox, showBoxCallback,
showToast, showToastCallback,
callback, callback,
_call->joinAs()); _call->joinAs());
} }
@ -1578,24 +1470,18 @@ void Panel::addMembers() {
} }
const auto result = call->inviteUsers(users); const auto result = call->inviteUsers(users);
if (const auto user = std::get_if<not_null<UserData*>>(&result)) { if (const auto user = std::get_if<not_null<UserData*>>(&result)) {
Ui::ShowMultilineToast({ showToast(tr::lng_group_call_invite_done_user(
.parentOverride = widget(),
.text = tr::lng_group_call_invite_done_user(
tr::now, tr::now,
lt_user, lt_user,
Ui::Text::Bold((*user)->firstName), Ui::Text::Bold((*user)->firstName),
Ui::Text::WithEntities), Ui::Text::WithEntities));
});
} else if (const auto count = std::get_if<int>(&result)) { } else if (const auto count = std::get_if<int>(&result)) {
if (*count > 0) { if (*count > 0) {
Ui::ShowMultilineToast({ showToast(tr::lng_group_call_invite_done_many(
.parentOverride = widget(),
.text = tr::lng_group_call_invite_done_many(
tr::now, tr::now,
lt_count, lt_count,
*count, *count,
Ui::Text::RichLangValue), Ui::Text::RichLangValue));
});
} }
} else { } else {
Unexpected("Result in GroupCall::inviteUsers."); Unexpected("Result in GroupCall::inviteUsers.");

View file

@ -42,6 +42,9 @@ class ScrollArea;
class GenericBox; class GenericBox;
class LayerManager; class LayerManager;
class GroupCallScheduledLeft; class GroupCallScheduledLeft;
namespace Toast {
class Instance;
} // namespace Toast
namespace Platform { namespace Platform {
class TitleControls; class TitleControls;
} // namespace Platform } // namespace Platform
@ -54,6 +57,7 @@ struct CallBodyLayout;
namespace Calls::Group { namespace Calls::Group {
class Toasts;
class Members; class Members;
class Viewport; class Viewport;
enum class PanelMode; enum class PanelMode;
@ -63,7 +67,11 @@ public:
Panel(not_null<GroupCall*> call); Panel(not_null<GroupCall*> call);
~Panel(); ~Panel();
[[nodiscard]] not_null<GroupCall*> call() const;
[[nodiscard]] bool isActive() const; [[nodiscard]] bool isActive() const;
void showToast(TextWithEntities &&text, crl::time duration = 0);
void minimize(); void minimize();
void close(); void close();
void showAndActivate(); void showAndActivate();
@ -88,12 +96,6 @@ private:
void setupScheduledLabels(rpl::producer<TimeId> date); void setupScheduledLabels(rpl::producer<TimeId> date);
void setupMembers(); void setupMembers();
void setupVideo(not_null<Viewport*> viewport); void setupVideo(not_null<Viewport*> viewport);
void setupToasts();
void setupJoinAsChangedToasts();
void setupTitleChangedToasts();
void setupRequestedToSpeakToasts();
void setupAllowedToSpeakToasts();
void setupErrorToasts();
void setupRealMuteButtonState(not_null<Data::GroupCall*> real); void setupRealMuteButtonState(not_null<Data::GroupCall*> real);
bool handleClose(); bool handleClose();
@ -196,6 +198,9 @@ private:
object_ptr<Ui::ImportantTooltip> _niceTooltip = { nullptr }; object_ptr<Ui::ImportantTooltip> _niceTooltip = { nullptr };
Fn<void()> _callShareLinkCallback; Fn<void()> _callShareLinkCallback;
const std::unique_ptr<Toasts> _toasts;
base::weak_ptr<Ui::Toast::Instance> _lastToast;
rpl::lifetime _peerLifetime; rpl::lifetime _peerLifetime;
}; };

View file

@ -0,0 +1,175 @@
/*
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/group/calls_group_toasts.h"
#include "calls/group/calls_group_call.h"
#include "calls/group/calls_group_common.h"
#include "calls/group/calls_group_panel.h"
#include "data/data_peer.h"
#include "data/data_group_call.h"
#include "ui/text/text_utilities.h"
#include "ui/toasts/common_toasts.h"
#include "lang/lang_keys.h"
namespace Calls::Group {
namespace {
constexpr auto kErrorDuration = 2 * crl::time(1000);
using State = GroupCall::State;
} // namespace
Toasts::Toasts(not_null<Panel*> panel)
: _panel(panel)
, _call(panel->call()) {
setup();
}
void Toasts::setup() {
setupJoinAsChanged();
setupTitleChanged();
setupRequestedToSpeak();
setupAllowedToSpeak();
setupPinnedVideo();
setupError();
}
void Toasts::setupJoinAsChanged() {
_call->rejoinEvents(
) | rpl::filter([](RejoinEvent event) {
return (event.wasJoinAs != event.nowJoinAs);
}) | rpl::map([=] {
return _call->stateValue() | rpl::filter([](State state) {
return (state == State::Joined);
}) | rpl::take(1);
}) | rpl::flatten_latest() | rpl::start_with_next([=] {
_panel->showToast(tr::lng_group_call_join_as_changed(
tr::now,
lt_name,
Ui::Text::Bold(_call->joinAs()->name),
Ui::Text::WithEntities));
}, _lifetime);
}
void Toasts::setupTitleChanged() {
_call->titleChanged(
) | rpl::filter([=] {
return (_call->lookupReal() != nullptr);
}) | rpl::map([=] {
const auto peer = _call->peer();
return peer->groupCall()->title().isEmpty()
? peer->name
: peer->groupCall()->title();
}) | rpl::start_with_next([=](const QString &title) {
_panel->showToast(tr::lng_group_call_title_changed(
tr::now,
lt_title,
Ui::Text::Bold(title),
Ui::Text::WithEntities));
}, _lifetime);
}
void Toasts::setupAllowedToSpeak() {
_call->allowedToSpeakNotifications(
) | rpl::start_with_next([=] {
if (_panel->isActive()) {
_panel->showToast({
tr::lng_group_call_can_speak_here(tr::now),
});
} else {
const auto real = _call->lookupReal();
const auto name = (real && !real->title().isEmpty())
? real->title()
: _call->peer()->name;
Ui::ShowMultilineToast({
.text = tr::lng_group_call_can_speak(
tr::now,
lt_chat,
Ui::Text::Bold(name),
Ui::Text::WithEntities),
});
}
}, _lifetime);
}
void Toasts::setupPinnedVideo() {
_call->videoEndpointPinnedValue(
) | rpl::map([=](bool pinned) {
return pinned
? _call->videoEndpointLargeValue()
: rpl::single(_call->videoEndpointLarge());
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const VideoEndpoint &endpoint) {
const auto pinned = _call->videoEndpointPinned();
const auto peer = endpoint.peer;
if (!peer) {
return;
}
const auto text = [&] {
const auto me = (peer == _call->joinAs());
const auto camera = (endpoint.type == VideoEndpointType::Camera);
if (me) {
const auto key = camera
? (pinned
? tr::lng_group_call_pinned_camera_me
: tr::lng_group_call_unpinned_camera_me)
: (pinned
? tr::lng_group_call_pinned_screen_me
: tr::lng_group_call_unpinned_screen_me);
return key(tr::now);
}
const auto key = camera
? (pinned
? tr::lng_group_call_pinned_camera
: tr::lng_group_call_unpinned_camera)
: (pinned
? tr::lng_group_call_pinned_screen
: tr::lng_group_call_unpinned_screen);
return key(tr::now, lt_user, peer->shortName());
}();
_panel->showToast({ text });
}, _lifetime);
}
void Toasts::setupRequestedToSpeak() {
_call->mutedValue(
) | rpl::combine_previous(
) | rpl::start_with_next([=](MuteState was, MuteState now) {
if (was == MuteState::ForceMuted && now == MuteState::RaisedHand) {
_panel->showToast({
tr::lng_group_call_tooltip_raised_hand(tr::now),
});
}
}, _lifetime);
}
void Toasts::setupError() {
_call->errors(
) | rpl::start_with_next([=](Error error) {
const auto key = [&] {
switch (error) {
case Error::NoCamera: return tr::lng_call_error_no_camera;
case Error::ScreenFailed:
return tr::lng_group_call_failed_screen;
case Error::MutedNoCamera:
return tr::lng_group_call_muted_no_camera;
case Error::MutedNoScreen:
return tr::lng_group_call_muted_no_screen;
case Error::DisabledNoCamera:
return tr::lng_group_call_chat_no_camera;
case Error::DisabledNoScreen:
return tr::lng_group_call_chat_no_screen;
}
Unexpected("Error in Calls::Group::Toasts::setupErrorToasts.");
}();
_panel->showToast({ key(tr::now) }, kErrorDuration);
}, _lifetime);
}
} // namespace Calls::Group

View file

@ -0,0 +1,38 @@
/*
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
namespace Calls {
class GroupCall;
} // namespace Calls
namespace Calls::Group {
class Panel;
class Toasts final {
public:
explicit Toasts(not_null<Panel*> panel);
private:
void setup();
void setupJoinAsChanged();
void setupTitleChanged();
void setupRequestedToSpeak();
void setupAllowedToSpeak();
void setupPinnedVideo();
void setupError();
const not_null<Panel*> _panel;
const not_null<GroupCall*> _call;
rpl::lifetime _lifetime;
};
} // namespace Calls::Group

View file

@ -1139,7 +1139,7 @@ void CallMuteButton::overridesColors(
const auto toInactive = IsInactive(toType); const auto toInactive = IsInactive(toType);
const auto fromInactive = IsInactive(fromType); const auto fromInactive = IsInactive(fromType);
if (toInactive && (progress == 1)) { if (toInactive && (progress == 1)) {
_colorOverrides.fire({ std::nullopt, std::nullopt }); _colorOverrides = CallButtonColors();
return; return;
} }
const auto &fromStops = _colors.find(fromType)->second.stops; const auto &fromStops = _colors.find(fromType)->second.stops;
@ -1158,11 +1158,11 @@ void CallMuteButton::overridesColors(
} }
const auto resultBg = anim::color(from, to, progress); const auto resultBg = anim::color(from, to, progress);
const auto resultRipple = anim::color(fromRipple, toRipple, progress); const auto resultRipple = anim::color(fromRipple, toRipple, progress);
_colorOverrides.fire({ resultBg, resultRipple }); _colorOverrides = CallButtonColors{ resultBg, resultRipple };
} }
rpl::producer<CallButtonColors> CallMuteButton::colorOverrides() const { rpl::producer<CallButtonColors> CallMuteButton::colorOverrides() const {
return _colorOverrides.events(); return _colorOverrides.value();
} }
not_null<RpWidget*> CallMuteButton::outer() const { not_null<RpWidget*> CallMuteButton::outer() const {

View file

@ -11,6 +11,7 @@
#include "ui/effects/cross_line.h" #include "ui/effects/cross_line.h"
#include "ui/effects/gradient.h" #include "ui/effects/gradient.h"
#include "ui/effects/radial_animation.h" #include "ui/effects/radial_animation.h"
#include "ui/widgets/call_button.h"
#include "ui/widgets/tooltip.h" #include "ui/widgets/tooltip.h"
#include "lottie/lottie_icon.h" #include "lottie/lottie_icon.h"
@ -31,8 +32,6 @@ class FlatLabel;
class RpWidget; class RpWidget;
class AnimatedLabel; class AnimatedLabel;
struct CallButtonColors;
enum class CallMuteButtonType { enum class CallMuteButtonType {
Connecting, Connecting,
Active, Active,
@ -179,7 +178,7 @@ private:
Animations::Simple _switchAnimation; Animations::Simple _switchAnimation;
Animations::Simple _shakeAnimation; Animations::Simple _shakeAnimation;
rpl::event_stream<CallButtonColors> _colorOverrides; rpl::variable<CallButtonColors> _colorOverrides;
}; };

View file

@ -12,7 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui { namespace Ui {
void ShowMultilineToast(MultilineToastArgs &&args) { base::weak_ptr<Toast::Instance> ShowMultilineToast(
MultilineToastArgs &&args) {
auto config = Ui::Toast::Config{ auto config = Ui::Toast::Config{
.text = std::move(args.text), .text = std::move(args.text),
.st = &st::defaultMultilineToast, .st = &st::defaultMultilineToast,
@ -21,11 +22,9 @@ void ShowMultilineToast(MultilineToastArgs &&args) {
: Ui::Toast::kDefaultDuration), : Ui::Toast::kDefaultDuration),
.multiline = true, .multiline = true,
}; };
if (args.parentOverride) { return args.parentOverride
Ui::Toast::Show(args.parentOverride, std::move(config)); ? Ui::Toast::Show(args.parentOverride, std::move(config))
} else { : Ui::Toast::Show(std::move(config));
Ui::Toast::Show(std::move(config));
}
} }
} // namespace Ui } // namespace Ui

View file

@ -8,8 +8,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "ui/text/text_entity.h" #include "ui/text/text_entity.h"
#include "base/weak_ptr.h"
namespace Ui { namespace Ui {
namespace Toast {
class Instance;
} // namespace Toast
struct MultilineToastArgs { struct MultilineToastArgs {
QWidget *parentOverride = nullptr; QWidget *parentOverride = nullptr;
@ -17,6 +21,7 @@ struct MultilineToastArgs {
crl::time duration = 0; crl::time duration = 0;
}; };
void ShowMultilineToast(MultilineToastArgs &&args); base::weak_ptr<Toast::Instance> ShowMultilineToast(
MultilineToastArgs &&args);
} // namespace Ui } // namespace Ui