mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add recording start/stop to Settings.
This commit is contained in:
parent
5bea88fd66
commit
22aa57ad6f
6 changed files with 156 additions and 6 deletions
|
@ -2000,6 +2000,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_group_call_recording_stop" = "Stop recording";
|
"lng_group_call_recording_stop" = "Stop recording";
|
||||||
"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_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.";
|
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
||||||
|
|
||||||
|
|
|
@ -876,6 +876,29 @@ void GroupCall::changeTitle(const QString &title) {
|
||||||
}).send();
|
}).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() {
|
void GroupCall::ensureControllerCreated() {
|
||||||
if (_instance) {
|
if (_instance) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -119,6 +119,7 @@ public:
|
||||||
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 changeTitle(const QString &title);
|
||||||
|
void toggleRecording(bool enabled, const QString &title);
|
||||||
|
|
||||||
void setMuted(MuteState mute);
|
void setMuted(MuteState mute);
|
||||||
void setMutedAndUpdate(MuteState mute);
|
void setMutedAndUpdate(MuteState mute);
|
||||||
|
|
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/event_filter.h"
|
#include "base/event_filter.h"
|
||||||
#include "base/global_shortcuts.h"
|
#include "base/global_shortcuts.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
|
#include "base/unixtime.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_group_call.h"
|
#include "data/data_group_call.h"
|
||||||
|
@ -100,13 +101,66 @@ void EditGroupCallTitleBox(
|
||||||
input->setFocusFast();
|
input->setFocusFast();
|
||||||
});
|
});
|
||||||
box->addButton(tr::lng_settings_save(), [=] {
|
box->addButton(tr::lng_settings_save(), [=] {
|
||||||
const auto result = input->getLastText();
|
const auto result = input->getLastText().trimmed();
|
||||||
box->closeBox();
|
box->closeBox();
|
||||||
done(result);
|
done(result);
|
||||||
});
|
});
|
||||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
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
|
} // namespace
|
||||||
|
|
||||||
void GroupCallSettingsBox(
|
void GroupCallSettingsBox(
|
||||||
|
@ -141,8 +195,9 @@ void GroupCallSettingsBox(
|
||||||
const auto joinMuted = goodReal ? real->joinMuted() : false;
|
const auto joinMuted = goodReal ? real->joinMuted() : false;
|
||||||
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); // #TODO calls when to show
|
||||||
const auto addEditTitle = peer->canManageGroupCall();
|
const auto addEditTitle = peer->canManageGroupCall() && goodReal;
|
||||||
|
const auto addEditRecording = peer->canManageGroupCall() && goodReal;
|
||||||
if (addCheck || addEditJoinAs) {
|
if (addCheck || addEditJoinAs) {
|
||||||
AddSkip(layout);
|
AddSkip(layout);
|
||||||
}
|
}
|
||||||
|
@ -152,12 +207,44 @@ 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)
|
const auto editTitle = addEditTitle
|
||||||
? AddButton(
|
? AddButton(
|
||||||
layout,
|
layout,
|
||||||
tr::lng_group_call_edit_title(),
|
tr::lng_group_call_edit_title(),
|
||||||
st::groupCallSettingsButton).get()
|
st::groupCallSettingsButton).get()
|
||||||
: nullptr;
|
: 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) {
|
if (editJoinAs) {
|
||||||
editJoinAs->setClickedCallback([=] {
|
editJoinAs->setClickedCallback([=] {
|
||||||
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
|
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
|
||||||
|
@ -184,14 +271,39 @@ void GroupCallSettingsBox(
|
||||||
editTitle->setClickedCallback([=] {
|
editTitle->setClickedCallback([=] {
|
||||||
const auto done = [=](const QString &title) {
|
const auto done = [=](const QString &title) {
|
||||||
call->changeTitle(title);
|
call->changeTitle(title);
|
||||||
|
box->closeBox();
|
||||||
};
|
};
|
||||||
box->getDelegate()->show(Box(
|
box->getDelegate()->show(Box(
|
||||||
EditGroupCallTitleBox,
|
EditGroupCallTitleBox,
|
||||||
peer->name,
|
peer->name,
|
||||||
goodReal ? real->title() : QString(),
|
real->title(),
|
||||||
done));
|
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
|
const auto muteJoined = addCheck
|
||||||
? AddButton(
|
? AddButton(
|
||||||
layout,
|
layout,
|
||||||
|
|
|
@ -179,10 +179,12 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
|
||||||
_version = data.vversion().v;
|
_version = data.vversion().v;
|
||||||
}
|
}
|
||||||
const auto title = qs(data.vtitle().value_or_empty());
|
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())
|
const auto changed = (_joinMuted != data.is_join_muted())
|
||||||
|| (_fullCount.current() != data.vparticipants_count().v)
|
|| (_fullCount.current() != data.vparticipants_count().v)
|
||||||
|| (_canChangeJoinMuted != data.is_can_change_join_muted())
|
|| (_canChangeJoinMuted != data.is_can_change_join_muted())
|
||||||
|| (_title.current() != title);
|
|| (_title.current() != title)
|
||||||
|
|| (_recordStartDate != recordDate);
|
||||||
if (!force && !changed) {
|
if (!force && !changed) {
|
||||||
return;
|
return;
|
||||||
} else if (!force && _version > data.vversion().v) {
|
} 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();
|
_canChangeJoinMuted = data.is_can_change_join_muted();
|
||||||
_fullCount = data.vparticipants_count().v;
|
_fullCount = data.vparticipants_count().v;
|
||||||
_title = title;
|
_title = title;
|
||||||
|
_recordStartDate = recordDate;
|
||||||
changePeerEmptyCallFlag();
|
changePeerEmptyCallFlag();
|
||||||
}, [&](const MTPDgroupCallDiscarded &data) {
|
}, [&](const MTPDgroupCallDiscarded &data) {
|
||||||
const auto id = _id;
|
const auto id = _id;
|
||||||
|
|
|
@ -53,6 +53,9 @@ public:
|
||||||
void setTitle(const QString &title) {
|
void setTitle(const QString &title) {
|
||||||
_title = title;
|
_title = title;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] TimeId recordStartDate() const {
|
||||||
|
return _recordStartDate;
|
||||||
|
}
|
||||||
|
|
||||||
void setPeer(not_null<PeerData*> peer);
|
void setPeer(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
@ -127,6 +130,7 @@ private:
|
||||||
base::Timer _speakingByActiveFinishTimer;
|
base::Timer _speakingByActiveFinishTimer;
|
||||||
QString _nextOffset;
|
QString _nextOffset;
|
||||||
rpl::variable<int> _fullCount = 0;
|
rpl::variable<int> _fullCount = 0;
|
||||||
|
TimeId _recordStartDate = 0;
|
||||||
|
|
||||||
base::flat_map<uint32, LastSpokeTimes> _unknownSpokenSsrcs;
|
base::flat_map<uint32, LastSpokeTimes> _unknownSpokenSsrcs;
|
||||||
base::flat_map<PeerId, LastSpokeTimes> _unknownSpokenPeerIds;
|
base::flat_map<PeerId, LastSpokeTimes> _unknownSpokenPeerIds;
|
||||||
|
|
Loading…
Add table
Reference in a new issue