mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added initial implementation of volume menu item in group calls.
This commit is contained in:
parent
e12689c8c1
commit
173564bcd5
5 changed files with 290 additions and 0 deletions
|
@ -290,6 +290,8 @@ PRIVATE
|
||||||
calls/calls_userpic.h
|
calls/calls_userpic.h
|
||||||
calls/calls_video_bubble.cpp
|
calls/calls_video_bubble.cpp
|
||||||
calls/calls_video_bubble.h
|
calls/calls_video_bubble.h
|
||||||
|
calls/calls_volume_item.cpp
|
||||||
|
calls/calls_volume_item.h
|
||||||
chat_helpers/bot_keyboard.cpp
|
chat_helpers/bot_keyboard.cpp
|
||||||
chat_helpers/bot_keyboard.h
|
chat_helpers/bot_keyboard.h
|
||||||
chat_helpers/emoji_keywords.cpp
|
chat_helpers/emoji_keywords.cpp
|
||||||
|
|
|
@ -778,6 +778,8 @@ groupCallMajorBlobMaxRadius: 4px;
|
||||||
groupCallMinorBlobIdleRadius: 3px;
|
groupCallMinorBlobIdleRadius: 3px;
|
||||||
groupCallMinorBlobMaxRadius: 12px;
|
groupCallMinorBlobMaxRadius: 12px;
|
||||||
|
|
||||||
|
groupCallMenuVolumeItemHeight: 100px;
|
||||||
|
|
||||||
callTopBarMuteCrossLine: CrossLineAnimation {
|
callTopBarMuteCrossLine: CrossLineAnimation {
|
||||||
fg: callBarFg;
|
fg: callBarFg;
|
||||||
icon: icon {{ "calls/call_record_active", callBarFg }};
|
icon: icon {{ "calls/call_record_active", callBarFg }};
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "calls/calls_group_call.h"
|
#include "calls/calls_group_call.h"
|
||||||
#include "calls/calls_group_common.h"
|
#include "calls/calls_group_common.h"
|
||||||
|
#include "calls/calls_volume_item.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
|
@ -1166,6 +1167,13 @@ base::unique_qptr<Ui::PopupMenu> MembersController::createRowContextMenu(
|
||||||
.mute = mute,
|
.mute = mute,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
const auto toggleMute_ = crl::guard(this, [=](bool mute, bool local) {
|
||||||
|
_toggleMuteRequests.fire(Group::MuteRequest{
|
||||||
|
.user = user,
|
||||||
|
.mute = mute,
|
||||||
|
.locallyOnly = local,
|
||||||
|
});
|
||||||
|
});
|
||||||
const auto changeVolume = crl::guard(this, [=](int volume, bool local) {
|
const auto changeVolume = crl::guard(this, [=](int volume, bool local) {
|
||||||
_changeVolumeRequests.fire(Group::VolumeRequest{
|
_changeVolumeRequests.fire(Group::VolumeRequest{
|
||||||
.user = user,
|
.user = user,
|
||||||
|
@ -1252,6 +1260,47 @@ base::unique_qptr<Ui::PopupMenu> MembersController::createRowContextMenu(
|
||||||
changeVolume(volume - 2000, false);
|
changeVolume(volume - 2000, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto call = _call.get();
|
||||||
|
auto otherParticipantStateValue = call
|
||||||
|
? call->otherParticipantStateValue(
|
||||||
|
) | rpl::filter([=](const Group::ParticipantState &data) {
|
||||||
|
return data.user == user;
|
||||||
|
})
|
||||||
|
: rpl::never<Group::ParticipantState>();
|
||||||
|
|
||||||
|
auto volumeItem = base::make_unique_q<MenuVolumeItem>(
|
||||||
|
result,
|
||||||
|
st::groupCallPopupMenu.menu,
|
||||||
|
otherParticipantStateValue,
|
||||||
|
real->volume(),
|
||||||
|
Group::kMaxVolume,
|
||||||
|
(muteState == Row::State::Muted
|
||||||
|
|| muteState == Row::State::MutedByMe));
|
||||||
|
|
||||||
|
volumeItem->toggleMuteRequests(
|
||||||
|
) | rpl::start_with_next([=](bool muted) {
|
||||||
|
toggleMute_(muted, false);
|
||||||
|
}, volumeItem->lifetime());
|
||||||
|
|
||||||
|
volumeItem->toggleMuteLocallyRequests(
|
||||||
|
) | rpl::start_with_next([=](bool muted) {
|
||||||
|
toggleMute_(muted, true);
|
||||||
|
}, volumeItem->lifetime());
|
||||||
|
|
||||||
|
volumeItem->changeVolumeRequests(
|
||||||
|
) | rpl::start_with_next([=](int volume) {
|
||||||
|
changeVolume(volume, false);
|
||||||
|
}, volumeItem->lifetime());
|
||||||
|
|
||||||
|
volumeItem->changeVolumeLocallyRequests(
|
||||||
|
) | rpl::start_with_next([=](int volume) {
|
||||||
|
changeVolume(volume, true);
|
||||||
|
}, volumeItem->lifetime());
|
||||||
|
|
||||||
|
result->addAction(std::move(volumeItem));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result->addAction(
|
result->addAction(
|
||||||
tr::lng_context_view_profile(tr::now),
|
tr::lng_context_view_profile(tr::now),
|
||||||
|
|
170
Telegram/SourceFiles/calls/calls_volume_item.cpp
Normal file
170
Telegram/SourceFiles/calls/calls_volume_item.cpp
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
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_volume_item.h"
|
||||||
|
|
||||||
|
#include "calls/calls_group_common.h"
|
||||||
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
|
#include "styles/style_calls.h"
|
||||||
|
#include "styles/style_media_player.h"
|
||||||
|
|
||||||
|
namespace Calls {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kMaxVolumePercent = 200;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
MenuVolumeItem::MenuVolumeItem(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
const style::Menu &st,
|
||||||
|
rpl::producer<Group::ParticipantState> participantState,
|
||||||
|
int startVolume,
|
||||||
|
int maxVolume,
|
||||||
|
bool muted)
|
||||||
|
: Ui::Menu::ItemBase(parent, st)
|
||||||
|
, _maxVolume(maxVolume)
|
||||||
|
, _cloudMuted(muted)
|
||||||
|
, _localMuted(muted)
|
||||||
|
, _slider(base::make_unique_q<Ui::MediaSlider>(
|
||||||
|
this,
|
||||||
|
st::mediaPlayerPanelPlayback))
|
||||||
|
, _dummyAction(new QAction(parent))
|
||||||
|
, _font(st.itemStyle.font) {
|
||||||
|
|
||||||
|
initResizeHook(parent->sizeValue());
|
||||||
|
enableMouseSelecting();
|
||||||
|
|
||||||
|
paintRequest(
|
||||||
|
) | rpl::start_with_next([=](const QRect &clip) {
|
||||||
|
Painter p(this);
|
||||||
|
|
||||||
|
const auto enabled = isEnabled();
|
||||||
|
const auto selected = isSelected();
|
||||||
|
p.fillRect(clip, selected ? st.itemBgOver : st.itemBg);
|
||||||
|
p.setPen(_localMuted
|
||||||
|
? (selected ? st::attentionButtonFgOver : st::attentionButtonFg)
|
||||||
|
: selected
|
||||||
|
? st.itemFgOver
|
||||||
|
: (enabled ? st.itemFg : st.itemFgDisabled));
|
||||||
|
p.setFont(_font);
|
||||||
|
const auto volume = std::round(_slider->value() * kMaxVolumePercent);
|
||||||
|
p.drawText(QPoint(0, _font->ascent), u"%1%"_q.arg(volume));
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
setCloudVolume(startVolume);
|
||||||
|
|
||||||
|
_slider->setChangeProgressCallback([=](float64 value) {
|
||||||
|
const auto newMuted = (value == 0);
|
||||||
|
if (_localMuted != newMuted) {
|
||||||
|
_localMuted = newMuted;
|
||||||
|
_toggleMuteLocallyRequests.fire_copy(newMuted);
|
||||||
|
}
|
||||||
|
if (value > 0) {
|
||||||
|
_changeVolumeLocallyRequests.fire(value * _maxVolume);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto returnVolume = [=] {
|
||||||
|
_changeVolumeLocallyRequests.fire_copy(_cloudVolume);
|
||||||
|
crl::on_main(_slider.get(), [=] {
|
||||||
|
setSliderVolume(_cloudVolume);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_slider->setChangeFinishedCallback([=](float64 value) {
|
||||||
|
const auto newVolume = std::round(value * _maxVolume);
|
||||||
|
const auto muted = (value == 0);
|
||||||
|
|
||||||
|
if (!_cloudMuted && muted) {
|
||||||
|
returnVolume();
|
||||||
|
_localMuted = true;
|
||||||
|
_toggleMuteRequests.fire(true);
|
||||||
|
}
|
||||||
|
if (_cloudMuted && muted) {
|
||||||
|
returnVolume();
|
||||||
|
}
|
||||||
|
if (_cloudMuted && !muted) {
|
||||||
|
_waitingForUpdateVolume = true;
|
||||||
|
_localMuted = false;
|
||||||
|
_toggleMuteRequests.fire(false);
|
||||||
|
}
|
||||||
|
if (!_cloudMuted && !muted) {
|
||||||
|
_changeVolumeRequests.fire_copy(newVolume);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
std::move(
|
||||||
|
participantState
|
||||||
|
) | rpl::start_with_next([=](const Group::ParticipantState &state) {
|
||||||
|
const auto newMuted = state.mutedByMe;
|
||||||
|
const auto newVolume = state.volume.value_or(0);
|
||||||
|
|
||||||
|
_cloudMuted = _localMuted = newMuted;
|
||||||
|
|
||||||
|
if (!newVolume) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_waitingForUpdateVolume) {
|
||||||
|
const auto localVolume =
|
||||||
|
std::round(_slider->value() * _maxVolume);
|
||||||
|
if ((localVolume != newVolume)
|
||||||
|
&& (_cloudVolume == newVolume)) {
|
||||||
|
_changeVolumeRequests.fire(localVolume);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setCloudVolume(newVolume);
|
||||||
|
}
|
||||||
|
_waitingForUpdateVolume = false;
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_slider->setGeometry(rect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuVolumeItem::setCloudVolume(int volume) {
|
||||||
|
if (_cloudVolume == volume) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_cloudVolume = volume;
|
||||||
|
if (!_slider->isChanging()) {
|
||||||
|
setSliderVolume(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuVolumeItem::setSliderVolume(int volume) {
|
||||||
|
_slider->setValue(float64(volume) / _maxVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<QAction*> MenuVolumeItem::action() const {
|
||||||
|
return _dummyAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MenuVolumeItem::isEnabled() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MenuVolumeItem::contentHeight() const {
|
||||||
|
return st::groupCallMenuVolumeItemHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> MenuVolumeItem::toggleMuteRequests() const {
|
||||||
|
return _toggleMuteRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> MenuVolumeItem::toggleMuteLocallyRequests() const {
|
||||||
|
return _toggleMuteLocallyRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> MenuVolumeItem::changeVolumeRequests() const {
|
||||||
|
return _changeVolumeRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<int> MenuVolumeItem::changeVolumeLocallyRequests() const {
|
||||||
|
return _changeVolumeLocallyRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Calls
|
67
Telegram/SourceFiles/calls/calls_volume_item.h
Normal file
67
Telegram/SourceFiles/calls/calls_volume_item.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
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 "ui/rp_widget.h"
|
||||||
|
#include "ui/widgets/menu/menu_item_base.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MediaSlider;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Calls {
|
||||||
|
|
||||||
|
namespace Group {
|
||||||
|
struct MuteRequest;
|
||||||
|
struct VolumeRequest;
|
||||||
|
struct ParticipantState;
|
||||||
|
} // namespace Group
|
||||||
|
|
||||||
|
class MenuVolumeItem final : public Ui::Menu::ItemBase {
|
||||||
|
public:
|
||||||
|
MenuVolumeItem(
|
||||||
|
not_null<RpWidget*> parent,
|
||||||
|
const style::Menu &st,
|
||||||
|
rpl::producer<Group::ParticipantState> participantState,
|
||||||
|
int startVolume,
|
||||||
|
int maxVolume,
|
||||||
|
bool muted);
|
||||||
|
|
||||||
|
not_null<QAction*> action() const override;
|
||||||
|
bool isEnabled() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<bool> toggleMuteRequests() const;
|
||||||
|
[[nodiscard]] rpl::producer<bool> toggleMuteLocallyRequests() const;
|
||||||
|
[[nodiscard]] rpl::producer<int> changeVolumeRequests() const;
|
||||||
|
[[nodiscard]] rpl::producer<int> changeVolumeLocallyRequests() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int contentHeight() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setCloudVolume(int volume);
|
||||||
|
void setSliderVolume(int volume);
|
||||||
|
|
||||||
|
const int _maxVolume;
|
||||||
|
int _cloudVolume = 0;
|
||||||
|
bool _waitingForUpdateVolume = false;
|
||||||
|
bool _cloudMuted = false;
|
||||||
|
bool _localMuted = false;
|
||||||
|
|
||||||
|
const base::unique_qptr<Ui::MediaSlider> _slider;
|
||||||
|
const not_null<QAction*> _dummyAction;
|
||||||
|
const style::font &_font;
|
||||||
|
|
||||||
|
rpl::event_stream<bool> _toggleMuteRequests;
|
||||||
|
rpl::event_stream<bool> _toggleMuteLocallyRequests;
|
||||||
|
rpl::event_stream<int> _changeVolumeRequests;
|
||||||
|
rpl::event_stream<int> _changeVolumeLocallyRequests;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Calls
|
Loading…
Add table
Reference in a new issue