Added initial ability to configure notification sound.
This commit is contained in:
parent
1c9b1ea69f
commit
c04a0e42a7
|
@ -252,6 +252,8 @@ PRIVATE
|
|||
boxes/phone_banned_box.h
|
||||
boxes/pin_messages_box.cpp
|
||||
boxes/pin_messages_box.h
|
||||
boxes/ringtones_box.cpp
|
||||
boxes/ringtones_box.h
|
||||
boxes/self_destruction_box.cpp
|
||||
boxes/self_destruction_box.h
|
||||
boxes/send_files_box.cpp
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 503 B |
Binary file not shown.
After Width: | Height: | Size: 892 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -897,6 +897,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_mute_menu_duration_unmute" = "Unmute";
|
||||
"lng_mute_menu_sound_on" = "Enable sound";
|
||||
"lng_mute_menu_sound_off" = "Disable sound";
|
||||
"lng_mute_menu_sound_select" = "Select sound";
|
||||
"lng_mute_box_title" = "Mute notifications for...";
|
||||
|
||||
"lng_mute_duration_hours#one" = "For {count} hour";
|
||||
|
@ -3113,6 +3114,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
"lng_telegram_features_url" = "https://t.me/TelegramTips";
|
||||
|
||||
"lng_ringtones_box_title" = "Notification Sound";
|
||||
"lng_ringtones_box_cloud_subtitle" = "Telegram tones";
|
||||
"lng_ringtones_box_local_subtitle" = "System notes";
|
||||
"lng_ringtones_box_upload" = "Upload Sound";
|
||||
"lng_ringtones_box_upload_choose" = "Choose ringtone";
|
||||
"lng_ringtones_box_upload_button" = "Upload Sound";
|
||||
"lng_ringtones_box_default" = "Default";
|
||||
"lng_ringtones_box_no_sound" = "No sound";
|
||||
"lng_ringtones_box_error" = "Sorry, but your file is too big.";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||
|
|
|
@ -1055,3 +1055,12 @@ requestsRejectButton: RoundButton(defaultLightButton) {
|
|||
}
|
||||
requestAcceptPosition: point(71px, 58px);
|
||||
requestButtonsSkip: 9px;
|
||||
|
||||
ringtonesBoxListHeight: 192;
|
||||
ringtonesBoxButton: SettingsButton(defaultSettingsButton) {
|
||||
textFg: lightButtonFg;
|
||||
textFgOver: lightButtonFgOver;
|
||||
padding: margins(56px, 10px, 22px, 8px);
|
||||
iconLeft: 25px;
|
||||
}
|
||||
ringtonesBoxSkip: 7px;
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "boxes/ringtones_box.h"
|
||||
|
||||
#include "api/api_ringtones.h"
|
||||
#include "apiwrap.h"
|
||||
#include "base/base_file_utilities.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "core/file_utilities.h"
|
||||
#include "core/mime_type.h"
|
||||
#include "data/data_document.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 "settings/settings_common.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto kDefaultValue = -1;
|
||||
constexpr auto kNoSoundValue = -2;
|
||||
|
||||
} // namespace
|
||||
|
||||
void RingtonesBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<PeerData*> peer) {
|
||||
box->setTitle(tr::lng_ringtones_box_title());
|
||||
|
||||
const auto container = box->verticalLayout();
|
||||
|
||||
auto padding = st::boxPadding;
|
||||
padding.setTop(padding.bottom());
|
||||
|
||||
struct State {
|
||||
std::shared_ptr<Ui::RadiobuttonGroup> group;
|
||||
std::vector<DocumentId> documentIds;
|
||||
base::unique_qptr<Ui::PopupMenu> menu;
|
||||
};
|
||||
const auto state = container->lifetime().make_state<State>(State{
|
||||
std::make_shared<Ui::RadiobuttonGroup>(
|
||||
peer->owner().notifySettings().sound(peer).none
|
||||
? kNoSoundValue
|
||||
: kDefaultValue),
|
||||
});
|
||||
|
||||
const auto addToGroup = [=](
|
||||
not_null<Ui::VerticalLayout*> verticalLayout,
|
||||
int value,
|
||||
const QString &text) {
|
||||
const auto button = verticalLayout->add(
|
||||
object_ptr<Ui::Radiobutton>(
|
||||
verticalLayout,
|
||||
state->group,
|
||||
value,
|
||||
text,
|
||||
st::defaultCheckbox),
|
||||
padding);
|
||||
if (value < 0) {
|
||||
return;
|
||||
}
|
||||
base::install_event_filter(button, [=](not_null<QEvent*> e) {
|
||||
if (state->menu || e->type() != QEvent::ContextMenu) {
|
||||
return base::EventFilterResult::Continue;
|
||||
}
|
||||
state->menu = base::make_unique_q<Ui::PopupMenu>(
|
||||
button,
|
||||
st::popupMenuWithIcons);
|
||||
auto callback = [=] {
|
||||
const auto id = state->documentIds[value];
|
||||
peer->session().api().ringtones().remove(id);
|
||||
};
|
||||
state->menu->addAction(
|
||||
tr::lng_box_delete(tr::now),
|
||||
std::move(callback),
|
||||
&st::menuIconDelete);
|
||||
state->menu->popup(QCursor::pos());
|
||||
return base::EventFilterResult::Cancel;
|
||||
});
|
||||
};
|
||||
|
||||
peer->session().api().ringtones().uploadFails(
|
||||
) | rpl::start_with_next([=](const QString &error) {
|
||||
if ((error == u"RINGTONE_DURATION_TOO_LONG"_q)
|
||||
|| (error == u"RINGTONE_SIZE_TOO_BIG"_q)) {
|
||||
box->getDelegate()->show(
|
||||
Ui::MakeInformBox(tr::lng_ringtones_box_error()));
|
||||
} else if (error == u"RINGTONE_MIME_INVALID"_q) {
|
||||
box->getDelegate()->show(
|
||||
Ui::MakeInformBox(tr::lng_edit_media_invalid_file()));
|
||||
}
|
||||
}, box->lifetime());
|
||||
|
||||
Settings::AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_ringtones_box_cloud_subtitle());
|
||||
|
||||
const auto emptyContent = box->addRow(
|
||||
object_ptr<Ui::FixedHeightWidget>(container),
|
||||
style::margins());
|
||||
const auto scroll = Ui::CreateChild<Ui::ScrollArea>(
|
||||
emptyContent,
|
||||
st::boxScroll);
|
||||
emptyContent->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
scroll->resize(width, scroll->height());
|
||||
}, emptyContent->lifetime());
|
||||
scroll->heightValue(
|
||||
) | rpl::start_with_next([=](int height) {
|
||||
emptyContent->resize(emptyContent->width(), height);
|
||||
}, scroll->lifetime());
|
||||
|
||||
{
|
||||
peer->session().api().ringtones().listUpdates(
|
||||
) | rpl::start_with_next([=] {
|
||||
state->documentIds.clear();
|
||||
const auto list = scroll->setOwnedWidget(
|
||||
object_ptr<Ui::VerticalLayout>(scroll));
|
||||
list->sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
scroll->resize(
|
||||
scroll->width(),
|
||||
std::min(s.height(), st::ringtonesBoxListHeight));
|
||||
}, list->lifetime());
|
||||
list->resize(scroll->size());
|
||||
auto value = 0;
|
||||
const auto checkedId = peer->owner().notifySettings().sound(peer);
|
||||
for (const auto &id : peer->session().api().ringtones().list()) {
|
||||
const auto document = peer->session().data().document(id);
|
||||
addToGroup(list, value++, document->filename());
|
||||
state->documentIds.push_back(id);
|
||||
if (checkedId.id && checkedId.id == id) {
|
||||
state->group->setValue(value - 1);
|
||||
}
|
||||
}
|
||||
}, scroll->lifetime());
|
||||
|
||||
peer->session().api().ringtones().requestList();
|
||||
}
|
||||
|
||||
const auto upload = box->addRow(
|
||||
Settings::CreateButton(
|
||||
container,
|
||||
tr::lng_ringtones_box_upload_button(),
|
||||
st::ringtonesBoxButton,
|
||||
{
|
||||
&st::mainMenuAddAccount,
|
||||
0,
|
||||
Settings::IconType::Round,
|
||||
&st::windowBgActive
|
||||
}),
|
||||
style::margins());
|
||||
upload->addClickHandler([=] {
|
||||
const auto delay = st::ringtonesBoxButton.ripple.hideDuration;
|
||||
base::call_delayed(delay, crl::guard(box, [=] {
|
||||
const auto callback = [=](const FileDialog::OpenResult &result) {
|
||||
auto mime = QString();
|
||||
auto name = QString();
|
||||
auto content = result.remoteContent;
|
||||
if (!result.paths.isEmpty()) {
|
||||
auto info = QFileInfo(result.paths.front());
|
||||
mime = Core::MimeTypeForFile(info).name();
|
||||
name = info.fileName();
|
||||
auto f = QFile(result.paths.front());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
content = f.readAll();
|
||||
f.close();
|
||||
}
|
||||
} else {
|
||||
mime = Core::MimeTypeForData(content).name();
|
||||
name = "audio";
|
||||
}
|
||||
|
||||
peer->session().api().ringtones().upload(name, mime, content);
|
||||
};
|
||||
FileDialog::GetOpenPath(
|
||||
box.get(),
|
||||
tr::lng_ringtones_box_upload_choose(tr::now),
|
||||
"Audio files (*.mp3)",
|
||||
crl::guard(box, callback));
|
||||
}));
|
||||
});
|
||||
|
||||
box->addSkip(st::ringtonesBoxSkip);
|
||||
Settings::AddDivider(container);
|
||||
|
||||
box->addSkip(st::ringtonesBoxSkip);
|
||||
|
||||
Settings::AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_ringtones_box_local_subtitle());
|
||||
|
||||
addToGroup(container, kDefaultValue, tr::lng_ringtones_box_default({}));
|
||||
addToGroup(container, kNoSoundValue, tr::lng_ringtones_box_no_sound({}));
|
||||
|
||||
box->addSkip(st::ringtonesBoxSkip);
|
||||
|
||||
box->setWidth(st::boxWideWidth);
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
const auto value = state->group->value();
|
||||
auto sound = (value == kDefaultValue)
|
||||
? Data::NotifySound()
|
||||
: (value == kNoSoundValue)
|
||||
? Data::NotifySound{ .none = true }
|
||||
: Data::NotifySound{ .id = state->documentIds[value] };
|
||||
peer->owner().notifySettings().updateNotifySettings(
|
||||
peer,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
sound);
|
||||
box->closeBox();
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/layers/generic_box.h"
|
||||
|
||||
class PeerData;
|
||||
|
||||
void RingtonesBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<PeerData*> peer);
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "menu/menu_mute.h"
|
||||
|
||||
#include "boxes/ringtones_box.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
|
@ -230,6 +231,11 @@ void FillMuteMenu(
|
|||
Args args) {
|
||||
const auto peer = args.peer;
|
||||
|
||||
menu->addAction(
|
||||
tr::lng_mute_menu_sound_select(tr::now),
|
||||
[=, show = args.show] { show->showBox(Box(RingtonesBox, peer)); },
|
||||
&st::menuIconSoundSelect);
|
||||
|
||||
const auto soundIsNone = peer->owner().notifySettings().sound(peer).none;
|
||||
menu->addAction(
|
||||
soundIsNone
|
||||
|
|
|
@ -107,6 +107,7 @@ menuIconSilent: icon {{ "menu/silent", menuIconColor }};
|
|||
menuIconCustomize: icon {{ "menu/customize", menuIconColor }};
|
||||
menuIconSoundOn: icon {{ "menu/sound_enable", menuIconColor }};
|
||||
menuIconSoundOff: icon {{ "menu/sound_disable", menuIconColor }};
|
||||
menuIconSoundSelect: icon {{ "menu/sound_select", menuIconColor }};
|
||||
|
||||
menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }};
|
||||
menuIconTTLAnyTextPosition: point(11px, 22px);
|
||||
|
|
Loading…
Reference in New Issue