mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Play ringtones on click in select box.
This commit is contained in:
parent
f5164fe3e4
commit
d35b8f82a3
7 changed files with 107 additions and 23 deletions
|
@ -11,7 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/random.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "main/main_session.h"
|
||||
#include "storage/file_upload.h"
|
||||
#include "storage/localimageloader.h"
|
||||
|
@ -83,7 +85,7 @@ void Ringtones::upload(
|
|||
filemime,
|
||||
content);
|
||||
|
||||
const auto uploadedData = UploadedData{ filename, filemime };
|
||||
const auto uploadedData = UploadedData{ filename, filemime, content };
|
||||
const auto fakeId = FullMsgId(
|
||||
_session->userPeerId(),
|
||||
_session->data().nextLocalMessageId());
|
||||
|
@ -111,9 +113,12 @@ void Ringtones::ready(const FullMsgId &msgId, const MTPInputFile &file) {
|
|||
file,
|
||||
MTP_string(uploadedData.filename),
|
||||
MTP_string(uploadedData.filemime)
|
||||
)).done([=](const MTPDocument &result) {
|
||||
)).done([=, content = uploadedData.content](const MTPDocument &result) {
|
||||
const auto document = _session->data().processDocument(result);
|
||||
_list.documents.insert(_list.documents.begin(), document->id);
|
||||
const auto media = document->createMediaView();
|
||||
media->setBytes(content);
|
||||
document->owner().notifySettings().cacheSound(document);
|
||||
_uploadDones.fire_copy(document->id);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_uploadFails.fire_copy(error.type());
|
||||
|
@ -134,6 +139,7 @@ void Ringtones::requestList() {
|
|||
_list.documents.reserve(data.vringtones().v.size());
|
||||
for (const auto &d : data.vringtones().v) {
|
||||
const auto document = _session->data().processDocument(d);
|
||||
document->forceToCache(true);
|
||||
_list.documents.emplace_back(document->id);
|
||||
}
|
||||
requestList();
|
||||
|
|
|
@ -42,6 +42,7 @@ private:
|
|||
struct UploadedData {
|
||||
QString filename;
|
||||
QString filemime;
|
||||
QByteArray content;
|
||||
};
|
||||
void ready(const FullMsgId &msgId, const MTPInputFile &file);
|
||||
|
||||
|
|
|
@ -13,15 +13,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/call_delayed.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/timer_rpl.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/mime_type.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_document_resolver.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
@ -40,6 +44,50 @@ namespace {
|
|||
|
||||
constexpr auto kDefaultValue = -1;
|
||||
constexpr auto kNoSoundValue = -2;
|
||||
constexpr auto kNoDetachTimeout = crl::time(250);
|
||||
|
||||
class AudioCreator final {
|
||||
public:
|
||||
AudioCreator();
|
||||
AudioCreator(AudioCreator &&other);
|
||||
AudioCreator &operator=(AudioCreator &&other);
|
||||
~AudioCreator();
|
||||
|
||||
private:
|
||||
rpl::lifetime _lifetime;
|
||||
bool _attached = false;
|
||||
|
||||
};
|
||||
|
||||
AudioCreator::AudioCreator()
|
||||
: _attached(true) {
|
||||
crl::async([] {
|
||||
QMutexLocker lock(Media::Player::internal::audioPlayerMutex());
|
||||
Media::Audio::AttachToDevice();
|
||||
});
|
||||
base::timer_each(
|
||||
kNoDetachTimeout
|
||||
) | rpl::start_with_next([=] {
|
||||
Media::Audio::StopDetachIfNotUsedSafe();
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
AudioCreator::AudioCreator(AudioCreator &&other)
|
||||
: _lifetime(base::take(other._lifetime))
|
||||
, _attached(base::take(other._attached)) {
|
||||
}
|
||||
|
||||
AudioCreator &AudioCreator::operator=(AudioCreator &&other) {
|
||||
_lifetime = base::take(other._lifetime);
|
||||
_attached = base::take(other._attached);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AudioCreator::~AudioCreator() {
|
||||
if (_attached) {
|
||||
Media::Audio::ScheduleDetachIfNotUsedSafe();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -79,8 +127,9 @@ void RingtonesBox(
|
|||
padding.setTop(padding.bottom());
|
||||
|
||||
struct State {
|
||||
AudioCreator creator;
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> group;
|
||||
std::vector<DocumentId> documentIds;
|
||||
std::vector<std::shared_ptr<Data::DocumentMedia>> medias;
|
||||
Data::NotifySound chosen;
|
||||
base::unique_qptr<Ui::PopupMenu> menu;
|
||||
QPointer<Ui::Radiobutton> defaultButton;
|
||||
|
@ -113,6 +162,9 @@ void RingtonesBox(
|
|||
}
|
||||
if (value == kDefaultValue) {
|
||||
state->defaultButton = button;
|
||||
button->setClickedCallback([=] {
|
||||
Core::App().notifications().playSound(session, 0);
|
||||
});
|
||||
}
|
||||
if (value < 0) {
|
||||
return;
|
||||
|
@ -120,6 +172,14 @@ void RingtonesBox(
|
|||
while (state->buttons.size() <= value) {
|
||||
state->buttons.push_back(nullptr);
|
||||
}
|
||||
button->setClickedCallback([=] {
|
||||
const auto media = state->medias[value].get();
|
||||
if (media->loaded()) {
|
||||
Core::App().notifications().playSound(
|
||||
session,
|
||||
media->owner()->id);
|
||||
}
|
||||
});
|
||||
base::install_event_filter(button, [=](not_null<QEvent*> e) {
|
||||
if (e->type() != QEvent::ContextMenu || state->menu) {
|
||||
return base::EventFilterResult::Continue;
|
||||
|
@ -128,7 +188,7 @@ void RingtonesBox(
|
|||
button,
|
||||
st::popupMenuWithIcons);
|
||||
auto callback = [=] {
|
||||
const auto id = state->documentIds[value];
|
||||
const auto id = state->medias[value]->owner()->id;
|
||||
session->api().ringtones().remove(id);
|
||||
};
|
||||
state->menu->addAction(
|
||||
|
@ -172,7 +232,7 @@ void RingtonesBox(
|
|||
object_ptr<Ui::VerticalLayout>(container));
|
||||
|
||||
const auto rebuild = [=] {
|
||||
state->documentIds.clear();
|
||||
const auto old = base::take(state->medias);
|
||||
auto value = 0;
|
||||
while (custom->count()) {
|
||||
delete custom->widgetAt(0);
|
||||
|
@ -183,7 +243,8 @@ void RingtonesBox(
|
|||
const auto document = session->data().document(id);
|
||||
const auto text = ExtractRingtoneName(document);
|
||||
addToGroup(custom, value++, text, chosen);
|
||||
state->documentIds.push_back(id);
|
||||
state->medias.push_back(document->createMediaView());
|
||||
document->owner().notifySettings().cacheSound(document);
|
||||
}
|
||||
|
||||
custom->resizeToWidth(container->width());
|
||||
|
@ -260,7 +321,7 @@ void RingtonesBox(
|
|||
? Data::NotifySound()
|
||||
: (value == kNoSoundValue)
|
||||
? Data::NotifySound{ .none = true }
|
||||
: Data::NotifySound{ .id = state->documentIds[value] };
|
||||
: Data::NotifySound{ .id = state->medias[value]->owner()->id };
|
||||
save(sound);
|
||||
box->closeBox();
|
||||
});
|
||||
|
|
|
@ -163,24 +163,16 @@ void NotifySettings::updateLocal(not_null<PeerData*> peer) {
|
|||
}
|
||||
|
||||
if (const auto sound = peer->notifySound(); sound && sound->id) {
|
||||
const auto cache = [=](DocumentId id) {
|
||||
if (const auto document = _owner->document(id)) {
|
||||
const auto view = document->createMediaView();
|
||||
_ringtones.views.emplace(id, view);
|
||||
document->forceToCache(true);
|
||||
document->save(Data::FileOriginRingtones(), QString());
|
||||
}
|
||||
};
|
||||
if (const auto doc = _owner->document(sound->id); !doc->isNull()) {
|
||||
cache(sound->id);
|
||||
cacheSound(doc);
|
||||
} else {
|
||||
_ringtones.pendingIds.push_back(sound->id);
|
||||
if (!_ringtones.pendingLifetime) {
|
||||
// Not requested yet.
|
||||
_owner->session().api().ringtones().listUpdates(
|
||||
) | rpl::start_with_next([=] {
|
||||
for (const auto &id : base::take(_ringtones.pendingIds)) {
|
||||
cache(id);
|
||||
for (const auto id : base::take(_ringtones.pendingIds)) {
|
||||
cacheSound(id);
|
||||
}
|
||||
_ringtones.pendingLifetime.destroy();
|
||||
}, _ringtones.pendingLifetime);
|
||||
|
@ -190,6 +182,20 @@ void NotifySettings::updateLocal(not_null<PeerData*> peer) {
|
|||
}
|
||||
}
|
||||
|
||||
void NotifySettings::cacheSound(DocumentId id) {
|
||||
cacheSound(_owner->document(id));
|
||||
}
|
||||
|
||||
void NotifySettings::cacheSound(not_null<DocumentData*> document) {
|
||||
if (document->isNull()) {
|
||||
return;
|
||||
}
|
||||
const auto view = document->createMediaView();
|
||||
_ringtones.views.emplace(document->id, view);
|
||||
document->forceToCache(true);
|
||||
document->save(Data::FileOriginRingtones(), QString());
|
||||
}
|
||||
|
||||
void NotifySettings::updateLocal(DefaultNotify type) {
|
||||
defaultValue(type).updates.fire({});
|
||||
|
||||
|
|
|
@ -39,7 +39,10 @@ public:
|
|||
std::optional<NotifySound> sound = std::nullopt);
|
||||
void resetToDefault(not_null<PeerData*> peer);
|
||||
|
||||
std::shared_ptr<DocumentMedia> lookupRingtone(DocumentId id) const;
|
||||
void cacheSound(DocumentId id);
|
||||
void cacheSound(not_null<DocumentData*> document);
|
||||
[[nodiscard]] std::shared_ptr<DocumentMedia> lookupRingtone(
|
||||
DocumentId id) const;
|
||||
|
||||
[[nodiscard]] rpl::producer<> defaultUpdates(DefaultNotify type) const;
|
||||
[[nodiscard]] rpl::producer<> defaultUpdates(
|
||||
|
|
|
@ -510,7 +510,7 @@ void System::showNext() {
|
|||
}
|
||||
if (settings.soundNotify() && !_manager->skipAudio()) {
|
||||
const auto track = lookupSound(
|
||||
alertPeer,
|
||||
&alertPeer->owner(),
|
||||
alertPeer->owner().notifySettings().sound(alertPeer).id);
|
||||
track->playOnce();
|
||||
Media::Player::mixer()->suppressAll(track->getLengthMs());
|
||||
|
@ -699,7 +699,7 @@ void System::showNext() {
|
|||
}
|
||||
|
||||
not_null<Media::Audio::Track*> System::lookupSound(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<Data::Session*> owner,
|
||||
DocumentId id) {
|
||||
if (!id) {
|
||||
ensureSoundCreated();
|
||||
|
@ -709,7 +709,7 @@ not_null<Media::Audio::Track*> System::lookupSound(
|
|||
if (i != end(_customSoundTracks)) {
|
||||
return i->second.get();
|
||||
}
|
||||
const auto ¬ifySettings = peer->owner().notifySettings();
|
||||
const auto ¬ifySettings = owner->notifySettings();
|
||||
const auto custom = notifySettings.lookupRingtone(id);
|
||||
if (custom && !custom->bytes().isEmpty()) {
|
||||
const auto j = _customSoundTracks.emplace(
|
||||
|
@ -747,6 +747,10 @@ void System::notifySettingsChanged(ChangeType type) {
|
|||
return _settingsChanged.fire(std::move(type));
|
||||
}
|
||||
|
||||
void System::playSound(not_null<Main::Session*> session, DocumentId id) {
|
||||
lookupSound(&session->data(), id)->playOnce();
|
||||
}
|
||||
|
||||
Manager::DisplayOptions Manager::getNotificationOptions(
|
||||
HistoryItem *item,
|
||||
ItemNotificationType type) const {
|
||||
|
|
|
@ -15,6 +15,7 @@ struct ItemNotification;
|
|||
enum class ItemNotificationType;
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
class CloudImageView;
|
||||
} // namespace Data
|
||||
|
||||
|
@ -99,6 +100,8 @@ public:
|
|||
[[nodiscard]] rpl::producer<ChangeType> settingsChanged() const;
|
||||
void notifySettingsChanged(ChangeType type);
|
||||
|
||||
void playSound(not_null<Main::Session*> session, DocumentId id);
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
@ -159,7 +162,7 @@ private:
|
|||
void showGrouped();
|
||||
void ensureSoundCreated();
|
||||
[[nodiscard]] not_null<Media::Audio::Track*> lookupSound(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<Data::Session*> owner,
|
||||
DocumentId id);
|
||||
|
||||
base::flat_map<
|
||||
|
|
Loading…
Add table
Reference in a new issue