Share instead of Settings for scheduled voice chats.
This commit is contained in:
parent
96bc4858c1
commit
65dd9b82c0
10 changed files with 118 additions and 50 deletions
BIN
Telegram/Resources/icons/calls/group_calls_share.png
Normal file
BIN
Telegram/Resources/icons/calls/group_calls_share.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 566 B |
BIN
Telegram/Resources/icons/calls/group_calls_share@2x.png
Normal file
BIN
Telegram/Resources/icons/calls/group_calls_share@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
BIN
Telegram/Resources/icons/calls/group_calls_share@3x.png
Normal file
BIN
Telegram/Resources/icons/calls/group_calls_share@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -1982,6 +1982,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_group_call_inactive" = "listening";
|
"lng_group_call_inactive" = "listening";
|
||||||
"lng_group_call_raised_hand_status" = "wants to speak";
|
"lng_group_call_raised_hand_status" = "wants to speak";
|
||||||
"lng_group_call_settings" = "Settings";
|
"lng_group_call_settings" = "Settings";
|
||||||
|
"lng_group_call_share_button" = "Share";
|
||||||
"lng_group_call_unmute" = "Unmute";
|
"lng_group_call_unmute" = "Unmute";
|
||||||
"lng_group_call_unmute_sub" = "or hold spacebar to talk";
|
"lng_group_call_unmute_sub" = "or hold spacebar to talk";
|
||||||
"lng_group_call_you_are_live" = "You are Live";
|
"lng_group_call_you_are_live" = "You are Live";
|
||||||
|
|
|
@ -685,13 +685,19 @@ groupCallMemberInvited: icon {{ "calls/group_calls_invited", groupCallMemberInac
|
||||||
groupCallMemberInvitedPosition: point(2px, 12px);
|
groupCallMemberInvitedPosition: point(2px, 12px);
|
||||||
groupCallMemberRaisedHand: icon {{ "calls/group_calls_raised_hand", groupCallMemberInactiveStatus }};
|
groupCallMemberRaisedHand: icon {{ "calls/group_calls_raised_hand", groupCallMemberInactiveStatus }};
|
||||||
|
|
||||||
|
groupCallSettingsInner: IconButton(callButton) {
|
||||||
|
iconPosition: point(-1px, 22px);
|
||||||
|
icon: icon {{ "calls/call_settings", groupCallIconFg }};
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: callMuteRipple;
|
||||||
|
}
|
||||||
|
}
|
||||||
groupCallSettings: CallButton(callMicrophoneMute) {
|
groupCallSettings: CallButton(callMicrophoneMute) {
|
||||||
button: IconButton(callButton) {
|
button: groupCallSettingsInner;
|
||||||
iconPosition: point(-1px, 22px);
|
}
|
||||||
icon: icon {{ "calls/call_settings", groupCallIconFg }};
|
groupCallShare: CallButton(groupCallSettings) {
|
||||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
button: IconButton(groupCallSettingsInner) {
|
||||||
color: callMuteRipple;
|
icon: icon {{ "calls/group_calls_share", groupCallIconFg }};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
groupCallHangup: CallButton(callHangup) {
|
groupCallHangup: CallButton(callHangup) {
|
||||||
|
|
|
@ -244,6 +244,9 @@ GroupCall::GroupCall(
|
||||||
} else {
|
} else {
|
||||||
start(info.scheduleDate);
|
start(info.scheduleDate);
|
||||||
}
|
}
|
||||||
|
if (_scheduleDate) {
|
||||||
|
saveDefaultJoinAs(_joinAs);
|
||||||
|
}
|
||||||
|
|
||||||
_mediaDevices->audioInputId(
|
_mediaDevices->audioInputId(
|
||||||
) | rpl::start_with_next([=](QString id) {
|
) | rpl::start_with_next([=](QString id) {
|
||||||
|
@ -465,6 +468,14 @@ void GroupCall::setJoinAs(not_null<PeerData*> as) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCall::saveDefaultJoinAs(not_null<PeerData*> as) {
|
||||||
|
setJoinAs(as);
|
||||||
|
_api.request(MTPphone_SaveDefaultGroupCallJoinAs(
|
||||||
|
_peer->input,
|
||||||
|
_joinAs->input
|
||||||
|
)).send();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::rejoin(not_null<PeerData*> as) {
|
void GroupCall::rejoin(not_null<PeerData*> as) {
|
||||||
if (state() != State::Joining
|
if (state() != State::Joining
|
||||||
&& state() != State::Joined
|
&& state() != State::Joined
|
||||||
|
@ -695,11 +706,7 @@ void GroupCall::rejoinAs(Group::JoinInfo info) {
|
||||||
.nowJoinAs = info.joinAs,
|
.nowJoinAs = info.joinAs,
|
||||||
};
|
};
|
||||||
if (_scheduleDate) {
|
if (_scheduleDate) {
|
||||||
setJoinAs(info.joinAs);
|
saveDefaultJoinAs(info.joinAs);
|
||||||
_api.request(MTPphone_SaveDefaultGroupCallJoinAs(
|
|
||||||
_peer->input,
|
|
||||||
_joinAs->input
|
|
||||||
)).send();
|
|
||||||
} else {
|
} else {
|
||||||
setState(State::Joining);
|
setState(State::Joining);
|
||||||
rejoin(info.joinAs);
|
rejoin(info.joinAs);
|
||||||
|
|
|
@ -256,6 +256,7 @@ private:
|
||||||
void rejoin();
|
void rejoin();
|
||||||
void rejoin(not_null<PeerData*> as);
|
void rejoin(not_null<PeerData*> as);
|
||||||
void setJoinAs(not_null<PeerData*> as);
|
void setJoinAs(not_null<PeerData*> as);
|
||||||
|
void saveDefaultJoinAs(not_null<PeerData*> as);
|
||||||
void subscribeToReal(not_null<Data::GroupCall*> real);
|
void subscribeToReal(not_null<Data::GroupCall*> real);
|
||||||
|
|
||||||
void audioLevelsUpdated(const tgcalls::GroupLevelsUpdate &data);
|
void audioLevelsUpdated(const tgcalls::GroupLevelsUpdate &data);
|
||||||
|
|
|
@ -175,13 +175,13 @@ private:
|
||||||
})) | rpl::flatten_latest();
|
})) | rpl::flatten_latest();
|
||||||
|
|
||||||
if (tillTomorrow > 0) {
|
if (tillTomorrow > 0) {
|
||||||
return std::move(full);
|
return full;
|
||||||
} else if (tillToday > 0) {
|
} else if (tillToday > 0) {
|
||||||
return std::move(tomorrowAndAfter);
|
return tomorrowAndAfter;
|
||||||
} else if (tillAfter > 0) {
|
} else if (tillAfter > 0) {
|
||||||
return std::move(todayAndAfter);
|
return todayAndAfter;
|
||||||
} else {
|
} else {
|
||||||
return std::move(exact);
|
return exact;
|
||||||
}
|
}
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
}
|
}
|
||||||
|
@ -381,7 +381,6 @@ Panel::Panel(not_null<GroupCall*> call)
|
||||||
_window->body(),
|
_window->body(),
|
||||||
st::groupCallTitle))
|
st::groupCallTitle))
|
||||||
#endif // !Q_OS_MAC
|
#endif // !Q_OS_MAC
|
||||||
, _settings(widget(), st::groupCallSettings)
|
|
||||||
, _mute(std::make_unique<Ui::CallMuteButton>(
|
, _mute(std::make_unique<Ui::CallMuteButton>(
|
||||||
widget(),
|
widget(),
|
||||||
Core::App().appDeactivatedValue(),
|
Core::App().appDeactivatedValue(),
|
||||||
|
@ -395,7 +394,6 @@ Panel::Panel(not_null<GroupCall*> call)
|
||||||
}))
|
}))
|
||||||
, _hangup(widget(), st::groupCallHangup) {
|
, _hangup(widget(), st::groupCallHangup) {
|
||||||
_layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox);
|
_layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox);
|
||||||
_settings->setColorOverrides(_mute->colorOverrides());
|
|
||||||
_layerBg->setHideByBackgroundClick(true);
|
_layerBg->setHideByBackgroundClick(true);
|
||||||
|
|
||||||
SubscribeToMigration(
|
SubscribeToMigration(
|
||||||
|
@ -591,12 +589,11 @@ void Panel::initControls() {
|
||||||
_call->setMutedAndUpdate(newState);
|
_call->setMutedAndUpdate(newState);
|
||||||
}, _mute->lifetime());
|
}, _mute->lifetime());
|
||||||
|
|
||||||
_hangup->setClickedCallback([=] { endCall(); });
|
initShareAction();
|
||||||
_settings->setClickedCallback([=] {
|
refreshLeftButton();
|
||||||
_layerBg->showBox(Box(SettingsBox, _call));
|
|
||||||
});
|
_hangup->setClickedCallback([=] { endCall(); });
|
||||||
|
|
||||||
_settings->setText(tr::lng_group_call_settings());
|
|
||||||
const auto scheduleDate = _call->scheduleDate();
|
const auto scheduleDate = _call->scheduleDate();
|
||||||
_hangup->setText(scheduleDate
|
_hangup->setText(scheduleDate
|
||||||
? tr::lng_group_call_close()
|
? tr::lng_group_call_close()
|
||||||
|
@ -606,12 +603,27 @@ void Panel::initControls() {
|
||||||
) | rpl::map([=](not_null<Data::GroupCall*> real) {
|
) | rpl::map([=](not_null<Data::GroupCall*> real) {
|
||||||
return real->scheduleDateValue();
|
return real->scheduleDateValue();
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
|
|
||||||
setupScheduledLabels(rpl::single(
|
setupScheduledLabels(rpl::single(
|
||||||
scheduleDate
|
scheduleDate
|
||||||
) | rpl::then(rpl::duplicate(changes)));
|
) | rpl::then(rpl::duplicate(changes)));
|
||||||
std::move(changes) | rpl::filter([](TimeId date) {
|
|
||||||
|
auto started = std::move(changes) | rpl::filter([](TimeId date) {
|
||||||
return (date == 0);
|
return (date == 0);
|
||||||
}) | rpl::take(1) | rpl::start_with_next([=] {
|
}) | rpl::take(1);
|
||||||
|
|
||||||
|
rpl::merge(
|
||||||
|
rpl::duplicate(started) | rpl::to_empty,
|
||||||
|
_peer->session().changes().peerFlagsValue(
|
||||||
|
_peer,
|
||||||
|
Data::PeerUpdate::Flag::Username
|
||||||
|
) | rpl::skip(1) | rpl::to_empty
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
refreshLeftButton();
|
||||||
|
updateControlsGeometry();
|
||||||
|
}, _callLifetime);
|
||||||
|
|
||||||
|
std::move(started) | rpl::start_with_next([=] {
|
||||||
_hangup->setText(tr::lng_group_call_leave());
|
_hangup->setText(tr::lng_group_call_leave());
|
||||||
setupMembers();
|
setupMembers();
|
||||||
}, _callLifetime);
|
}, _callLifetime);
|
||||||
|
@ -640,6 +652,53 @@ void Panel::initControls() {
|
||||||
}, _callLifetime);
|
}, _callLifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Panel::refreshLeftButton() {
|
||||||
|
const auto share = _call->scheduleDate()
|
||||||
|
&& _peer->isBroadcast()
|
||||||
|
&& _peer->asChannel()->hasUsername();
|
||||||
|
if ((share && _share) || (!share && _settings)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (share) {
|
||||||
|
_settings.destroy();
|
||||||
|
_share.create(widget(), st::groupCallShare);
|
||||||
|
_share->setClickedCallback(_shareLinkCallback);
|
||||||
|
_share->setText(tr::lng_group_call_share_button());
|
||||||
|
} else {
|
||||||
|
_share.destroy();
|
||||||
|
_settings.create(widget(), st::groupCallSettings);
|
||||||
|
_settings->setClickedCallback([=] {
|
||||||
|
_layerBg->showBox(Box(SettingsBox, _call));
|
||||||
|
});
|
||||||
|
_settings->setText(tr::lng_group_call_settings());
|
||||||
|
}
|
||||||
|
const auto raw = _share ? _share.data() : _settings.data();
|
||||||
|
raw->show();
|
||||||
|
raw->setColorOverrides(_mute->colorOverrides());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Panel::initShareAction() {
|
||||||
|
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);
|
||||||
|
_shareLinkCallback = [=, callback = std::move(shareLinkCallback)] {
|
||||||
|
if (_call->lookupReal()) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
widget()->lifetime().add(std::move(shareLinkLifetime));
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
|
void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
|
||||||
using namespace rpl::mappers;
|
using namespace rpl::mappers;
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
|
@ -792,26 +851,10 @@ void Panel::setupMembers() {
|
||||||
kickParticipant(participantPeer);
|
kickParticipant(participantPeer);
|
||||||
}, _callLifetime);
|
}, _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(
|
_members->addMembersRequests(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
if (_peer->isBroadcast() && _peer->asChannel()->hasUsername()) {
|
if (_peer->isBroadcast() && _peer->asChannel()->hasUsername()) {
|
||||||
shareLink();
|
_shareLinkCallback();
|
||||||
} else {
|
} else {
|
||||||
addMembers();
|
addMembers();
|
||||||
}
|
}
|
||||||
|
@ -1304,18 +1347,24 @@ QRect Panel::computeTitleRect() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::updateControlsGeometry() {
|
void Panel::updateControlsGeometry() {
|
||||||
if (widget()->size().isEmpty()) {
|
if (widget()->size().isEmpty() || (!_settings && !_share)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||||
const auto buttonsTop = widget()->height() - st::groupCallButtonBottomSkip;
|
const auto buttonsTop = widget()->height() - st::groupCallButtonBottomSkip;
|
||||||
const auto muteSize = _mute->innerSize().width();
|
const auto muteSize = _mute->innerSize().width();
|
||||||
const auto fullWidth = muteSize
|
const auto fullWidth = muteSize
|
||||||
+ 2 * _settings->width()
|
+ 2 * (_settings ? _settings : _share)->width()
|
||||||
+ 2 * st::groupCallButtonSkip;
|
+ 2 * st::groupCallButtonSkip;
|
||||||
_mute->moveInner({ (widget()->width() - muteSize) / 2, muteTop });
|
_mute->moveInner({ (widget()->width() - muteSize) / 2, muteTop });
|
||||||
_settings->moveToLeft((widget()->width() - fullWidth) / 2, buttonsTop);
|
const auto leftButtonLeft = (widget()->width() - fullWidth) / 2;
|
||||||
_hangup->moveToRight((widget()->width() - fullWidth) / 2, buttonsTop);
|
if (_settings) {
|
||||||
|
_settings->moveToLeft(leftButtonLeft, buttonsTop);
|
||||||
|
}
|
||||||
|
if (_share) {
|
||||||
|
_share->moveToLeft(leftButtonLeft, buttonsTop);
|
||||||
|
}
|
||||||
|
_hangup->moveToRight(leftButtonLeft, buttonsTop);
|
||||||
|
|
||||||
updateMembersGeometry();
|
updateMembersGeometry();
|
||||||
refreshTitle();
|
refreshTitle();
|
||||||
|
|
|
@ -74,6 +74,7 @@ private:
|
||||||
void initWindow();
|
void initWindow();
|
||||||
void initWidget();
|
void initWidget();
|
||||||
void initControls();
|
void initControls();
|
||||||
|
void initShareAction();
|
||||||
void initLayout();
|
void initLayout();
|
||||||
void initGeometry();
|
void initGeometry();
|
||||||
void setupScheduledLabels(rpl::producer<TimeId> date);
|
void setupScheduledLabels(rpl::producer<TimeId> date);
|
||||||
|
@ -89,6 +90,7 @@ private:
|
||||||
void updateControlsGeometry();
|
void updateControlsGeometry();
|
||||||
void updateMembersGeometry();
|
void updateMembersGeometry();
|
||||||
void showControls();
|
void showControls();
|
||||||
|
void refreshLeftButton();
|
||||||
|
|
||||||
void endCall();
|
void endCall();
|
||||||
|
|
||||||
|
@ -131,9 +133,11 @@ private:
|
||||||
object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
|
object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
|
||||||
ChooseJoinAsProcess _joinAsProcess;
|
ChooseJoinAsProcess _joinAsProcess;
|
||||||
|
|
||||||
object_ptr<Ui::CallButton> _settings;
|
object_ptr<Ui::CallButton> _settings = { nullptr };
|
||||||
|
object_ptr<Ui::CallButton> _share = { nullptr };
|
||||||
std::unique_ptr<Ui::CallMuteButton> _mute;
|
std::unique_ptr<Ui::CallMuteButton> _mute;
|
||||||
object_ptr<Ui::CallButton> _hangup;
|
object_ptr<Ui::CallButton> _hangup;
|
||||||
|
Fn<void()> _shareLinkCallback;
|
||||||
|
|
||||||
rpl::lifetime _peerLifetime;
|
rpl::lifetime _peerLifetime;
|
||||||
|
|
||||||
|
|
|
@ -676,7 +676,7 @@ std::pair<Fn<void()>, rpl::lifetime> ShareInviteLinkAction(
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
auto callback = [=] {
|
auto callback = [=] {
|
||||||
const auto real = peer->groupCall();
|
const auto real = peer->migrateToOrMe()->groupCall();
|
||||||
if (shareReady() || state->generatingLink || !real) {
|
if (shareReady() || state->generatingLink || !real) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -701,11 +701,11 @@ std::pair<Fn<void()>, rpl::lifetime> ShareInviteLinkAction(
|
||||||
state->linkSpeakerRequestId = peer->session().api().request(
|
state->linkSpeakerRequestId = peer->session().api().request(
|
||||||
MTPphone_ExportGroupCallInvite(
|
MTPphone_ExportGroupCallInvite(
|
||||||
MTP_flags(Flag::f_can_self_unmute),
|
MTP_flags(Flag::f_can_self_unmute),
|
||||||
real->input()
|
real->input())
|
||||||
)).done([=](const MTPphone_ExportedGroupCallInvite &result) {
|
).done([=](const MTPphone_ExportedGroupCallInvite &result) {
|
||||||
state->linkSpeakerRequestId = 0;
|
state->linkSpeakerRequestId = 0;
|
||||||
result.match([&](
|
result.match([&](
|
||||||
const MTPDphone_exportedGroupCallInvite &data) {
|
const MTPDphone_exportedGroupCallInvite &data) {
|
||||||
state->linkSpeaker = qs(data.vlink());
|
state->linkSpeaker = qs(data.vlink());
|
||||||
shareReady();
|
shareReady();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue