Add recording start/stop to Settings.

This commit is contained in:
John Preston 2021-03-09 13:27:17 +04:00
parent 5bea88fd66
commit 22aa57ad6f
6 changed files with 156 additions and 6 deletions

View file

@ -2000,6 +2000,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_recording_stop" = "Stop recording";
"lng_group_call_recording_started" = "Voice chat recording started.";
"lng_group_call_recording_stopped" = "Voice chat recording stopped.";
"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_start_field" = "Recording Title";
"lng_group_call_recording_start_button" = "Start";
"lng_group_call_is_recorded" = "Voice chat is being recorded";
"lng_group_call_can_speak_here" = "You can now speak.";
"lng_group_call_can_speak" = "You can now speak in **{chat}**.";
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";

View file

@ -876,6 +876,29 @@ void GroupCall::changeTitle(const QString &title) {
}).send();
}
void GroupCall::toggleRecording(bool enabled, const QString &title) {
const auto real = _peer->groupCall();
if (!real || real->id() != _id) {
return;
}
const auto already = (real->recordStartDate() != 0);
if (already == enabled) {
return;
}
using Flag = MTPphone_ToggleGroupCallRecord::Flag;
_api.request(MTPphone_ToggleGroupCallRecord(
MTP_flags((enabled ? Flag::f_start : Flag(0))
| (title.isEmpty() ? Flag(0) : Flag::f_title)),
inputCall(),
MTP_string(title)
)).done([=](const MTPUpdates &result) {
_peer->session().api().applyUpdates(result);
}).fail([=](const RPCError &error) {
}).send();
}
void GroupCall::ensureControllerCreated() {
if (_instance) {
return;

View file

@ -119,6 +119,7 @@ public:
void handleUpdate(const MTPGroupCall &call);
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
void changeTitle(const QString &title);
void toggleRecording(bool enabled, const QString &title);
void setMuted(MuteState mute);
void setMutedAndUpdate(MuteState mute);

View file

@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/event_filter.h"
#include "base/global_shortcuts.h"
#include "base/platform/base_platform_info.h"
#include "base/unixtime.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_group_call.h"
@ -100,13 +101,66 @@ void EditGroupCallTitleBox(
input->setFocusFast();
});
box->addButton(tr::lng_settings_save(), [=] {
const auto result = input->getLastText();
const auto result = input->getLastText().trimmed();
box->closeBox();
done(result);
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
}
void StartGroupCallRecordingBox(
not_null<Ui::GenericBox*> box,
const QString &title,
Fn<void(QString)> done) {
box->setTitle(tr::lng_group_call_recording_start());
box->addRow(
object_ptr<Ui::FlatLabel>(
box.get(),
tr::lng_group_call_recording_start_sure(),
st::groupCallBoxLabel));
const auto input = box->addRow(object_ptr<Ui::InputField>(
box,
st::groupCallField,
tr::lng_group_call_recording_start_field(),
title));
box->setFocusCallback([=] {
input->setFocusFast();
});
box->addButton(tr::lng_group_call_recording_start_button(), [=] {
const auto result = input->getLastText().trimmed();
if (result.isEmpty()) {
input->showError();
return;
}
box->closeBox();
done(result);
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
}
void StopGroupCallRecordingBox(
not_null<Ui::GenericBox*> box,
Fn<void(QString)> done) {
box->addRow(
object_ptr<Ui::FlatLabel>(
box.get(),
tr::lng_group_call_recording_stop_sure(),
st::groupCallBoxLabel),
style::margins(
st::boxRowPadding.left(),
st::boxPadding.top(),
st::boxRowPadding.right(),
st::boxPadding.bottom()));
box->addButton(tr::lng_box_ok(), [=] {
box->closeBox();
done(QString());
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
}
} // namespace
void GroupCallSettingsBox(
@ -141,8 +195,9 @@ void GroupCallSettingsBox(
const auto joinMuted = goodReal ? real->joinMuted() : false;
const auto canChangeJoinMuted = (goodReal && real->canChangeJoinMuted());
const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted);
const auto addEditJoinAs = (call->possibleJoinAs().size() > 1);
const auto addEditTitle = peer->canManageGroupCall();
const auto addEditJoinAs = (call->possibleJoinAs().size() > 1); // #TODO calls when to show
const auto addEditTitle = peer->canManageGroupCall() && goodReal;
const auto addEditRecording = peer->canManageGroupCall() && goodReal;
if (addCheck || addEditJoinAs) {
AddSkip(layout);
}
@ -152,12 +207,44 @@ void GroupCallSettingsBox(
tr::lng_group_call_display_as_header(),
st::groupCallSettingsButton).get()
: nullptr;
const auto editTitle = (goodReal && addEditTitle)
const auto editTitle = addEditTitle
? AddButton(
layout,
tr::lng_group_call_edit_title(),
st::groupCallSettingsButton).get()
: nullptr;
const auto recordStartDate = goodReal ? real->recordStartDate() : 0;
auto recordingLabel = [&] {
return ;
};
const auto editRecording = !addEditRecording
? nullptr
: !recordStartDate
? AddButton(
layout,
tr::lng_group_call_recording_start(),
st::groupCallSettingsButton).get()
: AddButtonWithLabel(
layout,
tr::lng_group_call_recording_stop(),
base::timer_each(
crl::time(1000)
) | rpl::map([=] {
const auto now = base::unixtime::now();
const auto elapsed = std::max(now - recordStartDate, 0);
const auto hours = elapsed / 3600;
const auto minutes = (elapsed % 3600) / 60;
const auto seconds = (elapsed % 60);
return hours
? QString("%1:%2:%3"
).arg(hours
).arg(minutes, 2, 10, QChar('0')
).arg(seconds, 2, 10, QChar('0'))
: QString("%1:%2"
).arg(minutes
).arg(seconds, 2, 10, QChar('0'));
}),
st::groupCallSettingsButton).get();
if (editJoinAs) {
editJoinAs->setClickedCallback([=] {
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
@ -184,14 +271,39 @@ void GroupCallSettingsBox(
editTitle->setClickedCallback([=] {
const auto done = [=](const QString &title) {
call->changeTitle(title);
box->closeBox();
};
box->getDelegate()->show(Box(
EditGroupCallTitleBox,
peer->name,
goodReal ? real->title() : QString(),
real->title(),
done));
});
}
if (editRecording) {
editRecording->setClickedCallback([=] {
const auto done = [=](QString title) {
call->toggleRecording(!recordStartDate, title);
const auto container = box->getDelegate()->outerContainer();
Ui::Toast::Show(
container,
(recordStartDate
? tr::lng_group_call_recording_stopped(tr::now)
: tr::lng_group_call_recording_started(tr::now)));
box->closeBox();
};
if (recordStartDate) {
box->getDelegate()->show(Box(
StopGroupCallRecordingBox,
done));
} else {
box->getDelegate()->show(Box(
StartGroupCallRecordingBox,
real->title(),
done));
}
});
}
const auto muteJoined = addCheck
? AddButton(
layout,

View file

@ -179,10 +179,12 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
_version = data.vversion().v;
}
const auto title = qs(data.vtitle().value_or_empty());
const auto recordDate = data.vrecord_start_date().value_or_empty();
const auto changed = (_joinMuted != data.is_join_muted())
|| (_fullCount.current() != data.vparticipants_count().v)
|| (_canChangeJoinMuted != data.is_can_change_join_muted())
|| (_title.current() != title);
|| (_title.current() != title)
|| (_recordStartDate != recordDate);
if (!force && !changed) {
return;
} else if (!force && _version > data.vversion().v) {
@ -193,6 +195,7 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
_canChangeJoinMuted = data.is_can_change_join_muted();
_fullCount = data.vparticipants_count().v;
_title = title;
_recordStartDate = recordDate;
changePeerEmptyCallFlag();
}, [&](const MTPDgroupCallDiscarded &data) {
const auto id = _id;

View file

@ -53,6 +53,9 @@ public:
void setTitle(const QString &title) {
_title = title;
}
[[nodiscard]] TimeId recordStartDate() const {
return _recordStartDate;
}
void setPeer(not_null<PeerData*> peer);
@ -127,6 +130,7 @@ private:
base::Timer _speakingByActiveFinishTimer;
QString _nextOffset;
rpl::variable<int> _fullCount = 0;
TimeId _recordStartDate = 0;
base::flat_map<uint32, LastSpokeTimes> _unknownSpokenSsrcs;
base::flat_map<PeerId, LastSpokeTimes> _unknownSpokenPeerIds;