mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
feat: suggest ghost mode before opening story
This commit is contained in:
@@ -115,6 +115,12 @@ void GhostModeAccountSettings::setSendWithoutSound(bool val) {
|
|||||||
AyuSettings::save();
|
AyuSettings::save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GhostModeAccountSettings::setSuggestGhostModeBeforeViewingStory(bool val) {
|
||||||
|
if (_suggestGhostModeBeforeViewingStory.current() == val) return;
|
||||||
|
_suggestGhostModeBeforeViewingStory = val;
|
||||||
|
AyuSettings::save();
|
||||||
|
}
|
||||||
|
|
||||||
void GhostModeAccountSettings::setGhostModeEnabled(bool val) {
|
void GhostModeAccountSettings::setGhostModeEnabled(bool val) {
|
||||||
if (!_sendReadMessagesLocked.current()) _sendReadMessages = !val;
|
if (!_sendReadMessagesLocked.current()) _sendReadMessages = !val;
|
||||||
if (!_sendReadStoriesLocked.current()) _sendReadStories = !val;
|
if (!_sendReadStoriesLocked.current()) _sendReadStories = !val;
|
||||||
@@ -172,6 +178,7 @@ void to_json(nlohmann::json &j, const GhostModeAccountSettings &s) {
|
|||||||
{"markReadAfterAction", s._markReadAfterAction.current()},
|
{"markReadAfterAction", s._markReadAfterAction.current()},
|
||||||
{"useScheduledMessages", s._useScheduledMessages.current()},
|
{"useScheduledMessages", s._useScheduledMessages.current()},
|
||||||
{"sendWithoutSound", s._sendWithoutSound.current()},
|
{"sendWithoutSound", s._sendWithoutSound.current()},
|
||||||
|
{"suggestGhostModeBeforeViewingStory", s._suggestGhostModeBeforeViewingStory.current()},
|
||||||
{"sendReadMessagesLocked", s._sendReadMessagesLocked.current()},
|
{"sendReadMessagesLocked", s._sendReadMessagesLocked.current()},
|
||||||
{"sendReadStoriesLocked", s._sendReadStoriesLocked.current()},
|
{"sendReadStoriesLocked", s._sendReadStoriesLocked.current()},
|
||||||
{"sendOnlinePacketsLocked", s._sendOnlinePacketsLocked.current()},
|
{"sendOnlinePacketsLocked", s._sendOnlinePacketsLocked.current()},
|
||||||
@@ -189,6 +196,7 @@ void from_json(const nlohmann::json &j, GhostModeAccountSettings &s) {
|
|||||||
s._markReadAfterAction = j.value("markReadAfterAction", true);
|
s._markReadAfterAction = j.value("markReadAfterAction", true);
|
||||||
s._useScheduledMessages = j.value("useScheduledMessages", false);
|
s._useScheduledMessages = j.value("useScheduledMessages", false);
|
||||||
s._sendWithoutSound = j.value("sendWithoutSound", false);
|
s._sendWithoutSound = j.value("sendWithoutSound", false);
|
||||||
|
s._suggestGhostModeBeforeViewingStory = j.value("suggestGhostModeBeforeViewingStory", true);
|
||||||
s._sendReadMessagesLocked = j.value("sendReadMessagesLocked", false);
|
s._sendReadMessagesLocked = j.value("sendReadMessagesLocked", false);
|
||||||
s._sendReadStoriesLocked = j.value("sendReadStoriesLocked", false);
|
s._sendReadStoriesLocked = j.value("sendReadStoriesLocked", false);
|
||||||
s._sendOnlinePacketsLocked = j.value("sendOnlinePacketsLocked", false);
|
s._sendOnlinePacketsLocked = j.value("sendOnlinePacketsLocked", false);
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ public:
|
|||||||
[[nodiscard]] bool markReadAfterAction() const { return _markReadAfterAction.current(); }
|
[[nodiscard]] bool markReadAfterAction() const { return _markReadAfterAction.current(); }
|
||||||
[[nodiscard]] bool useScheduledMessages() const { return _useScheduledMessages.current(); }
|
[[nodiscard]] bool useScheduledMessages() const { return _useScheduledMessages.current(); }
|
||||||
[[nodiscard]] bool sendWithoutSound() const { return _sendWithoutSound.current(); }
|
[[nodiscard]] bool sendWithoutSound() const { return _sendWithoutSound.current(); }
|
||||||
|
[[nodiscard]] bool suggestGhostModeBeforeViewingStory() const { return _suggestGhostModeBeforeViewingStory.current(); }
|
||||||
[[nodiscard]] bool isGhostModeActive() const { return _ghostModeActive.current(); }
|
[[nodiscard]] bool isGhostModeActive() const { return _ghostModeActive.current(); }
|
||||||
[[nodiscard]] bool isUseScheduledMessages() const { return isGhostModeActive() && useScheduledMessages(); }
|
[[nodiscard]] bool isUseScheduledMessages() const { return isGhostModeActive() && useScheduledMessages(); }
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ public:
|
|||||||
void setMarkReadAfterAction(bool val);
|
void setMarkReadAfterAction(bool val);
|
||||||
void setUseScheduledMessages(bool val);
|
void setUseScheduledMessages(bool val);
|
||||||
void setSendWithoutSound(bool val);
|
void setSendWithoutSound(bool val);
|
||||||
|
void setSuggestGhostModeBeforeViewingStory(bool val);
|
||||||
void setGhostModeEnabled(bool val);
|
void setGhostModeEnabled(bool val);
|
||||||
|
|
||||||
void setSendReadMessagesLocked(bool val);
|
void setSendReadMessagesLocked(bool val);
|
||||||
@@ -123,6 +125,8 @@ public:
|
|||||||
[[nodiscard]] rpl::producer<bool> useScheduledMessagesChanges() const { return _useScheduledMessages.changes(); }
|
[[nodiscard]] rpl::producer<bool> useScheduledMessagesChanges() const { return _useScheduledMessages.changes(); }
|
||||||
[[nodiscard]] rpl::producer<bool> sendWithoutSoundValue() const { return _sendWithoutSound.value(); }
|
[[nodiscard]] rpl::producer<bool> sendWithoutSoundValue() const { return _sendWithoutSound.value(); }
|
||||||
[[nodiscard]] rpl::producer<bool> sendWithoutSoundChanges() const { return _sendWithoutSound.changes(); }
|
[[nodiscard]] rpl::producer<bool> 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(); }
|
[[nodiscard]] rpl::producer<bool> ghostModeActiveValue() const { return _ghostModeActive.value(); }
|
||||||
[[nodiscard]] rpl::producer<bool> ghostModeActiveChanges() const { return _ghostModeActive.changes(); }
|
[[nodiscard]] rpl::producer<bool> ghostModeActiveChanges() const { return _ghostModeActive.changes(); }
|
||||||
|
|
||||||
@@ -151,6 +155,7 @@ private:
|
|||||||
rpl::variable<bool> _markReadAfterAction = true;
|
rpl::variable<bool> _markReadAfterAction = true;
|
||||||
rpl::variable<bool> _useScheduledMessages = false;
|
rpl::variable<bool> _useScheduledMessages = false;
|
||||||
rpl::variable<bool> _sendWithoutSound = false;
|
rpl::variable<bool> _sendWithoutSound = false;
|
||||||
|
rpl::variable<bool> _suggestGhostModeBeforeViewingStory = true;
|
||||||
rpl::variable<bool> _ghostModeActive = false;
|
rpl::variable<bool> _ghostModeActive = false;
|
||||||
|
|
||||||
rpl::variable<bool> _sendReadMessagesLocked = false;
|
rpl::variable<bool> _sendReadMessagesLocked = false;
|
||||||
|
|||||||
@@ -6,9 +6,12 @@
|
|||||||
// Copyright @Radolyn, 2026
|
// Copyright @Radolyn, 2026
|
||||||
#include "ayu/ayu_state.h"
|
#include "ayu/ayu_state.h"
|
||||||
|
|
||||||
|
#include "ayu/ayu_settings.h"
|
||||||
|
|
||||||
namespace AyuState {
|
namespace AyuState {
|
||||||
|
|
||||||
std::unordered_map<PeerId, std::unordered_set<MsgId>> hiddenMessages;
|
std::unordered_map<PeerId, std::unordered_set<MsgId>> hiddenMessages;
|
||||||
|
Main::Session *disableGhostModeOnStoryCloseSession = nullptr;
|
||||||
|
|
||||||
void hide(PeerId peerId, MsgId messageId) {
|
void hide(PeerId peerId, MsgId messageId) {
|
||||||
hiddenMessages[peerId].insert(messageId);
|
hiddenMessages[peerId].insert(messageId);
|
||||||
@@ -30,4 +33,18 @@ bool isHidden(not_null<HistoryItem*> item) {
|
|||||||
return isHidden(item->history()->peer->id, item->id);
|
return isHidden(item->history()->peer->id, item->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setDisableGhostModeOnStoryClose(Main::Session *session) {
|
||||||
|
disableGhostModeOnStoryCloseSession = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableGhostModeOnStoryClose(Main::Session *session) {
|
||||||
|
if (disableGhostModeOnStoryCloseSession != session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
disableGhostModeOnStoryCloseSession = nullptr;
|
||||||
|
if (session) {
|
||||||
|
AyuSettings::ghost(session).setGhostModeEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
|
||||||
|
namespace Main {
|
||||||
|
class Session;
|
||||||
|
} // namespace Main
|
||||||
|
|
||||||
namespace AyuState {
|
namespace AyuState {
|
||||||
|
|
||||||
void hide(PeerId peerId, MsgId messageId);
|
void hide(PeerId peerId, MsgId messageId);
|
||||||
@@ -16,4 +20,7 @@ void hide(not_null<HistoryItem*> item);
|
|||||||
bool isHidden(PeerId peerId, MsgId messageId);
|
bool isHidden(PeerId peerId, MsgId messageId);
|
||||||
bool isHidden(not_null<HistoryItem*> item);
|
bool isHidden(not_null<HistoryItem*> item);
|
||||||
|
|
||||||
|
void setDisableGhostModeOnStoryClose(Main::Session *session);
|
||||||
|
void disableGhostModeOnStoryClose(Main::Session *session);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ void BuildGhostEssentials(SectionBuilder &builder) {
|
|||||||
dst.setMarkReadAfterAction(src.markReadAfterAction());
|
dst.setMarkReadAfterAction(src.markReadAfterAction());
|
||||||
dst.setUseScheduledMessages(src.useScheduledMessages());
|
dst.setUseScheduledMessages(src.useScheduledMessages());
|
||||||
dst.setSendWithoutSound(src.sendWithoutSound());
|
dst.setSendWithoutSound(src.sendWithoutSound());
|
||||||
|
dst.setSuggestGhostModeBeforeViewingStory(src.suggestGhostModeBeforeViewingStory());
|
||||||
dst.setSendReadMessagesLocked(src.sendReadMessagesLocked());
|
dst.setSendReadMessagesLocked(src.sendReadMessagesLocked());
|
||||||
dst.setSendReadStoriesLocked(src.sendReadStoriesLocked());
|
dst.setSendReadStoriesLocked(src.sendReadStoriesLocked());
|
||||||
dst.setSendOnlinePacketsLocked(src.sendOnlinePacketsLocked());
|
dst.setSendOnlinePacketsLocked(src.sendOnlinePacketsLocked());
|
||||||
@@ -472,6 +473,34 @@ void BuildGhostEssentials(SectionBuilder &builder) {
|
|||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
AddDividerText(container, tr::ayu_SendWithoutSoundByDefaultDescription());
|
AddDividerText(container, tr::ayu_SendWithoutSoundByDefaultDescription());
|
||||||
|
|
||||||
|
AddSkip(container);
|
||||||
|
const auto suggestGhostModeButton = AddButtonWithIcon(
|
||||||
|
container,
|
||||||
|
tr::ayu_SuggestGhostModeBeforeViewingStory(),
|
||||||
|
st::settingsButtonNoIcon);
|
||||||
|
if (wctx.highlights) {
|
||||||
|
wctx.highlights->push_back(std::make_pair(
|
||||||
|
u"ayu/suggestGhostModeBeforeViewingStory"_q,
|
||||||
|
HighlightEntry{ suggestGhostModeButton.get(), {} }));
|
||||||
|
}
|
||||||
|
suggestGhostModeButton->toggleOn(
|
||||||
|
state->selectedUserId.value()
|
||||||
|
| rpl::map([](uint64 id) {
|
||||||
|
return AyuSettings::ghost(id).suggestGhostModeBeforeViewingStoryValue();
|
||||||
|
}) | rpl::flatten_latest()
|
||||||
|
)->toggledValue(
|
||||||
|
) | rpl::filter(
|
||||||
|
[=](bool enabled) {
|
||||||
|
return enabled != AyuSettings::ghost(state->selectedUserId.current()).suggestGhostModeBeforeViewingStory();
|
||||||
|
}
|
||||||
|
) | on_next(
|
||||||
|
[=](bool enabled) {
|
||||||
|
AyuSettings::ghost(state->selectedUserId.current()).setSuggestGhostModeBeforeViewingStory(enabled);
|
||||||
|
},
|
||||||
|
container->lifetime());
|
||||||
|
AddSkip(container);
|
||||||
|
AddDividerText(container, tr::ayu_SuggestGhostModeBeforeViewingStoryDescription());
|
||||||
|
|
||||||
auto showMenu = [=] {
|
auto showMenu = [=] {
|
||||||
state->menu = base::make_unique_q<Ui::PopupMenu>(
|
state->menu = base::make_unique_q<Ui::PopupMenu>(
|
||||||
pickerButton,
|
pickerButton,
|
||||||
@@ -525,6 +554,11 @@ void BuildGhostEssentials(SectionBuilder &builder) {
|
|||||||
.title = tr::ayu_SendWithoutSoundByDefault(tr::now),
|
.title = tr::ayu_SendWithoutSoundByDefault(tr::now),
|
||||||
.section = sctx.sectionId,
|
.section = sctx.sectionId,
|
||||||
});
|
});
|
||||||
|
sctx.entries->push_back({
|
||||||
|
.id = u"ayu/suggestGhostModeBeforeViewingStory"_q,
|
||||||
|
.title = tr::ayu_SuggestGhostModeBeforeViewingStory(tr::now),
|
||||||
|
.section = sctx.sectionId,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include <kurlmimedata.h>
|
#include <kurlmimedata.h>
|
||||||
|
|
||||||
// AyuGram includes
|
// AyuGram includes
|
||||||
|
#include "ayu/ayu_state.h"
|
||||||
#include "ayu/features/streamer_mode/streamer_mode.h"
|
#include "ayu/features/streamer_mode/streamer_mode.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -7933,6 +7934,7 @@ Window::SessionController *OverlayWidget::findWindow(bool switchTo) const {
|
|||||||
|
|
||||||
// #TODO unite and check
|
// #TODO unite and check
|
||||||
void OverlayWidget::clearBeforeHide() {
|
void OverlayWidget::clearBeforeHide() {
|
||||||
|
AyuState::disableGhostModeOnStoryClose(_storiesSession);
|
||||||
_message = nullptr;
|
_message = nullptr;
|
||||||
_sharedMedia = nullptr;
|
_sharedMedia = nullptr;
|
||||||
_sharedMediaData = std::nullopt;
|
_sharedMediaData = std::nullopt;
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
#include <QtGui/QScreen>
|
#include <QtGui/QScreen>
|
||||||
|
|
||||||
|
// AyuGram includes
|
||||||
|
#include "ayu/ayu_settings.h"
|
||||||
|
#include "ayu/ayu_state.h"
|
||||||
|
#include "data/data_story.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -567,6 +573,38 @@ Window::Adaptive &Controller::adaptive() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Controller::openInMediaView(Media::View::OpenRequest &&request) {
|
void Controller::openInMediaView(Media::View::OpenRequest &&request) {
|
||||||
|
if (request.story()) {
|
||||||
|
const auto story = not_null{ request.story() };
|
||||||
|
auto &ghost = AyuSettings::ghost(&story->session());
|
||||||
|
const auto suggestGhostMode = ghost.suggestGhostModeBeforeViewingStory()
|
||||||
|
&& ghost.sendReadStories()
|
||||||
|
&& !ghost.sendReadStoriesLocked()
|
||||||
|
&& !ghost.isGhostModeActive();
|
||||||
|
if (suggestGhostMode) {
|
||||||
|
const auto controller = request.controller();
|
||||||
|
const auto context = request.storiesContext();
|
||||||
|
show(Ui::MakeConfirmBox({
|
||||||
|
.text = tr::ayu_SuggestGhostModeStoryText(tr::now, tr::rich),
|
||||||
|
.confirmed = [=](Fn<void()> close) {
|
||||||
|
close();
|
||||||
|
AyuSettings::ghost(&story->session()).setGhostModeEnabled(true);
|
||||||
|
AyuState::setDisableGhostModeOnStoryClose(&story->session());
|
||||||
|
_openInMediaViewRequests.fire(
|
||||||
|
Media::View::OpenRequest(controller, story, context));
|
||||||
|
},
|
||||||
|
.cancelled = [=](Fn<void()> close) {
|
||||||
|
close();
|
||||||
|
_openInMediaViewRequests.fire(
|
||||||
|
Media::View::OpenRequest(controller, story, context));
|
||||||
|
},
|
||||||
|
.confirmText = tr::ayu_SuggestGhostModeStoryActionTextYes(),
|
||||||
|
.cancelText = tr::ayu_SuggestGhostModeStoryActionTextNo(),
|
||||||
|
.title = tr::ayu_SuggestGhostModeTitle(),
|
||||||
|
.strictCancel = true,
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
_openInMediaViewRequests.fire(std::move(request));
|
_openInMediaViewRequests.fire(std::move(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user