diff --git a/Telegram/SourceFiles/ayu/ayu_settings.cpp b/Telegram/SourceFiles/ayu/ayu_settings.cpp index db31341548..f06ba4d2e1 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.cpp +++ b/Telegram/SourceFiles/ayu/ayu_settings.cpp @@ -109,7 +109,20 @@ void GhostModeAccountSettings::setUseScheduledMessages(bool val) { AyuSettings::save(); } -void GhostModeAccountSettings::setSendWithoutSound(bool val) { +bool GhostModeAccountSettings::shouldSendWithoutSound() const { + switch (_sendWithoutSound.current()) { + case SendWithoutSoundOption::Never: + return false; + case SendWithoutSoundOption::InGhostMode: + return isGhostModeActive(); + case SendWithoutSoundOption::Always: + return true; + } + Unexpected("Value in GhostModeAccountSettings::shouldSendWithoutSound."); +} + +void GhostModeAccountSettings::setSendWithoutSound( + SendWithoutSoundOption val) { if (_sendWithoutSound.current() == val) return; _sendWithoutSound = val; AyuSettings::save(); @@ -195,7 +208,14 @@ void from_json(const nlohmann::json &j, GhostModeAccountSettings &s) { s._sendOfflinePacketAfterOnline = j.value("sendOfflinePacketAfterOnline", false); s._markReadAfterAction = j.value("markReadAfterAction", true); s._useScheduledMessages = j.value("useScheduledMessages", false); - s._sendWithoutSound = j.value("sendWithoutSound", false); + const auto sendWithoutSound = j.find("sendWithoutSound"); + s._sendWithoutSound = (sendWithoutSound == j.end()) + ? SendWithoutSoundOption::Never + : sendWithoutSound->is_boolean() + ? (sendWithoutSound->get() + ? SendWithoutSoundOption::Always + : SendWithoutSoundOption::Never) + : sendWithoutSound->get(); s._suggestGhostModeBeforeViewingStory = j.value("suggestGhostModeBeforeViewingStory", true); s._sendReadMessagesLocked = j.value("sendReadMessagesLocked", false); s._sendReadStoriesLocked = j.value("sendReadStoriesLocked", false); diff --git a/Telegram/SourceFiles/ayu/ayu_settings.h b/Telegram/SourceFiles/ayu/ayu_settings.h index 6906a1ad60..29f131149a 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.h +++ b/Telegram/SourceFiles/ayu/ayu_settings.h @@ -45,6 +45,12 @@ enum class TranslationProvider { Native = 3, }; +enum class SendWithoutSoundOption { + Never = 0, + InGhostMode = 1, + Always = 2, +}; + NLOHMANN_JSON_SERIALIZE_ENUM(PeerIdDisplay, { {PeerIdDisplay::Hidden, 0}, {PeerIdDisplay::TelegramApi, 1}, @@ -70,6 +76,12 @@ NLOHMANN_JSON_SERIALIZE_ENUM(TranslationProvider, { {TranslationProvider::Native, "native"}, }) +NLOHMANN_JSON_SERIALIZE_ENUM(SendWithoutSoundOption, { + {SendWithoutSoundOption::Never, 0}, + {SendWithoutSoundOption::InGhostMode, 1}, + {SendWithoutSoundOption::Always, 2}, +}) + class GhostModeAccountSettings { public: GhostModeAccountSettings(); @@ -81,7 +93,8 @@ public: [[nodiscard]] bool sendOfflinePacketAfterOnline() const { return _sendOfflinePacketAfterOnline.current(); } [[nodiscard]] bool markReadAfterAction() const { return _markReadAfterAction.current(); } [[nodiscard]] bool useScheduledMessages() const { return _useScheduledMessages.current(); } - [[nodiscard]] bool sendWithoutSound() const { return _sendWithoutSound.current(); } + [[nodiscard]] SendWithoutSoundOption sendWithoutSound() const { return _sendWithoutSound.current(); } + [[nodiscard]] bool shouldSendWithoutSound() const; [[nodiscard]] bool suggestGhostModeBeforeViewingStory() const { return _suggestGhostModeBeforeViewingStory.current(); } [[nodiscard]] bool isGhostModeActive() const { return _ghostModeActive.current(); } [[nodiscard]] bool isUseScheduledMessages() const { return isGhostModeActive() && useScheduledMessages(); } @@ -99,7 +112,7 @@ public: void setSendOfflinePacketAfterOnline(bool val); void setMarkReadAfterAction(bool val); void setUseScheduledMessages(bool val); - void setSendWithoutSound(bool val); + void setSendWithoutSound(SendWithoutSoundOption val); void setSuggestGhostModeBeforeViewingStory(bool val); void setGhostModeEnabled(bool val); @@ -123,8 +136,8 @@ public: [[nodiscard]] rpl::producer markReadAfterActionChanges() const { return _markReadAfterAction.changes(); } [[nodiscard]] rpl::producer useScheduledMessagesValue() const { return _useScheduledMessages.value(); } [[nodiscard]] rpl::producer useScheduledMessagesChanges() const { return _useScheduledMessages.changes(); } - [[nodiscard]] rpl::producer sendWithoutSoundValue() const { return _sendWithoutSound.value(); } - [[nodiscard]] rpl::producer sendWithoutSoundChanges() const { return _sendWithoutSound.changes(); } + [[nodiscard]] rpl::producer sendWithoutSoundValue() const { return _sendWithoutSound.value(); } + [[nodiscard]] rpl::producer sendWithoutSoundChanges() const { return _sendWithoutSound.changes(); } [[nodiscard]] rpl::producer suggestGhostModeBeforeViewingStoryValue() const { return _suggestGhostModeBeforeViewingStory.value(); } [[nodiscard]] rpl::producer suggestGhostModeBeforeViewingStoryChanges() const { return _suggestGhostModeBeforeViewingStory.changes(); } [[nodiscard]] rpl::producer ghostModeActiveValue() const { return _ghostModeActive.value(); } @@ -154,7 +167,7 @@ private: rpl::variable _sendOfflinePacketAfterOnline = false; rpl::variable _markReadAfterAction = true; rpl::variable _useScheduledMessages = false; - rpl::variable _sendWithoutSound = false; + rpl::variable _sendWithoutSound = SendWithoutSoundOption::Never; rpl::variable _suggestGhostModeBeforeViewingStory = true; rpl::variable _ghostModeActive = false; diff --git a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp index 8a85c73ec6..7b29799643 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/settings_ayu.cpp @@ -27,6 +27,7 @@ #include "styles/style_menu_icons.h" #include "styles/style_settings.h" #include "ui/painter.h" +#include "ui/boxes/single_choice_box.h" #include "ui/vertical_list.h" #include "ui/text/text.h" #include "ui/toast/toast.h" @@ -445,31 +446,45 @@ void BuildGhostEssentials(SectionBuilder &builder) { AddDividerText(container, tr::ayu_UseScheduledMessagesDescription()); AddSkip(container); - const auto silentButton = AddButtonWithIcon( + const auto silentOptions = std::vector{ + tr::ayu_SendWithoutSoundByDefaultNever(tr::now), + tr::ayu_SendWithoutSoundByDefaultInGhostMode(tr::now), + tr::ayu_SendWithoutSoundByDefaultAlways(tr::now), + }; + const auto silentOptionText = state->selectedUserId.value( + ) | rpl::map([=](uint64 id) { + return AyuSettings::ghost(id).sendWithoutSoundValue( + ) | rpl::map([=](SendWithoutSoundOption value) { + return silentOptions[static_cast(value)]; + }); + }) | rpl::flatten_latest(); + const auto silentButton = AddButtonWithLabel( container, tr::ayu_SendWithoutSoundByDefault(), - st::settingsButtonNoIcon - ); + std::move(silentOptionText), + st::settingsButtonNoIcon); if (wctx.highlights) { wctx.highlights->push_back(std::make_pair( u"ayu/sendWithoutSound"_q, HighlightEntry{ silentButton.get(), {} })); } - silentButton->toggleOn( - state->selectedUserId.value() - | rpl::map([](uint64 id) { - return AyuSettings::ghost(id).sendWithoutSoundValue(); - }) | rpl::flatten_latest() - )->toggledValue( - ) | rpl::filter( - [=](bool enabled) { - return enabled != AyuSettings::ghost(state->selectedUserId.current()).sendWithoutSound(); - } - ) | on_next( - [=](bool enabled) { - AyuSettings::ghost(state->selectedUserId.current()).setSendWithoutSound(enabled); - }, - container->lifetime()); + silentButton->addClickHandler([=] { + controller->show(Box([=](not_null box) { + const auto save = [=](int index) { + AyuSettings::ghost(state->selectedUserId.current() + ).setSendWithoutSound( + static_cast(index)); + }; + SingleChoiceBox(box, { + .title = tr::ayu_SendWithoutSoundByDefault(), + .options = silentOptions, + .initialSelection = static_cast( + AyuSettings::ghost(state->selectedUserId.current() + ).sendWithoutSound()), + .callback = save, + }); + })); + }); AddSkip(container); AddDividerText(container, tr::ayu_SendWithoutSoundByDefaultDescription()); diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index 132b12177f..21c158039b 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -614,7 +614,7 @@ bool ShouldSendSilent( not_null peer, const Api::SendOptions &options) { const auto &ghost = AyuSettings::ghost(&peer->session()); - if (ghost.sendWithoutSound()) { + if (ghost.shouldSendWithoutSound()) { return !options.silent; } diff --git a/Telegram/SourceFiles/menu/menu_send.cpp b/Telegram/SourceFiles/menu/menu_send.cpp index ca96fffbb7..3f180e24c8 100644 --- a/Telegram/SourceFiles/menu/menu_send.cpp +++ b/Telegram/SourceFiles/menu/menu_send.cpp @@ -749,7 +749,7 @@ FillMenuResult FillSendMenu( const auto &ghost = maybeShow ? AyuSettings::ghost(&maybeShow->session()) : AyuSettings::ghost(); - const auto sendWithoutSound = ghost.sendWithoutSound(); + const auto sendWithoutSound = ghost.shouldSendWithoutSound(); menu->addAction( sendWithoutSound ? tr::ayu_SendWithSound(tr::now) : tr::lng_send_silent_message(tr::now), [=] { action({ Api::SendOptions{ .silent = true } }, details); }, diff --git a/Telegram/SourceFiles/platform/mac/global_menu_mac.mm b/Telegram/SourceFiles/platform/mac/global_menu_mac.mm index 68da50703a..2b9876d76b 100644 --- a/Telegram/SourceFiles/platform/mac/global_menu_mac.mm +++ b/Telegram/SourceFiles/platform/mac/global_menu_mac.mm @@ -105,7 +105,6 @@ private: QAction *_ghostMode = nullptr; QAction *_readOnInteract = nullptr; QAction *_scheduleMessages = nullptr; - QAction *_sendWithoutSound = nullptr; NSPasteboard *_pasteboard = nullptr; int _pasteboardChangeCount = -1; @@ -237,9 +236,6 @@ void Manager::retranslate() { if (_scheduleMessages) { _scheduleMessages->setText(tr::ayu_UseScheduledMessages(tr::now)); } - if (_sendWithoutSound) { - _sendWithoutSound->setText(tr::ayu_SendWithoutSoundByDefault(tr::now)); - } } void Manager::ensureLanguageBound() { @@ -336,7 +332,6 @@ void Manager::recomputeState() { ForceDisabled(_ghostMode, ghostInactive); ForceDisabled(_readOnInteract, ghostInactive); ForceDisabled(_scheduleMessages, ghostInactive); - ForceDisabled(_sendWithoutSound, ghostInactive); const auto setChecked = [](QAction *action, bool checked) { const auto wasBlocked = action->blockSignals(true); action->setChecked(checked); @@ -348,12 +343,10 @@ void Manager::recomputeState() { : tr::ayu_EnableGhostMode(tr::now)); setChecked(_readOnInteract, ghost->markReadAfterAction()); setChecked(_scheduleMessages, ghost->useScheduledMessages()); - setChecked(_sendWithoutSound, ghost->sendWithoutSound()); } else { _ghostMode->setText(tr::ayu_EnableGhostMode(tr::now)); setChecked(_readOnInteract, false); setChecked(_scheduleMessages, false); - setChecked(_sendWithoutSound, false); } } @@ -592,13 +585,6 @@ void Manager::buildGhostModeMenu(QMenu *ghostMode) { } }); - _sendWithoutSound = addToggle( - u"Send without Sound"_q, - [this](bool enabled) { - if (const auto ghost = resolveGhostSettings()) { - ghost->setSendWithoutSound(enabled); - } - }); } void Manager::buildWindowMenu(QMenu *window) { @@ -720,8 +706,7 @@ void Manager::destroy() { = _strikeOut = _blockquote = _monospace = _clearFormat = nullptr; _ghostModeMenu = nullptr; - _ghostMode = _readOnInteract = _scheduleMessages = _sendWithoutSound - = nullptr; + _ghostMode = _readOnInteract = _scheduleMessages = nullptr; _pasteboard = nullptr; _pasteboardChangeCount = -1; _pasteboardHasText = false;