Add edit voice chat title.
This commit is contained in:
parent
b670ca2a51
commit
bc43168ca7
|
@ -505,6 +505,27 @@ groupCallMultiSelect: MultiSelect(defaultMultiSelect) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupCallField: InputField(defaultInputField) {
|
||||||
|
textMargins: margins(2px, 7px, 2px, 0px);
|
||||||
|
|
||||||
|
textBg: transparent;
|
||||||
|
textFg: groupCallMembersFg;
|
||||||
|
|
||||||
|
placeholderFg: groupCallMemberNotJoinedStatus;
|
||||||
|
placeholderFgActive: groupCallMemberNotJoinedStatus;
|
||||||
|
placeholderFgError: groupCallMemberNotJoinedStatus;
|
||||||
|
placeholderMargins: margins(2px, 0px, 2px, 0px);
|
||||||
|
placeholderScale: 0.;
|
||||||
|
placeholderFont: normalFont;
|
||||||
|
heightMin: 32px;
|
||||||
|
|
||||||
|
borderFg: inputBorderFg;
|
||||||
|
borderFgActive: groupCallMemberInactiveStatus;
|
||||||
|
borderFgError: activeLineFgError;
|
||||||
|
|
||||||
|
menu: groupCallPopupMenu;
|
||||||
|
}
|
||||||
|
|
||||||
groupCallMembersTop: 62px;
|
groupCallMembersTop: 62px;
|
||||||
groupCallTitleTop: 14px;
|
groupCallTitleTop: 14px;
|
||||||
groupCallSubtitleTop: 33px;
|
groupCallSubtitleTop: 33px;
|
||||||
|
|
|
@ -705,6 +705,22 @@ void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCall::changeTitle(const QString &title) {
|
||||||
|
const auto real = _peer->groupCall();
|
||||||
|
if (!real || real->id() != _id || real->title() == title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
real->setTitle(title);
|
||||||
|
_api.request(MTPphone_EditGroupCallTitle(
|
||||||
|
inputCall(),
|
||||||
|
MTP_string(title)
|
||||||
|
)).done([=](const MTPUpdates &result) {
|
||||||
|
_peer->session().api().applyUpdates(result);
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::createAndStartController() {
|
void GroupCall::createAndStartController() {
|
||||||
const auto &settings = Core::App().settings();
|
const auto &settings = Core::App().settings();
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ public:
|
||||||
void join(const MTPInputGroupCall &inputCall);
|
void join(const MTPInputGroupCall &inputCall);
|
||||||
void handleUpdate(const MTPGroupCall &call);
|
void handleUpdate(const MTPGroupCall &call);
|
||||||
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
|
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
|
||||||
|
void changeTitle(const QString &title);
|
||||||
|
|
||||||
void setMuted(MuteState mute);
|
void setMuted(MuteState mute);
|
||||||
[[nodiscard]] MuteState muted() const {
|
[[nodiscard]] MuteState muted() const {
|
||||||
|
|
|
@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_group_call.h"
|
#include "data/data_group_call.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_changes.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "base/event_filter.h"
|
#include "base/event_filter.h"
|
||||||
#include "boxes/peers/edit_participants_box.h"
|
#include "boxes/peers/edit_participants_box.h"
|
||||||
|
@ -324,6 +325,7 @@ GroupPanel::GroupPanel(not_null<GroupCall*> call)
|
||||||
_peer,
|
_peer,
|
||||||
_window->lifetime(),
|
_window->lifetime(),
|
||||||
[=](not_null<ChannelData*> channel) { migrate(channel); });
|
[=](not_null<ChannelData*> channel) { migrate(channel); });
|
||||||
|
setupRealCallViewers(call);
|
||||||
|
|
||||||
initWindow();
|
initWindow();
|
||||||
initWidget();
|
initWidget();
|
||||||
|
@ -334,6 +336,22 @@ GroupPanel::GroupPanel(not_null<GroupCall*> call)
|
||||||
|
|
||||||
GroupPanel::~GroupPanel() = default;
|
GroupPanel::~GroupPanel() = default;
|
||||||
|
|
||||||
|
void GroupPanel::setupRealCallViewers(not_null<GroupCall*> call) {
|
||||||
|
const auto peer = call->peer();
|
||||||
|
peer->session().changes().peerFlagsValue(
|
||||||
|
peer,
|
||||||
|
Data::PeerUpdate::Flag::GroupCall
|
||||||
|
) | rpl::map([=] {
|
||||||
|
return peer->groupCall();
|
||||||
|
}) | rpl::filter([=](Data::GroupCall *real) {
|
||||||
|
return _call && real && (real->id() == _call->id());
|
||||||
|
}) | rpl::take(
|
||||||
|
1
|
||||||
|
) | rpl::start_with_next([=](not_null<Data::GroupCall*> real) {
|
||||||
|
subscribeToChanges(real);
|
||||||
|
}, _window->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
bool GroupPanel::isActive() const {
|
bool GroupPanel::isActive() const {
|
||||||
return _window->isActiveWindow()
|
return _window->isActiveWindow()
|
||||||
&& _window->isVisible()
|
&& _window->isVisible()
|
||||||
|
@ -565,6 +583,10 @@ void GroupPanel::initWithCall(GroupCall *call) {
|
||||||
}, _callLifetime);
|
}, _callLifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupPanel::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||||
|
_titleText = real->titleValue();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupPanel::addMembers() {
|
void GroupPanel::addMembers() {
|
||||||
const auto real = _peer->groupCall();
|
const auto real = _peer->groupCall();
|
||||||
if (!_call || !real || real->id() != _call->id()) {
|
if (!_call || !real || real->id() != _call->id()) {
|
||||||
|
@ -829,32 +851,26 @@ void GroupPanel::updateControlsGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupPanel::refreshTitle() {
|
void GroupPanel::refreshTitle() {
|
||||||
if (const auto titleRect = computeTitleRect()) {
|
if (computeTitleRect().has_value()) {
|
||||||
if (!_title) {
|
if (!_title) {
|
||||||
|
auto text = rpl::combine(
|
||||||
|
Info::Profile::NameValue(_peer),
|
||||||
|
_titleText.value()
|
||||||
|
) | rpl::map([=](
|
||||||
|
const TextWithEntities &name,
|
||||||
|
const QString &title) {
|
||||||
|
return title.isEmpty() ? name.text : title;
|
||||||
|
}) | rpl::after_next([=] {
|
||||||
|
refreshTitleGeometry();
|
||||||
|
});
|
||||||
_title.create(
|
_title.create(
|
||||||
widget(),
|
widget(),
|
||||||
Info::Profile::NameValue(_peer),
|
rpl::duplicate(text),
|
||||||
st::groupCallTitleLabel);
|
st::groupCallTitleLabel);
|
||||||
_title->show();
|
_title->show();
|
||||||
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
|
_title->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
}
|
}
|
||||||
const auto best = _title->naturalWidth();
|
refreshTitleGeometry();
|
||||||
const auto from = (widget()->width() - best) / 2;
|
|
||||||
const auto top = st::groupCallTitleTop;
|
|
||||||
const auto left = titleRect->x();
|
|
||||||
if (from >= left && from + best <= left + titleRect->width()) {
|
|
||||||
_title->resizeToWidth(best);
|
|
||||||
_title->moveToLeft(from, top);
|
|
||||||
} else if (titleRect->width() < best) {
|
|
||||||
_title->resizeToWidth(titleRect->width());
|
|
||||||
_title->moveToLeft(left, top);
|
|
||||||
} else if (from < left) {
|
|
||||||
_title->resizeToWidth(best);
|
|
||||||
_title->moveToLeft(left, top);
|
|
||||||
} else {
|
|
||||||
_title->resizeToWidth(best);
|
|
||||||
_title->moveToLeft(left + titleRect->width() - best, top);
|
|
||||||
}
|
|
||||||
} else if (_title) {
|
} else if (_title) {
|
||||||
_title.destroy();
|
_title.destroy();
|
||||||
}
|
}
|
||||||
|
@ -879,6 +895,30 @@ void GroupPanel::refreshTitle() {
|
||||||
top);
|
top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupPanel::refreshTitleGeometry() {
|
||||||
|
const auto titleRect = computeTitleRect();
|
||||||
|
if (!_title || !titleRect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto best = _title->naturalWidth();
|
||||||
|
const auto from = (widget()->width() - best) / 2;
|
||||||
|
const auto top = st::groupCallTitleTop;
|
||||||
|
const auto left = titleRect->x();
|
||||||
|
if (from >= left && from + best <= left + titleRect->width()) {
|
||||||
|
_title->resizeToWidth(best);
|
||||||
|
_title->moveToLeft(from, top);
|
||||||
|
} else if (titleRect->width() < best) {
|
||||||
|
_title->resizeToWidth(titleRect->width());
|
||||||
|
_title->moveToLeft(left, top);
|
||||||
|
} else if (from < left) {
|
||||||
|
_title->resizeToWidth(best);
|
||||||
|
_title->moveToLeft(left, top);
|
||||||
|
} else {
|
||||||
|
_title->resizeToWidth(best);
|
||||||
|
_title->moveToLeft(left + titleRect->width() - best, top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GroupPanel::paint(QRect clip) {
|
void GroupPanel::paint(QRect clip) {
|
||||||
Painter p(widget());
|
Painter p(widget());
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Image;
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
class CloudImageView;
|
class CloudImageView;
|
||||||
|
class GroupCall;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -100,6 +101,9 @@ private:
|
||||||
[[nodiscard]] int computeMembersListTop() const;
|
[[nodiscard]] int computeMembersListTop() const;
|
||||||
[[nodiscard]] std::optional<QRect> computeTitleRect() const;
|
[[nodiscard]] std::optional<QRect> computeTitleRect() const;
|
||||||
void refreshTitle();
|
void refreshTitle();
|
||||||
|
void refreshTitleGeometry();
|
||||||
|
void setupRealCallViewers(not_null<GroupCall*> call);
|
||||||
|
void subscribeToChanges(not_null<Data::GroupCall*> real);
|
||||||
|
|
||||||
void migrate(not_null<ChannelData*> channel);
|
void migrate(not_null<ChannelData*> channel);
|
||||||
void subscribeToPeerChanges();
|
void subscribeToPeerChanges();
|
||||||
|
@ -119,6 +123,7 @@ private:
|
||||||
object_ptr<Ui::FlatLabel> _title = { nullptr };
|
object_ptr<Ui::FlatLabel> _title = { nullptr };
|
||||||
object_ptr<Ui::FlatLabel> _subtitle = { nullptr };
|
object_ptr<Ui::FlatLabel> _subtitle = { nullptr };
|
||||||
object_ptr<GroupMembers> _members;
|
object_ptr<GroupMembers> _members;
|
||||||
|
rpl::variable<QString> _titleText;
|
||||||
|
|
||||||
object_ptr<Ui::CallButton> _settings;
|
object_ptr<Ui::CallButton> _settings;
|
||||||
std::unique_ptr<Ui::CallMuteButton> _mute;
|
std::unique_ptr<Ui::CallMuteButton> _mute;
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/level_meter.h"
|
#include "ui/widgets/level_meter.h"
|
||||||
#include "ui/widgets/continuous_sliders.h"
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/widgets/input_fields.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
|
@ -84,6 +85,28 @@ void SaveCallJoinMuted(
|
||||||
QString::number(delay / 1000., 'f', 2));
|
QString::number(delay / 1000., 'f', 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditGroupCallTitleBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
const QString &placeholder,
|
||||||
|
const QString &title,
|
||||||
|
Fn<void(QString)> done) {
|
||||||
|
box->setTitle(tr::lng_group_call_edit_title());
|
||||||
|
const auto input = box->addRow(object_ptr<Ui::InputField>(
|
||||||
|
box,
|
||||||
|
st::groupCallField,
|
||||||
|
rpl::single(placeholder),
|
||||||
|
title));
|
||||||
|
box->setFocusCallback([=] {
|
||||||
|
input->setFocusFast();
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_settings_save(), [=] {
|
||||||
|
const auto result = input->getLastText();
|
||||||
|
box->closeBox();
|
||||||
|
done(result);
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void GroupCallSettingsBox(
|
void GroupCallSettingsBox(
|
||||||
|
@ -119,6 +142,7 @@ void GroupCallSettingsBox(
|
||||||
const auto canChangeJoinMuted = (goodReal && real->canChangeJoinMuted());
|
const auto canChangeJoinMuted = (goodReal && real->canChangeJoinMuted());
|
||||||
const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted);
|
const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted);
|
||||||
const auto addEditJoinAs = (call->possibleJoinAs().size() > 1);
|
const auto addEditJoinAs = (call->possibleJoinAs().size() > 1);
|
||||||
|
const auto addEditTitle = peer->canManageGroupCall();
|
||||||
if (addCheck || addEditJoinAs) {
|
if (addCheck || addEditJoinAs) {
|
||||||
AddSkip(layout);
|
AddSkip(layout);
|
||||||
}
|
}
|
||||||
|
@ -128,6 +152,12 @@ void GroupCallSettingsBox(
|
||||||
tr::lng_group_call_display_as_header(),
|
tr::lng_group_call_display_as_header(),
|
||||||
st::groupCallSettingsButton).get()
|
st::groupCallSettingsButton).get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
const auto editTitle = (goodReal && addEditTitle)
|
||||||
|
? AddButton(
|
||||||
|
layout,
|
||||||
|
tr::lng_group_call_edit_title(),
|
||||||
|
st::groupCallSettingsButton).get()
|
||||||
|
: nullptr;
|
||||||
if (editJoinAs) {
|
if (editJoinAs) {
|
||||||
editJoinAs->setClickedCallback([=] {
|
editJoinAs->setClickedCallback([=] {
|
||||||
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
|
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
|
||||||
|
@ -145,6 +175,18 @@ void GroupCallSettingsBox(
|
||||||
call->joinAs());
|
call->joinAs());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (editTitle) {
|
||||||
|
editTitle->setClickedCallback([=] {
|
||||||
|
const auto done = [=](const QString &title) {
|
||||||
|
call->changeTitle(title);
|
||||||
|
};
|
||||||
|
box->getDelegate()->show(Box(
|
||||||
|
EditGroupCallTitleBox,
|
||||||
|
peer->name,
|
||||||
|
goodReal ? real->title() : QString(),
|
||||||
|
done));
|
||||||
|
});
|
||||||
|
}
|
||||||
const auto muteJoined = addCheck
|
const auto muteJoined = addCheck
|
||||||
? AddButton(
|
? AddButton(
|
||||||
layout,
|
layout,
|
||||||
|
|
|
@ -175,10 +175,12 @@ void GroupCall::applyUpdate(const MTPGroupCall &update) {
|
||||||
|
|
||||||
void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
|
void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
|
||||||
call.match([&](const MTPDgroupCall &data) {
|
call.match([&](const MTPDgroupCall &data) {
|
||||||
|
const auto title = qs(data.vtitle().value_or_empty());
|
||||||
const auto changed = (_version != data.vversion().v)
|
const auto changed = (_version != data.vversion().v)
|
||||||
|| (_fullCount.current() != data.vparticipants_count().v)
|
|| (_fullCount.current() != data.vparticipants_count().v)
|
||||||
|| (_joinMuted != data.is_join_muted())
|
|| (_joinMuted != data.is_join_muted())
|
||||||
|| (_canChangeJoinMuted != data.is_can_change_join_muted());
|
|| (_canChangeJoinMuted != data.is_can_change_join_muted())
|
||||||
|
|| (_title.current() != title);
|
||||||
if (!force && !changed) {
|
if (!force && !changed) {
|
||||||
return;
|
return;
|
||||||
} else if (!force && _version > data.vversion().v) {
|
} else if (!force && _version > data.vversion().v) {
|
||||||
|
@ -189,6 +191,7 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
|
||||||
_canChangeJoinMuted = data.is_can_change_join_muted();
|
_canChangeJoinMuted = data.is_can_change_join_muted();
|
||||||
_version = data.vversion().v;
|
_version = data.vversion().v;
|
||||||
_fullCount = data.vparticipants_count().v;
|
_fullCount = data.vparticipants_count().v;
|
||||||
|
_title = title;
|
||||||
changePeerEmptyCallFlag();
|
changePeerEmptyCallFlag();
|
||||||
}, [&](const MTPDgroupCallDiscarded &data) {
|
}, [&](const MTPDgroupCallDiscarded &data) {
|
||||||
const auto id = _id;
|
const auto id = _id;
|
||||||
|
|
|
@ -28,6 +28,15 @@ public:
|
||||||
[[nodiscard]] uint64 id() const;
|
[[nodiscard]] uint64 id() const;
|
||||||
[[nodiscard]] not_null<PeerData*> peer() const;
|
[[nodiscard]] not_null<PeerData*> peer() const;
|
||||||
[[nodiscard]] MTPInputGroupCall input() const;
|
[[nodiscard]] MTPInputGroupCall input() const;
|
||||||
|
[[nodiscard]] QString title() const {
|
||||||
|
return _title.current();
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<QString> titleValue() const {
|
||||||
|
return _title.value();
|
||||||
|
}
|
||||||
|
void setTitle(const QString &title) {
|
||||||
|
_title = title;
|
||||||
|
}
|
||||||
|
|
||||||
void setPeer(not_null<PeerData*> peer);
|
void setPeer(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
@ -105,6 +114,7 @@ private:
|
||||||
int _version = 0;
|
int _version = 0;
|
||||||
mtpRequestId _participantsRequestId = 0;
|
mtpRequestId _participantsRequestId = 0;
|
||||||
mtpRequestId _reloadRequestId = 0;
|
mtpRequestId _reloadRequestId = 0;
|
||||||
|
rpl::variable<QString> _title;
|
||||||
|
|
||||||
std::vector<Participant> _participants;
|
std::vector<Participant> _participants;
|
||||||
base::flat_map<uint32, not_null<PeerData*>> _participantPeerBySsrc;
|
base::flat_map<uint32, not_null<PeerData*>> _participantPeerBySsrc;
|
||||||
|
|
Loading…
Reference in New Issue