mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
feat: support send without sound in ghost mode
This commit is contained in:
@@ -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<bool>()
|
||||
? SendWithoutSoundOption::Always
|
||||
: SendWithoutSoundOption::Never)
|
||||
: sendWithoutSound->get<SendWithoutSoundOption>();
|
||||
s._suggestGhostModeBeforeViewingStory = j.value("suggestGhostModeBeforeViewingStory", true);
|
||||
s._sendReadMessagesLocked = j.value("sendReadMessagesLocked", false);
|
||||
s._sendReadStoriesLocked = j.value("sendReadStoriesLocked", false);
|
||||
|
||||
@@ -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<bool> markReadAfterActionChanges() const { return _markReadAfterAction.changes(); }
|
||||
[[nodiscard]] rpl::producer<bool> useScheduledMessagesValue() const { return _useScheduledMessages.value(); }
|
||||
[[nodiscard]] rpl::producer<bool> useScheduledMessagesChanges() const { return _useScheduledMessages.changes(); }
|
||||
[[nodiscard]] rpl::producer<bool> sendWithoutSoundValue() const { return _sendWithoutSound.value(); }
|
||||
[[nodiscard]] rpl::producer<bool> sendWithoutSoundChanges() const { return _sendWithoutSound.changes(); }
|
||||
[[nodiscard]] rpl::producer<SendWithoutSoundOption> sendWithoutSoundValue() const { return _sendWithoutSound.value(); }
|
||||
[[nodiscard]] rpl::producer<SendWithoutSoundOption> sendWithoutSoundChanges() const { return _sendWithoutSound.changes(); }
|
||||
[[nodiscard]] rpl::producer<bool> suggestGhostModeBeforeViewingStoryValue() const { return _suggestGhostModeBeforeViewingStory.value(); }
|
||||
[[nodiscard]] rpl::producer<bool> suggestGhostModeBeforeViewingStoryChanges() const { return _suggestGhostModeBeforeViewingStory.changes(); }
|
||||
[[nodiscard]] rpl::producer<bool> ghostModeActiveValue() const { return _ghostModeActive.value(); }
|
||||
@@ -154,7 +167,7 @@ private:
|
||||
rpl::variable<bool> _sendOfflinePacketAfterOnline = false;
|
||||
rpl::variable<bool> _markReadAfterAction = true;
|
||||
rpl::variable<bool> _useScheduledMessages = false;
|
||||
rpl::variable<bool> _sendWithoutSound = false;
|
||||
rpl::variable<SendWithoutSoundOption> _sendWithoutSound = SendWithoutSoundOption::Never;
|
||||
rpl::variable<bool> _suggestGhostModeBeforeViewingStory = true;
|
||||
rpl::variable<bool> _ghostModeActive = false;
|
||||
|
||||
|
||||
@@ -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<QString>{
|
||||
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<int>(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<Ui::GenericBox*> box) {
|
||||
const auto save = [=](int index) {
|
||||
AyuSettings::ghost(state->selectedUserId.current()
|
||||
).setSendWithoutSound(
|
||||
static_cast<SendWithoutSoundOption>(index));
|
||||
};
|
||||
SingleChoiceBox(box, {
|
||||
.title = tr::ayu_SendWithoutSoundByDefault(),
|
||||
.options = silentOptions,
|
||||
.initialSelection = static_cast<int>(
|
||||
AyuSettings::ghost(state->selectedUserId.current()
|
||||
).sendWithoutSound()),
|
||||
.callback = save,
|
||||
});
|
||||
}));
|
||||
});
|
||||
AddSkip(container);
|
||||
AddDividerText(container, tr::ayu_SendWithoutSoundByDefaultDescription());
|
||||
|
||||
|
||||
@@ -614,7 +614,7 @@ bool ShouldSendSilent(
|
||||
not_null<PeerData*> peer,
|
||||
const Api::SendOptions &options) {
|
||||
const auto &ghost = AyuSettings::ghost(&peer->session());
|
||||
if (ghost.sendWithoutSound()) {
|
||||
if (ghost.shouldSendWithoutSound()) {
|
||||
return !options.silent;
|
||||
}
|
||||
|
||||
|
||||
@@ -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); },
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user