feat: reformat ayu files with resharper

This commit is contained in:
ZavaruKitsu 2023-07-09 18:09:01 +00:00
parent 85e8c75ad1
commit 32a2de1bef
35 changed files with 1866 additions and 1590 deletions

View file

@ -8,127 +8,155 @@
#include "ayu_lang.h" #include "ayu_lang.h"
#include "qjsondocument.h" #include "qjsondocument.h"
#include "lang/lang_instance.h"
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "lang/lang_instance.h"
CustomLangPack *CustomLangPack::instance = nullptr; CustomLangPack* CustomLangPack::instance = nullptr;
CustomLangPack::CustomLangPack() = default; CustomLangPack::CustomLangPack() = default;
void CustomLangPack::initInstance() { void CustomLangPack::initInstance()
if (!instance) {
instance = new CustomLangPack; if (!instance)
instance = new CustomLangPack;
} }
CustomLangPack *CustomLangPack::currentInstance() { CustomLangPack* CustomLangPack::currentInstance()
return instance; {
return instance;
} }
void CustomLangPack::fetchCustomLangPack(const QString &langPackId, const QString &langPackBaseId) { void CustomLangPack::fetchCustomLangPack(const QString& langPackId, const QString& langPackBaseId)
LOG(("Current Language pack ID: %1, Base ID: %2").arg(langPackId, langPackBaseId)); {
LOG(("Current Language pack ID: %1, Base ID: %2").arg(langPackId, langPackBaseId));
auto finalLangPackId = langPackId; auto finalLangPackId = langPackId;
if (finalLangPackId == qsl("pt-br")) { // meh if (finalLangPackId == qsl("pt-br"))
finalLangPackId = qsl("pt"); {
} // meh
finalLangPackId = qsl("pt");
}
const auto proxy = Core::App().settings().proxy().isEnabled() ? Core::App().settings().proxy().selected() const auto proxy = Core::App().settings().proxy().isEnabled()
: MTP::ProxyData(); ? Core::App().settings().proxy().selected()
if (proxy.type == MTP::ProxyData::Type::Socks5 || proxy.type == MTP::ProxyData::Type::Http) { : MTP::ProxyData();
QNetworkProxy LocaleProxy = MTP::ToNetworkProxy(MTP::ToDirectIpProxy(proxy)); if (proxy.type == MTP::ProxyData::Type::Socks5 || proxy.type == MTP::ProxyData::Type::Http)
networkManager.setProxy(LocaleProxy); {
} QNetworkProxy LocaleProxy = ToNetworkProxy(ToDirectIpProxy(proxy));
networkManager.setProxy(LocaleProxy);
}
QUrl url; QUrl url;
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) { if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg( {
finalLangPackId)); url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
} else { finalLangPackId));
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg( }
needFallback ? langPackBaseId : finalLangPackId)); else
} {
_chkReply = networkManager.get(QNetworkRequest(url)); url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
connect(_chkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(fetchError(QNetworkReply::NetworkError))); needFallback ? langPackBaseId : finalLangPackId));
connect(_chkReply, SIGNAL(finished()), this, SLOT(fetchFinished())); }
LOG(("Fetching %1 lang pack...").arg( _chkReply = networkManager.get(QNetworkRequest(url));
needFallback ? (langPackBaseId.isEmpty() ? finalLangPackId : langPackBaseId) : finalLangPackId)); connect(_chkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(fetchError(QNetworkReply::NetworkError)));
connect(_chkReply, SIGNAL(finished()), this, SLOT(fetchFinished()));
LOG(("Fetching %1 lang pack...").arg(
needFallback ? (langPackBaseId.isEmpty() ? finalLangPackId : langPackBaseId) : finalLangPackId));
} }
void CustomLangPack::fetchFinished() { void CustomLangPack::fetchFinished()
if (!_chkReply) return; {
if (!_chkReply) return;
QString langPackBaseId = Lang::GetInstance().baseId(); QString langPackBaseId = Lang::GetInstance().baseId();
QString langPackId = Lang::GetInstance().id(); QString langPackId = Lang::GetInstance().id();
auto statusCode = _chkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); auto statusCode = _chkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode == 404 && !langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) { if (statusCode == 404 && !langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId)); {
needFallback = true; LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
_chkReply->disconnect(); needFallback = true;
fetchCustomLangPack("", langPackBaseId); _chkReply->disconnect();
} else { fetchCustomLangPack("", langPackBaseId);
QByteArray result = _chkReply->readAll().trimmed(); }
QJsonParseError error{}; else
QJsonDocument str = QJsonDocument::fromJson(result, &error); {
if (error.error == QJsonParseError::NoError) { QByteArray result = _chkReply->readAll().trimmed();
parseLangFile(str); QJsonParseError error{};
} else { QJsonDocument str = QJsonDocument::fromJson(result, &error);
LOG(("Incorrect JSON File. Fallback to default language: English...")); if (error.error == QJsonParseError::NoError)
loadDefaultLangFile(); {
} parseLangFile(str);
}
else
{
LOG(("Incorrect JSON File. Fallback to default language: English..."));
loadDefaultLangFile();
}
_chkReply = nullptr; _chkReply = nullptr;
} }
} }
void CustomLangPack::fetchError(QNetworkReply::NetworkError e) { void CustomLangPack::fetchError(QNetworkReply::NetworkError e)
LOG(("Network error: %1").arg(e)); {
LOG(("Network error: %1").arg(e));
if (e == QNetworkReply::NetworkError::ContentNotFoundError) { if (e == QNetworkReply::NetworkError::ContentNotFoundError)
QString langPackBaseId = Lang::GetInstance().baseId(); {
QString langPackId = Lang::GetInstance().id(); QString langPackBaseId = Lang::GetInstance().baseId();
QString langPackId = Lang::GetInstance().id();
if (!langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) { if (!langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId)); {
needFallback = true; LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
_chkReply->disconnect(); needFallback = true;
fetchCustomLangPack("", langPackBaseId); _chkReply->disconnect();
} else { fetchCustomLangPack("", langPackBaseId);
LOG(("AyuGram Language pack not found! Fallback to default language: English...")); }
loadDefaultLangFile(); else
_chkReply = nullptr; {
} LOG(("AyuGram Language pack not found! Fallback to default language: English..."));
} loadDefaultLangFile();
_chkReply = nullptr;
}
}
} }
void CustomLangPack::loadDefaultLangFile() { void CustomLangPack::loadDefaultLangFile()
QFile file(":/localization/en.json"); {
if (file.open(QIODevice::ReadOnly)) { QFile file(":/localization/en.json");
QJsonDocument str = QJsonDocument::fromJson(file.readAll()); if (file.open(QIODevice::ReadOnly))
QJsonObject json = str.object(); {
for (const QString &key: json.keys()) { QJsonDocument str = QJsonDocument::fromJson(file.readAll());
Lang::GetInstance().applyValue(key.toUtf8(), json.value(key).toString().toUtf8()); QJsonObject json = str.object();
} for (const QString& key : json.keys())
Lang::GetInstance().updatePluralRules(); {
file.close(); Lang::GetInstance().applyValue(key.toUtf8(), json.value(key).toString().toUtf8());
} }
Lang::GetInstance().updatePluralRules();
file.close();
}
} }
void CustomLangPack::parseLangFile(QJsonDocument str) { void CustomLangPack::parseLangFile(QJsonDocument str)
QJsonObject json = str.object(); {
for (const QString &brokenKey: json.keys()) { QJsonObject json = str.object();
auto key = qsl("ayu_") + brokenKey; for (const QString& brokenKey : json.keys())
auto val = json.value(brokenKey).toString().replace(qsl("&"), qsl("&")).toUtf8(); {
auto key = qsl("ayu_") + brokenKey;
auto val = json.value(brokenKey).toString().replace(qsl("&"), qsl("&")).toUtf8();
Lang::GetInstance().resetValue(key.toUtf8()); Lang::GetInstance().resetValue(key.toUtf8());
Lang::GetInstance().applyValue(key.toUtf8(), val); Lang::GetInstance().applyValue(key.toUtf8(), val);
if (key.contains("#other")) { if (key.contains("#other"))
Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few")); {
Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few")); Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few"));
Lang::GetInstance().applyValue(key.toUtf8().replace("#other", "#few"), val); Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few"));
Lang::GetInstance().applyValue(key.toUtf8().replace("#other", "#many"), val); Lang::GetInstance().applyValue(key.toUtf8().replace("#other", "#few"), val);
} Lang::GetInstance().applyValue(key.toUtf8().replace("#other", "#many"), val);
} }
Lang::GetInstance().updatePluralRules(); }
} Lang::GetInstance().updatePluralRules();
}

View file

@ -10,36 +10,36 @@
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <QtXml/QDomDocument> #include <QtXml/QDomDocument>
class CustomLangPack : public QObject { class CustomLangPack : public QObject
Q_OBJECT {
Q_OBJECT
Q_DISABLE_COPY(CustomLangPack) Q_DISABLE_COPY(CustomLangPack)
public: public:
static CustomLangPack *currentInstance(); static CustomLangPack* currentInstance();
static void initInstance(); static void initInstance();
static CustomLangPack *instance; static CustomLangPack* instance;
void fetchCustomLangPack(const QString &langPackId, const QString &langPackBaseId); void fetchCustomLangPack(const QString& langPackId, const QString& langPackBaseId);
void loadDefaultLangFile(); void loadDefaultLangFile();
void parseLangFile(QJsonDocument str); void parseLangFile(QJsonDocument str);
public Q_SLOTS: public Q_SLOTS:
void fetchFinished();
void fetchFinished(); void fetchError(QNetworkReply::NetworkError e);
void fetchError(QNetworkReply::NetworkError e);
private: private:
CustomLangPack(); CustomLangPack();
~CustomLangPack() = default; ~CustomLangPack() override = default;
QNetworkAccessManager networkManager; QNetworkAccessManager networkManager;
QNetworkReply *_chkReply = nullptr; QNetworkReply* _chkReply = nullptr;
bool needFallback = false; bool needFallback = false;
}; };

View file

@ -12,199 +12,239 @@
using json = nlohmann::json; using json = nlohmann::json;
namespace AyuSettings { namespace AyuSettings
const QString filename = "tdata/ayu_settings.json"; {
std::optional<AyuGramSettings> settings = std::nullopt; const QString filename = "tdata/ayu_settings.json";
std::optional<AyuGramSettings> settings = std::nullopt;
rpl::variable<bool> sendReadPacketsReactive; rpl::variable<bool> sendReadPacketsReactive;
rpl::variable<bool> sendOnlinePacketsReactive; rpl::variable<bool> sendOnlinePacketsReactive;
rpl::variable<bool> sendUploadProgressReactive; rpl::variable<bool> sendUploadProgressReactive;
rpl::variable<bool> sendOfflinePacketAfterOnlineReactive; rpl::variable<bool> sendOfflinePacketAfterOnlineReactive;
rpl::variable<QString> deletedMarkReactive; rpl::variable<QString> deletedMarkReactive;
rpl::variable<QString> editedMarkReactive; rpl::variable<QString> editedMarkReactive;
rpl::variable<int> showPeerIdReactive; rpl::variable<int> showPeerIdReactive;
rpl::variable<bool> ghostModeEnabled; rpl::variable<bool> ghostModeEnabled;
rpl::lifetime lifetime = rpl::lifetime(); rpl::lifetime lifetime = rpl::lifetime();
bool ghostModeEnabled_util(AyuGramSettings &settingsUtil) { bool ghostModeEnabled_util(AyuGramSettings& settingsUtil)
return (!settingsUtil.sendReadPackets {
&& !settingsUtil.sendOnlinePackets return (!settingsUtil.sendReadPackets
&& !settingsUtil.sendUploadProgress && !settingsUtil.sendOnlinePackets
&& settingsUtil.sendOfflinePacketAfterOnline); && !settingsUtil.sendUploadProgress
} && settingsUtil.sendOfflinePacketAfterOnline);
}
void initialize() { void initialize()
if (settings.has_value()) { {
return; if (settings.has_value())
} {
return;
}
settings = AyuGramSettings(); settings = AyuGramSettings();
sendReadPacketsReactive.value() | rpl::filter([=](bool val) { sendReadPacketsReactive.value() | rpl::filter([=](bool val)
return (val != settings->sendReadPackets); {
}) | rpl::start_with_next([=](bool val) { return (val != settings->sendReadPackets);
ghostModeEnabled = ghostModeEnabled_util(settings.value()); }) | start_with_next([=](bool val)
}, lifetime); {
sendOnlinePacketsReactive.value() | rpl::filter([=](bool val) { ghostModeEnabled = ghostModeEnabled_util(settings.value());
return (val != settings->sendOnlinePackets); }, lifetime);
}) | rpl::start_with_next([=](bool val) { sendOnlinePacketsReactive.value() | rpl::filter([=](bool val)
ghostModeEnabled = ghostModeEnabled_util(settings.value()); {
}, lifetime); return (val != settings->sendOnlinePackets);
sendUploadProgressReactive.value() | rpl::filter([=](bool val) { }) | start_with_next([=](bool val)
return (val != settings->sendUploadProgress); {
}) | rpl::start_with_next([=](bool val) { ghostModeEnabled = ghostModeEnabled_util(settings.value());
ghostModeEnabled = ghostModeEnabled_util(settings.value()); }, lifetime);
}, lifetime); sendUploadProgressReactive.value() | rpl::filter([=](bool val)
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val) { {
return (val != settings->sendOfflinePacketAfterOnline); return (val != settings->sendUploadProgress);
}) | rpl::start_with_next([=](bool val) { }) | start_with_next([=](bool val)
ghostModeEnabled = ghostModeEnabled_util(settings.value()); {
}, lifetime); ghostModeEnabled = ghostModeEnabled_util(settings.value());
} }, lifetime);
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val)
{
return (val != settings->sendOfflinePacketAfterOnline);
}) | start_with_next([=](bool val)
{
ghostModeEnabled = ghostModeEnabled_util(settings.value());
}, lifetime);
}
void postinitialize() { void postinitialize()
sendReadPacketsReactive = settings->sendReadPackets; {
sendOnlinePacketsReactive = settings->sendOnlinePackets; sendReadPacketsReactive = settings->sendReadPackets;
sendOnlinePacketsReactive = settings->sendOnlinePackets;
deletedMarkReactive = settings->deletedMark; deletedMarkReactive = settings->deletedMark;
editedMarkReactive = settings->editedMark; editedMarkReactive = settings->editedMark;
showPeerIdReactive = settings->showPeerId; showPeerIdReactive = settings->showPeerId;
ghostModeEnabled = ghostModeEnabled_util(settings.value()); ghostModeEnabled = ghostModeEnabled_util(settings.value());
} }
AyuGramSettings &getInstance() { AyuGramSettings& getInstance()
initialize(); {
return settings.value(); initialize();
} return settings.value();
}
void load() { void load()
QFile file(filename); {
if (!file.exists()) { QFile file(filename);
return; if (!file.exists())
} {
file.open(QIODevice::ReadOnly); return;
QByteArray data = file.readAll(); }
file.close(); file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
file.close();
initialize(); initialize();
json p = json::parse(data); json p = json::parse(data);
settings = p.template get<AyuGramSettings>(); settings = p.get<AyuGramSettings>();
postinitialize(); postinitialize();
} }
void save() { void save()
initialize(); {
initialize();
json p = settings.value(); json p = settings.value();
QFile file(filename); QFile file(filename);
file.open(QIODevice::WriteOnly); file.open(QIODevice::WriteOnly);
file.write(p.dump().c_str()); file.write(p.dump().c_str());
file.close(); file.close();
postinitialize(); postinitialize();
} }
void AyuGramSettings::set_sendReadPackets(bool val) { void AyuGramSettings::set_sendReadPackets(bool val)
sendReadPackets = val; {
sendReadPacketsReactive = val; sendReadPackets = val;
} sendReadPacketsReactive = val;
}
void AyuGramSettings::set_sendOnlinePackets(bool val) { void AyuGramSettings::set_sendOnlinePackets(bool val)
sendOnlinePackets = val; {
sendOnlinePacketsReactive = val; sendOnlinePackets = val;
} sendOnlinePacketsReactive = val;
}
void AyuGramSettings::set_sendUploadProgress(bool val) { void AyuGramSettings::set_sendUploadProgress(bool val)
sendUploadProgress = val; {
sendUploadProgressReactive = val; sendUploadProgress = val;
} sendUploadProgressReactive = val;
}
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val) { void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val)
sendOfflinePacketAfterOnline = val; {
sendOfflinePacketAfterOnlineReactive = val; sendOfflinePacketAfterOnline = val;
} sendOfflinePacketAfterOnlineReactive = val;
}
void AyuGramSettings::set_markReadAfterSend(bool val) { void AyuGramSettings::set_markReadAfterSend(bool val)
markReadAfterSend = val; {
} markReadAfterSend = val;
}
void AyuGramSettings::set_useScheduledMessages(bool val) { void AyuGramSettings::set_useScheduledMessages(bool val)
useScheduledMessages = val; {
} useScheduledMessages = val;
}
void AyuGramSettings::set_keepDeletedMessages(bool val) { void AyuGramSettings::set_keepDeletedMessages(bool val)
keepDeletedMessages = val; {
} keepDeletedMessages = val;
}
void AyuGramSettings::set_keepMessagesHistory(bool val) { void AyuGramSettings::set_keepMessagesHistory(bool val)
keepMessagesHistory = val; {
} keepMessagesHistory = val;
}
void AyuGramSettings::set_enableAds(bool val) { void AyuGramSettings::set_enableAds(bool val)
enableAds = val; {
} enableAds = val;
}
void AyuGramSettings::set_deletedMark(QString val) { void AyuGramSettings::set_deletedMark(QString val)
deletedMark = std::move(val); {
deletedMarkReactive = deletedMark; deletedMark = std::move(val);
} deletedMarkReactive = deletedMark;
}
void AyuGramSettings::set_editedMark(QString val) { void AyuGramSettings::set_editedMark(QString val)
editedMark = std::move(val); {
editedMarkReactive = editedMark; editedMark = std::move(val);
} editedMarkReactive = editedMark;
}
void AyuGramSettings::set_recentStickersCount(int val) { void AyuGramSettings::set_recentStickersCount(int val)
recentStickersCount = val; {
} recentStickersCount = val;
}
void AyuGramSettings::set_showGhostToggleInDrawer(bool val) { void AyuGramSettings::set_showGhostToggleInDrawer(bool val)
showGhostToggleInDrawer = val; {
} showGhostToggleInDrawer = val;
}
void AyuGramSettings::set_showPeerId(int val) { void AyuGramSettings::set_showPeerId(int val)
showPeerId = val; {
showPeerIdReactive = val; showPeerId = val;
} showPeerIdReactive = val;
}
void AyuGramSettings::set_showMessageSeconds(bool val) { void AyuGramSettings::set_showMessageSeconds(bool val)
showMessageSeconds = val; {
} showMessageSeconds = val;
}
void AyuGramSettings::set_stickerConfirmation(bool val) { void AyuGramSettings::set_stickerConfirmation(bool val)
stickerConfirmation = val; {
} stickerConfirmation = val;
}
void AyuGramSettings::set_GIFConfirmation(bool val) { void AyuGramSettings::set_GIFConfirmation(bool val)
GIFConfirmation = val; {
} GIFConfirmation = val;
}
void AyuGramSettings::set_voiceConfirmation(bool val) { void AyuGramSettings::set_voiceConfirmation(bool val)
voiceConfirmation = val; {
} voiceConfirmation = val;
}
bool get_ghostModeEnabled() { bool get_ghostModeEnabled()
return ghostModeEnabled.current(); {
} return ghostModeEnabled.current();
}
rpl::producer<QString> get_deletedMarkReactive() { rpl::producer<QString> get_deletedMarkReactive()
return deletedMarkReactive.value(); {
} return deletedMarkReactive.value();
}
rpl::producer<QString> get_editedMarkReactive() { rpl::producer<QString> get_editedMarkReactive()
return editedMarkReactive.value(); {
} return editedMarkReactive.value();
}
rpl::producer<int> get_showPeerIdReactive() { rpl::producer<int> get_showPeerIdReactive()
return showPeerIdReactive.value(); {
} return showPeerIdReactive.value();
}
rpl::producer<bool> get_ghostModeEnabledReactive() { rpl::producer<bool> get_ghostModeEnabledReactive()
return ghostModeEnabled.value(); {
} return ghostModeEnabled.value();
}
} }

View file

@ -7,149 +7,152 @@
#pragma once #pragma once
#include "rpl/producer.h"
#include "lang_auto.h" #include "lang_auto.h"
#include "ayu/libs/json.hpp" #include "ayu/libs/json.hpp"
#include "ayu/libs/json_ext.hpp" #include "ayu/libs/json_ext.hpp"
#include "rpl/producer.h"
namespace AyuSettings { namespace AyuSettings
class AyuGramSettings { {
public: class AyuGramSettings
AyuGramSettings() { {
// ~ Ghost essentials public:
sendReadPackets = true; AyuGramSettings()
sendOnlinePackets = true; {
sendUploadProgress = true; // ~ Ghost essentials
sendReadPackets = true;
sendOnlinePackets = true;
sendUploadProgress = true;
sendOfflinePacketAfterOnline = false; sendOfflinePacketAfterOnline = false;
markReadAfterSend = true; markReadAfterSend = true;
useScheduledMessages = false; useScheduledMessages = false;
// ~ Message edits & deletion history // ~ Message edits & deletion history
keepDeletedMessages = true; keepDeletedMessages = true;
keepMessagesHistory = true; keepMessagesHistory = true;
// ~ QoL toggles // ~ QoL toggles
enableAds = false; enableAds = false;
// ~ Customization // ~ Customization
deletedMark = "🧹"; deletedMark = "🧹";
editedMark = tr::lng_edited(tr::now); editedMark = tr::lng_edited(tr::now);
recentStickersCount = 20; recentStickersCount = 20;
showGhostToggleInDrawer = true; showGhostToggleInDrawer = true;
// ~ Beta functionality // ~ Beta functionality
stickerConfirmation = false; stickerConfirmation = false;
GIFConfirmation = false; GIFConfirmation = false;
voiceConfirmation = false; voiceConfirmation = false;
/* /*
* showPeerId = 0 means no ID shown * showPeerId = 0 means no ID shown
* showPeerId = 1 means ID shown as for Telegram API devs * showPeerId = 1 means ID shown as for Telegram API devs
* showPeerId = 2 means ID shown as for Bot API devs (-100) * showPeerId = 2 means ID shown as for Bot API devs (-100)
*/ */
showPeerId = 2; showPeerId = 2;
showMessageSeconds = false; showMessageSeconds = false;
stickerConfirmation = false; stickerConfirmation = false;
GIFConfirmation = false; GIFConfirmation = false;
voiceConfirmation = false; voiceConfirmation = false;
} }
bool sendReadPackets; bool sendReadPackets;
bool sendOnlinePackets; bool sendOnlinePackets;
bool sendUploadProgress; bool sendUploadProgress;
bool sendOfflinePacketAfterOnline; bool sendOfflinePacketAfterOnline;
bool markReadAfterSend; bool markReadAfterSend;
bool useScheduledMessages; bool useScheduledMessages;
bool keepDeletedMessages; bool keepDeletedMessages;
bool keepMessagesHistory; bool keepMessagesHistory;
bool enableAds; bool enableAds;
QString deletedMark; QString deletedMark;
QString editedMark; QString editedMark;
int recentStickersCount; int recentStickersCount;
bool showGhostToggleInDrawer; bool showGhostToggleInDrawer;
int showPeerId; int showPeerId;
bool showMessageSeconds; bool showMessageSeconds;
bool stickerConfirmation; bool stickerConfirmation;
bool GIFConfirmation; bool GIFConfirmation;
bool voiceConfirmation; bool voiceConfirmation;
public: public:
void set_sendReadPackets(bool val); void set_sendReadPackets(bool val);
void set_sendOnlinePackets(bool val); void set_sendOnlinePackets(bool val);
void set_sendUploadProgress(bool val); void set_sendUploadProgress(bool val);
void set_sendOfflinePacketAfterOnline(bool val); void set_sendOfflinePacketAfterOnline(bool val);
void set_markReadAfterSend(bool val); void set_markReadAfterSend(bool val);
void set_useScheduledMessages(bool val); void set_useScheduledMessages(bool val);
void set_keepDeletedMessages(bool val); void set_keepDeletedMessages(bool val);
void set_keepMessagesHistory(bool val); void set_keepMessagesHistory(bool val);
void set_enableAds(bool val); void set_enableAds(bool val);
void set_deletedMark(QString val); void set_deletedMark(QString val);
void set_editedMark(QString val); void set_editedMark(QString val);
void set_recentStickersCount(int val); void set_recentStickersCount(int val);
void set_showGhostToggleInDrawer(bool val); void set_showGhostToggleInDrawer(bool val);
void set_showPeerId(int val); void set_showPeerId(int val);
void set_showMessageSeconds(bool val); void set_showMessageSeconds(bool val);
void set_stickerConfirmation(bool val); void set_stickerConfirmation(bool val);
void set_GIFConfirmation(bool val); void set_GIFConfirmation(bool val);
void set_voiceConfirmation(bool val); void set_voiceConfirmation(bool val);
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
AyuGramSettings, AyuGramSettings,
sendReadPackets, sendReadPackets,
sendOnlinePackets, sendOnlinePackets,
sendUploadProgress, sendUploadProgress,
sendOfflinePacketAfterOnline, sendOfflinePacketAfterOnline,
markReadAfterSend, markReadAfterSend,
useScheduledMessages, useScheduledMessages,
keepDeletedMessages, keepDeletedMessages,
keepMessagesHistory, keepMessagesHistory,
enableAds, enableAds,
deletedMark, deletedMark,
editedMark, editedMark,
recentStickersCount, recentStickersCount,
showGhostToggleInDrawer, showGhostToggleInDrawer,
showPeerId, showPeerId,
showMessageSeconds, showMessageSeconds,
stickerConfirmation, stickerConfirmation,
GIFConfirmation, GIFConfirmation,
voiceConfirmation voiceConfirmation
); );
AyuGramSettings &getInstance(); AyuGramSettings& getInstance();
void load(); void load();
void save(); void save();
rpl::producer<QString> get_deletedMarkReactive(); rpl::producer<QString> get_deletedMarkReactive();
rpl::producer<QString> get_editedMarkReactive(); rpl::producer<QString> get_editedMarkReactive();
rpl::producer<int> get_showPeerIdReactive(); rpl::producer<int> get_showPeerIdReactive();
// computed fields // computed fields
bool get_ghostModeEnabled(); bool get_ghostModeEnabled();
rpl::producer<bool> get_ghostModeEnabledReactive(); rpl::producer<bool> get_ghostModeEnabledReactive();
} }

View file

@ -7,14 +7,17 @@
#include "ayu_state.h" #include "ayu_state.h"
namespace AyuState { namespace AyuState
void setAllowSendReadPacket(bool val, int resetAfter) { {
allowSendReadPacket.val = val; void setAllowSendReadPacket(bool val, int resetAfter)
allowSendReadPacket.resetAfter = resetAfter; {
} allowSendReadPacket.val = val;
allowSendReadPacket.resetAfter = resetAfter;
}
bool getAllowSendPacket() { bool getAllowSendPacket()
auto settings = &AyuSettings::getInstance(); {
return settings->sendReadPackets || processVariable(allowSendReadPacket); auto settings = &AyuSettings::getInstance();
} return settings->sendReadPackets || processVariable(allowSendReadPacket);
} }
}

View file

@ -9,33 +9,39 @@
#include "ayu_settings.h" #include "ayu_settings.h"
namespace AyuState { namespace AyuState
namespace { {
class AyuStateVariable { namespace
public: {
bool val; class AyuStateVariable
int resetAfter; {
}; public:
bool val;
int resetAfter;
};
AyuStateVariable allowSendReadPacket; AyuStateVariable allowSendReadPacket;
bool processVariable(AyuStateVariable &variable) { bool processVariable(AyuStateVariable& variable)
if (variable.resetAfter == -1) { {
return variable.val; if (variable.resetAfter == -1)
} {
return variable.val;
}
variable.resetAfter -= 1; variable.resetAfter -= 1;
auto val = variable.val; auto val = variable.val;
if (variable.resetAfter == 0) { if (variable.resetAfter == 0)
variable.val = false; {
} variable.val = false;
}
return val; return val;
} }
} }
void setAllowSendReadPacket(bool val, int resetAfter = 1); void setAllowSendReadPacket(bool val, int resetAfter = 1);
bool getAllowSendPacket(); bool getAllowSendPacket();
} }

View file

@ -27,56 +27,59 @@ auto storage = make_storage("ayugram.db",
); );
namespace AyuDatabase { namespace AyuDatabase
void addEditedMessage( {
long userId, void addEditedMessage(
long dialogId, long userId,
long messageId, long dialogId,
const QString &text, long messageId,
bool isDocument, const QString& text,
QString path, bool isDocument,
long date) { QString path,
long date)
{
EditedMessage entity;
entity.userId = userId;
entity.dialogId = dialogId;
entity.messageId = messageId;
entity.text = text.toStdString();
entity.isDocument = isDocument;
entity.path = path.toStdString();
entity.date = date;
EditedMessage entity; storage.sync_schema();
entity.userId = userId;
entity.dialogId = dialogId;
entity.messageId = messageId;
entity.text = text.toStdString();
entity.isDocument = isDocument;
entity.path = path.toStdString();
entity.date = date;
storage.sync_schema(); storage.begin_transaction();
storage.insert(entity);
storage.commit();
}
storage.begin_transaction(); std::vector<EditedMessage> getEditedMessages(
storage.insert(entity); long userId,
storage.commit(); long dialogId,
} long messageId
)
{
return storage.get_all<EditedMessage>(
where(
c(&EditedMessage::userId) == userId and
c(&EditedMessage::dialogId) == dialogId and
c(&EditedMessage::messageId) == messageId)
);
}
std::vector<EditedMessage> getEditedMessages( std::vector<EditedMessage> getEditedMessages(HistoryItem* item)
long userId, {
long dialogId, auto userId = item->displayFrom()->id.value;
long messageId auto dialogId = item->history()->peer->id.value;
) { auto msgId = item->id.bare;
// auto some = &item->history()->session().account();
return storage.get_all<EditedMessage>( return getEditedMessages(static_cast<long>(userId), static_cast<long>(dialogId), static_cast<long>(msgId));
where( }
c(&EditedMessage::userId) == userId and
c(&EditedMessage::dialogId) == dialogId and
c(&EditedMessage::messageId) == messageId)
);
}
std::vector<EditedMessage> getEditedMessages(HistoryItem *item) { bool editedMessagesTableExists()
auto userId = item->displayFrom()->id.value; {
auto dialogId = item->history()->peer->id.value; return storage.table_exists("editedmessage");
auto msgId = item->id.bare; }
// auto some = &item->history()->session().account();
return getEditedMessages((long) userId, (long) dialogId, (long) msgId);
}
bool editedMessagesTableExists() {
return storage.table_exists("editedmessage");
}
} }

View file

@ -8,26 +8,27 @@
#pragma once #pragma once
#include "entities.h" #include "entities.h"
#include "history/history_item.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h"
namespace AyuDatabase { namespace AyuDatabase
void addEditedMessage( {
long userId, void addEditedMessage(
long dialogId, long userId,
long messageId, long dialogId,
const QString &text, long messageId,
bool isDocument, const QString& text,
QString path, bool isDocument,
long date); QString path,
long date);
std::vector<EditedMessage> getEditedMessages( std::vector<EditedMessage> getEditedMessages(
long userId, long userId,
long dialogId, long dialogId,
long messageId long messageId
); );
std::vector<EditedMessage> getEditedMessages(HistoryItem *item); std::vector<EditedMessage> getEditedMessages(HistoryItem* item);
bool editedMessagesTableExists(); bool editedMessagesTableExists();
} }

View file

@ -11,14 +11,15 @@
#include <string> #include <string>
// https://github.com/AyuGram/AyuGram4A/blob/main/TMessagesProj/src/main/java/com/radolyn/ayugram/database/entities/EditedMessage.java // https://github.com/AyuGram/AyuGram4A/blob/main/TMessagesProj/src/main/java/com/radolyn/ayugram/database/entities/EditedMessage.java
class EditedMessage { class EditedMessage
{
public: public:
long userId; long userId;
long dialogId; long dialogId;
long messageId; long messageId;
std::string text; std::string text;
bool isDocument; bool isDocument;
std::string path; std::string path;
long date; long date;
}; };

View file

@ -10,10 +10,12 @@
#include <QString> #include <QString>
#include "json.hpp" #include "json.hpp"
inline void to_json(nlohmann::json &j, const QString &q) { inline void to_json(nlohmann::json& j, const QString& q)
j = nlohmann::json(q.toStdString()); {
j = nlohmann::json(q.toStdString());
} }
inline void from_json(const nlohmann::json &j, QString &q) { inline void from_json(const nlohmann::json& j, QString& q)
q = QString::fromStdString(j.get<std::string>()); {
} q = QString::fromStdString(j.get<std::string>());
}

View file

@ -7,110 +7,132 @@
#include "ayu_sync_controller.h" #include "ayu_sync_controller.h"
#include "ayu/libs/process.hpp" #include "ayu/libs/process.hpp"
#include "ayu/sync/utils/process_utils.hpp"
#include "ayu/sync/models.h" #include "ayu/sync/models.h"
#include "ayu/sync/utils/process_utils.hpp"
#include "ayu/sync/utils/telegram_helpers.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/history.h" #include "history/history.h"
#include "ayu/sync/utils/telegram_helpers.h"
#include <QString> #include <QString>
#include <thread> #include <thread>
namespace AyuSync { namespace AyuSync
std::optional<ayu_sync_controller> controller = std::nullopt; {
std::optional<ayu_sync_controller> controller = std::nullopt;
bool isAgentDownloaded() { bool isAgentDownloaded()
return std::filesystem::exists(AgentPath); {
} return std::filesystem::exists(AgentPath);
}
bool isAgentRunning() { bool isAgentRunning()
return is_process_running(AgentFilename); {
} return is_process_running(AgentFilename);
}
void initialize() { void initialize()
if (controller.has_value()) { {
return; if (controller.has_value())
} {
return;
}
controller = ayu_sync_controller(); controller = ayu_sync_controller();
} }
ayu_sync_controller &getControllerInstance() { ayu_sync_controller& getControllerInstance()
initialize(); {
return controller.value(); initialize();
} return controller.value();
}
void ayu_sync_controller::initializeAgent() { void ayu_sync_controller::initializeAgent()
if (!isAgentDownloaded()) { {
return; if (!isAgentDownloaded())
} {
return;
}
if (!isAgentRunning()) { if (!isAgentRunning())
auto configPath = std::filesystem::absolute("./tdata/sync_preferences.json"); {
auto process = nes::process{AgentPath, {configPath.string(), ""}, nes::process_options::none}; auto configPath = std::filesystem::absolute("./tdata/sync_preferences.json");
process.detach(); auto process = nes::process{AgentPath, {configPath.string(), ""}, nes::process_options::none};
} process.detach();
}
std::thread receiverThread(&ayu_sync_controller::receiver, this); std::thread receiverThread(&ayu_sync_controller::receiver, this);
receiverThread.detach(); receiverThread.detach();
} }
void ayu_sync_controller::receiver() { void ayu_sync_controller::receiver()
pipe = std::make_unique<ayu_pipe_wrapper>(); {
pipe = std::make_unique<ayu_pipe_wrapper>();
while (true) { while (true)
auto p = pipe->receive(); {
if (p == std::nullopt) { auto p = pipe->receive();
continue; if (p == std::nullopt)
} {
continue;
}
std::string s = p->dump(); std::string s = p->dump();
LOG(("[AyuSync] Received message: %1").arg(QString::fromStdString(s))); LOG(("[AyuSync] Received message: %1").arg(QString::fromStdString(s)));
invokeHandler(p.value()); invokeHandler(p.value());
} }
} }
void ayu_sync_controller::invokeHandler(json p) { void ayu_sync_controller::invokeHandler(json p)
LOG(("Invoking handler on %1").arg(p.dump().c_str())); {
LOG(("Invoking handler on %1").arg(p.dump().c_str()));
auto userId = p["userId"].get<long>(); auto userId = p["userId"].get<long>();
auto type = p["type"].get<std::string>(); auto type = p["type"].get<std::string>();
LOG(("userId: %1, type: %2").arg(userId).arg(type.c_str())); LOG(("userId: %1, type: %2").arg(userId).arg(type.c_str()));
// todo: check if account exists // todo: check if account exists
if (type == "sync_force") { if (type == "sync_force")
auto ev = p.template get<SyncForce>(); {
onSyncForce(ev); auto ev = p.template get<SyncForce>();
} else if (type == "sync_batch") { onSyncForce(ev);
onSyncBatch(p); }
} else if (type == "sync_read") { else if (type == "sync_batch")
auto ev = p.template get<SyncRead>(); {
onSyncRead(ev); onSyncBatch(p);
} else { }
LOG(("Unknown sync type: %1").arg(type.c_str())); else if (type == "sync_read")
} {
} auto ev = p.template get<SyncRead>();
onSyncRead(ev);
}
else
{
LOG(("Unknown sync type: %1").arg(type.c_str()));
}
}
void ayu_sync_controller::onSyncForce(SyncForce ev) { void ayu_sync_controller::onSyncForce(SyncForce ev)
{
}
} void ayu_sync_controller::onSyncBatch(json ev)
{
}
void ayu_sync_controller::onSyncBatch(json ev) { void ayu_sync_controller::onSyncRead(SyncRead ev)
{
auto session = getSession(ev.userId);
} auto peer = PeerId(abs(ev.args.dialogId));
void ayu_sync_controller::onSyncRead(SyncRead ev) { auto history = session->data().history(peer);
auto session = getSession(ev.userId); if (history)
{
auto peer = PeerId(abs(ev.args.dialogId)); history->inboxRead(ev.args.untilId, ev.args.unread);
}
auto history = session->data().history(peer); }
if (history) { }
history->inboxRead(ev.args.untilId, ev.args.unread);
}
}
}

View file

@ -7,39 +7,42 @@
#pragma once #pragma once
#include "ayu/libs/json.hpp"
#include "models.h" #include "models.h"
#include "ayu/libs/json.hpp"
#include "utils/ayu_pipe_wrapper.h" #include "utils/ayu_pipe_wrapper.h"
using json = nlohmann::json; using json = nlohmann::json;
const std::string AgentFilename = const std::string AgentFilename =
#ifdef _WIN32 #ifdef _WIN32
"AyuSync.Agent.exe"; "AyuSync.Agent.exe";
#else #else
"AyuSync.Agent"; "AyuSync.Agent";
#endif #endif
const std::string AgentPath = "./AyuSync/" + AgentFilename; const std::string AgentPath = "./AyuSync/" + AgentFilename;
namespace AyuSync { namespace AyuSync
class ayu_sync_controller { {
public: class ayu_sync_controller
void initializeAgent(); {
public:
void initializeAgent();
void onSyncForce(SyncForce ev); void onSyncForce(SyncForce ev);
void onSyncBatch(json ev); void onSyncBatch(json ev);
void onSyncRead(SyncRead ev); void onSyncRead(SyncRead ev);
void invokeHandler(json p); void invokeHandler(json p);
private:
void receiver();
std::unique_ptr<ayu_pipe_wrapper> pipe; private:
}; void receiver();
ayu_sync_controller &getControllerInstance(); std::unique_ptr<ayu_pipe_wrapper> pipe;
};
bool isAgentDownloaded(); ayu_sync_controller& getControllerInstance();
bool isAgentRunning();
bool isAgentDownloaded();
bool isAgentRunning();
} }

View file

@ -1,66 +1,77 @@
#pragma once #pragma once
#include "ayu/libs/json.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
class SyncEvent { class SyncEvent
{
public: public:
std::string type = "sync_unspecified"; std::string type = "sync_unspecified";
long userId = 0; long userId = 0;
}; };
class SyncBatch : public SyncEvent { class SyncBatch : public SyncEvent
{
public: public:
std::string type = "sync_batch"; std::string type = "sync_batch";
long userId; long userId;
class SyncBatchArgs { class SyncBatchArgs
public: {
std::vector<SyncEvent> events; public:
}; std::vector<SyncEvent> events;
};
SyncBatchArgs args; SyncBatchArgs args;
}; };
class SyncRead : public SyncEvent { class SyncRead : public SyncEvent
{
public: public:
std::string type = "sync_read"; std::string type = "sync_read";
long userId; long userId;
class SyncReadArgs { class SyncReadArgs
public: {
long dialogId; public:
int untilId; long dialogId;
int unread; int untilId;
}; int unread;
};
SyncReadArgs args; SyncReadArgs args;
}; };
class SyncForce : public SyncEvent { class SyncForce : public SyncEvent
{
public: public:
std::string type = "sync_force"; std::string type = "sync_force";
long userId; long userId;
class SyncForceArgs { class SyncForceArgs
public: {
int fromDate; public:
}; int fromDate;
};
SyncForceArgs args; SyncForceArgs args;
}; };
class SyncForceFinish : public SyncEvent { class SyncForceFinish : public SyncEvent
{
public: public:
std::string type = "sync_force_finish"; std::string type = "sync_force_finish";
long userId; long userId;
class SyncForceFinishArgs { class SyncForceFinishArgs
public: {
short dummy; // required to be JSON serializable public:
}; short dummy; // required to be JSON serializable
};
SyncForceFinishArgs args; SyncForceFinishArgs args;
}; };
@ -73,4 +84,3 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce::SyncForceArgs, fromDate)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce, type, userId, args) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce, type, userId, args)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish::SyncForceFinishArgs, dummy) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish::SyncForceFinishArgs, dummy)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish, type, userId, args) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish, type, userId, args)

View file

@ -5,47 +5,52 @@
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include <sstream>
#include "ayu_pipe_wrapper.h" #include "ayu_pipe_wrapper.h"
#include <sstream>
#include "ayu/libs/bit_converter.hpp" #include "ayu/libs/bit_converter.hpp"
template<class T> template <class T>
void ayu_pipe_wrapper::send(T obj) { void ayu_pipe_wrapper::send(T obj)
// auto s = json(obj).dump(); {
// auto length = s.length(); // auto s = json(obj).dump();
// char lengthBuff[4]; // auto length = s.length();
// bit_converter::i32_to_bytes(length, false, lengthBuff); // char lengthBuff[4];
// // bit_converter::i32_to_bytes(length, false, lengthBuff);
// os.write(lengthBuff, 4); //
// os.write(s.c_str(), length); // os.write(lengthBuff, 4);
// os.flush(); // os.write(s.c_str(), length);
throw std::logic_error("not implemented"); // os.flush();
throw std::logic_error("not implemented");
} }
std::optional<json> ayu_pipe_wrapper::receive() { std::optional<json> ayu_pipe_wrapper::receive()
if (!is.is_open()) { {
return std::nullopt; if (!is.is_open())
} {
return std::nullopt;
}
char lengthBuff[4]; char lengthBuff[4];
is.read(lengthBuff, 4); is.read(lengthBuff, 4);
auto length = bit_converter::bytes_to_i32(lengthBuff, false); auto length = bit_converter::bytes_to_i32(lengthBuff, false);
if (length <= 0) { if (length <= 0)
return std::nullopt; {
} return std::nullopt;
}
auto sb = std::stringbuf(); auto sb = std::stringbuf();
char buff[4096]; char buff[4096];
while (length > 0) { while (length > 0)
auto readSize = std::min(length, (int) sizeof(buff)); {
is.read(buff, readSize); auto readSize = std::min(length, static_cast<int>(sizeof(buff)));
sb.sputn(buff, readSize); is.read(buff, readSize);
length -= readSize; sb.sputn(buff, readSize);
} length -= readSize;
}
auto p = json::parse(sb.str()); auto p = json::parse(sb.str());
return p; return p;
} }

View file

@ -13,13 +13,14 @@
using json = nlohmann::json; using json = nlohmann::json;
class ayu_pipe_wrapper { class ayu_pipe_wrapper
{
public: public:
template<class T> template <class T>
void send(T obj); void send(T obj);
std::optional<json> receive(); std::optional<json> receive();
private: private:
nes::pipe_istream is{"AyuSync"}; nes::pipe_istream is{"AyuSync"};
}; };

View file

@ -1,14 +1,14 @@
#include <algorithm>
#include <codecvt>
#include <iostream> #include <iostream>
#include <locale>
#include <string> #include <string>
#include <vector> #include <vector>
#include <algorithm>
#include <locale>
#include <codecvt>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h>
#include <tlhelp32.h> #include <tlhelp32.h>
#include <windows.h>
#else #else
#include <dirent.h> #include <dirent.h>
@ -17,34 +17,40 @@
// A function to check if a process is running by its name // A function to check if a process is running by its name
// Bing AI generated // Bing AI generated
bool is_process_running(const std::string &name) { bool is_process_running(const std::string& name)
{
#ifdef _WIN32 #ifdef _WIN32
// Create a snapshot of all processes // Create a snapshot of all processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) { if (snapshot == INVALID_HANDLE_VALUE)
std::cerr << "Failed to create snapshot\n"; {
return false; std::cerr << "Failed to create snapshot\n";
} return false;
// Iterate over the processes and compare the names }
PROCESSENTRY32 entry; // Iterate over the processes and compare the names
entry.dwSize = sizeof(entry); PROCESSENTRY32 entry;
if (!Process32First(snapshot, &entry)) { entry.dwSize = sizeof(entry);
std::cerr << "Failed to get first process\n"; if (!Process32First(snapshot, &entry))
CloseHandle(snapshot); {
return false; std::cerr << "Failed to get first process\n";
} CloseHandle(snapshot);
do { return false;
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; }
std::string entry_name = converter.to_bytes(entry.szExeFile); do
if (name == entry_name) { {
// Found a match std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
CloseHandle(snapshot); std::string entry_name = converter.to_bytes(entry.szExeFile);
return true; if (name == entry_name)
} {
} while (Process32Next(snapshot, &entry)); // Found a match
// No match found CloseHandle(snapshot);
CloseHandle(snapshot); return true;
return false; }
}
while (Process32Next(snapshot, &entry));
// No match found
CloseHandle(snapshot);
return false;
#else #else
// Open the /proc directory // Open the /proc directory
DIR* dir = opendir("/proc"); DIR* dir = opendir("/proc");
@ -83,4 +89,4 @@ bool is_process_running(const std::string &name) {
closedir(dir); closedir(dir);
return false; return false;
#endif #endif
} }

View file

@ -8,19 +8,24 @@
#include "telegram_helpers.h" #include "telegram_helpers.h"
#include "data/data_peer_id.h" #include "data/data_peer_id.h"
Main::Session* getSession(long userId) { Main::Session* getSession(long userId)
for (auto &[index, account] : Core::App().domain().accounts()) { {
if (const auto session = account->maybeSession()) { for (auto& [index, account] : Core::App().domain().accounts())
if (session->userId().bare == userId) { {
return session; if (const auto session = account->maybeSession())
} {
} if (session->userId().bare == userId)
} {
return session;
}
}
}
return nullptr; return nullptr;
} }
PeerId dialogIdToPeerId(long dialogId) { PeerId dialogIdToPeerId(long dialogId)
auto peerId = PeerId(); {
return peerId; auto peerId = PeerId();
} return peerId;
}

View file

@ -9,7 +9,7 @@
#include "core/application.h" #include "core/application.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_session.h"
#include "main/main_domain.h" #include "main/main_domain.h"
#include "main/main_session.h"
Main::Session* getSession(long userId); Main::Session* getSession(long userId);

View file

@ -6,57 +6,63 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "confirmation_box.h" #include "confirmation_box.h"
#include "ayu/ayu_settings.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "window/window_peer_menu.h"
#include "styles/style_layers.h"
#include "lang_auto.h" #include "lang_auto.h"
#include "ayu/ayu_settings.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "styles/style_layers.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
namespace AyuUi { namespace AyuUi
ConfirmationBox::ConfirmationBox( {
QWidget *, ConfirmationBox::ConfirmationBox(
not_null<Window::SessionController *> controller) : _controller(controller) { QWidget*,
// not_null<Window::SessionController*> controller) : _controller(controller)
} {
//
}
void ConfirmationBox::prepare() { void ConfirmationBox::prepare()
// setTitle(rpl::single(QString("Confirmation for SRead"))); {
auto details = TextWithEntities(); // setTitle(rpl::single(QString("Confirmation for SRead")));
details.text = QString("Do you want to read all messages?"); auto details = TextWithEntities();
details.text = QString("Do you want to read all messages?");
_text.create(this, rpl::single(std::move(details)), st::boxLabel); _text.create(this, rpl::single(std::move(details)), st::boxLabel);
auto fullHeight = st::boxPadding.top() auto fullHeight = st::boxPadding.top()
+ _text->height() + _text->height()
+ st::boxPadding.bottom(); + st::boxPadding.bottom();
setDimensions(st::boxWidth, fullHeight); setDimensions(st::boxWidth, fullHeight);
addButton(rpl::single(QString("Read")), [=, this] { addButton(rpl::single(QString("Read")), [=, this]
ReadAllPeers(); {
closeBox(); ReadAllPeers();
}); closeBox();
addButton(tr::lng_cancel(), [=, this] { closeBox(); }); });
} addButton(tr::lng_cancel(), [=, this] { closeBox(); });
}
void ConfirmationBox::resizeEvent(QResizeEvent *e) { void ConfirmationBox::resizeEvent(QResizeEvent* e)
BoxContent::resizeEvent(e); {
BoxContent::resizeEvent(e);
const auto &padding = st::boxPadding; const auto& padding = st::boxPadding;
_text->moveToLeft(padding.left(), padding.top()); _text->moveToLeft(padding.left(), padding.top());
} }
void ConfirmationBox::ReadAllPeers() { void ConfirmationBox::ReadAllPeers()
auto settings = &AyuSettings::getInstance(); {
auto prev = settings->sendReadPackets; auto settings = &AyuSettings::getInstance();
settings->set_sendReadPackets(true); auto prev = settings->sendReadPackets;
settings->set_sendReadPackets(true);
auto chats = _controller->session().data().chatsList(); auto chats = _controller->session().data().chatsList();
Window::MarkAsReadChatListHack(chats); Window::MarkAsReadChatListHack(chats);
settings->set_sendReadPackets(prev); settings->set_sendReadPackets(prev);
} }
} }

View file

@ -8,20 +8,22 @@
#include "ui/layers/box_content.h" #include "ui/layers/box_content.h"
#include "window/window_main_menu.h" #include "window/window_main_menu.h"
namespace AyuUi { namespace AyuUi
class ConfirmationBox : public Ui::BoxContent { {
public: class ConfirmationBox : public Ui::BoxContent
ConfirmationBox(QWidget *, not_null<Window::SessionController *> controller); {
public:
ConfirmationBox(QWidget*, not_null<Window::SessionController*> controller);
protected: protected:
void prepare() override; void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent* e) override;
private: private:
void ReadAllPeers(); void ReadAllPeers();
not_null<Window::SessionController *> _controller; not_null<Window::SessionController*> _controller;
object_ptr<Ui::FlatLabel> _text = {nullptr}; object_ptr<Ui::FlatLabel> _text = {nullptr};
}; };
} }

View file

@ -7,83 +7,92 @@
#include "edit_deleted_mark.h" #include "edit_deleted_mark.h"
#include "lang/lang_keys.h"
#include "base/random.h" #include "base/random.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h" #include "boxes/premium_limits_box.h"
#include "data/data_cloud_file.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "styles/style_widgets.h"
#include "ui/ui_utility.h"
#include "ui/unread_badge.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/fields/special_fields.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/unread_badge.h" #include "ui/widgets/fields/special_fields.h"
#include "ui/ui_utility.h"
#include "data/data_cloud_file.h"
#include "main/main_session.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_widgets.h"
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
EditDeletedMarkBox::EditDeletedMarkBox(QWidget *) : EditDeletedMarkBox::EditDeletedMarkBox(QWidget*) :
_text( _text(
this, this,
st::defaultInputField, st::defaultInputField,
rpl::single(QString("Deleted Mark")), rpl::single(QString("Deleted Mark")),
AyuSettings::getInstance().deletedMark) { AyuSettings::getInstance().deletedMark)
{
} }
void EditDeletedMarkBox::prepare() { void EditDeletedMarkBox::prepare()
const auto defaultDeletedMark = "🧹"; {
auto newHeight = st::contactPadding.top() + _text->height(); const auto defaultDeletedMark = "🧹";
auto newHeight = st::contactPadding.top() + _text->height();
setTitle(rpl::single(QString("Edit Deleted Mark"))); setTitle(rpl::single(QString("Edit Deleted Mark")));
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom(); newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
setDimensions(st::boxWidth, newHeight); setDimensions(st::boxWidth, newHeight);
addLeftButton(rpl::single(QString("Reset")), [=] { _text->setText(defaultDeletedMark); }); addLeftButton(rpl::single(QString("Reset")), [=] { _text->setText(defaultDeletedMark); });
addButton(tr::lng_settings_save(), [=] { save(); }); addButton(tr::lng_settings_save(), [=] { save(); });
addButton(tr::lng_cancel(), [=] { closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); });
connect(_text, &Ui::InputField::submitted, [=] { submit(); }); connect(_text, &Ui::InputField::submitted, [=] { submit(); });
} }
void EditDeletedMarkBox::setInnerFocus() { void EditDeletedMarkBox::setInnerFocus()
_text->setFocusFast(); {
_text->setFocusFast();
} }
void EditDeletedMarkBox::submit() { void EditDeletedMarkBox::submit()
if (_text->getLastText().trimmed().isEmpty()) { {
_text->setFocus(); if (_text->getLastText().trimmed().isEmpty())
_text->showError(); {
} else { _text->setFocus();
save(); _text->showError();
} }
else
{
save();
}
} }
void EditDeletedMarkBox::resizeEvent(QResizeEvent *e) { void EditDeletedMarkBox::resizeEvent(QResizeEvent* e)
BoxContent::resizeEvent(e); {
BoxContent::resizeEvent(e);
_text->resize( _text->resize(
width() width()
- st::boxPadding.left() - st::boxPadding.left()
- st::newGroupInfoPadding.left() - st::newGroupInfoPadding.left()
- st::boxPadding.right(), - st::boxPadding.right(),
_text->height()); _text->height());
const auto left = st::boxPadding.left() + st::newGroupInfoPadding.left(); const auto left = st::boxPadding.left() + st::newGroupInfoPadding.left();
_text->moveToLeft(left, st::contactPadding.top()); _text->moveToLeft(left, st::contactPadding.top());
} }
void EditDeletedMarkBox::save() { void EditDeletedMarkBox::save()
const auto settings = &AyuSettings::getInstance(); {
settings->set_deletedMark(_text->getLastText()); const auto settings = &AyuSettings::getInstance();
AyuSettings::save(); settings->set_deletedMark(_text->getLastText());
AyuSettings::save();
closeBox(); closeBox();
} }

View file

@ -7,25 +7,26 @@
#pragma once #pragma once
#include "boxes/abstract_box.h"
#include "base/timer.h" #include "base/timer.h"
#include "boxes/abstract_box.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
class EditDeletedMarkBox : public Ui::BoxContent { class EditDeletedMarkBox : public Ui::BoxContent
{
public: public:
EditDeletedMarkBox(QWidget *); EditDeletedMarkBox(QWidget*);
protected: protected:
void setInnerFocus() override; void setInnerFocus() override;
void prepare() override; void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent* e) override;
private: private:
void submit(); void submit();
void save(); void save();
object_ptr<Ui::InputField> _text; object_ptr<Ui::InputField> _text;
}; };

View file

@ -7,85 +7,93 @@
#include "edit_edited_mark.h" #include "edit_edited_mark.h"
#include "lang/lang_keys.h"
#include "base/random.h" #include "base/random.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h" #include "boxes/premium_limits_box.h"
#include "data/data_cloud_file.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "styles/style_widgets.h"
#include "ui/ui_utility.h"
#include "ui/unread_badge.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/fields/special_fields.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/unread_badge.h" #include "ui/widgets/fields/special_fields.h"
#include "ui/ui_utility.h"
#include "data/data_cloud_file.h"
#include "main/main_session.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_widgets.h"
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
EditEditedMarkBox::EditEditedMarkBox(QWidget *) : EditEditedMarkBox::EditEditedMarkBox(QWidget*) :
_text( _text(
this, this,
st::defaultInputField, st::defaultInputField,
rpl::single(QString("Edited mark")), rpl::single(QString("Edited mark")),
AyuSettings::getInstance().editedMark) { AyuSettings::getInstance().editedMark)
{
} }
void EditEditedMarkBox::prepare() { void EditEditedMarkBox::prepare()
const auto defaultEditedMark = tr::lng_edited(tr::now); {
auto newHeight = st::contactPadding.top() + _text->height(); const auto defaultEditedMark = tr::lng_edited(tr::now);
auto newHeight = st::contactPadding.top() + _text->height();
setTitle(rpl::single(QString("Edit edited Mark"))); setTitle(rpl::single(QString("Edit edited Mark")));
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom(); newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
setDimensions(st::boxWidth, newHeight); setDimensions(st::boxWidth, newHeight);
addLeftButton(rpl::single(QString("Reset")), [=] { _text->setText(defaultEditedMark); }); addLeftButton(rpl::single(QString("Reset")), [=] { _text->setText(defaultEditedMark); });
addButton(tr::lng_settings_save(), [=] { save(); }); addButton(tr::lng_settings_save(), [=] { save(); });
addButton(tr::lng_cancel(), [=] { closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); });
connect(_text, &Ui::InputField::submitted, [=] { submit(); }); connect(_text, &Ui::InputField::submitted, [=] { submit(); });
} }
void EditEditedMarkBox::setInnerFocus() { void EditEditedMarkBox::setInnerFocus()
_text->setFocusFast(); {
_text->setFocusFast();
} }
void EditEditedMarkBox::submit() { void EditEditedMarkBox::submit()
if (_text->getLastText().trimmed().isEmpty()) { {
_text->setFocus(); if (_text->getLastText().trimmed().isEmpty())
_text->showError(); {
} else { _text->setFocus();
save(); _text->showError();
} }
else
{
save();
}
} }
void EditEditedMarkBox::resizeEvent(QResizeEvent *e) { void EditEditedMarkBox::resizeEvent(QResizeEvent* e)
BoxContent::resizeEvent(e); {
BoxContent::resizeEvent(e);
_text->resize( _text->resize(
width() width()
- st::boxPadding.left() - st::boxPadding.left()
- st::newGroupInfoPadding.left() - st::newGroupInfoPadding.left()
- st::boxPadding.right(), - st::boxPadding.right(),
_text->height()); _text->height());
const auto left = st::boxPadding.left() + st::newGroupInfoPadding.left(); const auto left = st::boxPadding.left() + st::newGroupInfoPadding.left();
_text->moveToLeft(left, st::contactPadding.top()); _text->moveToLeft(left, st::contactPadding.top());
} }
void EditEditedMarkBox::save() { void EditEditedMarkBox::save()
const auto settings = &AyuSettings::getInstance(); {
settings->set_editedMark(_text->getLastText()); const auto settings = &AyuSettings::getInstance();
AyuSettings::save(); settings->set_editedMark(_text->getLastText());
AyuSettings::save();
closeBox(); closeBox();
} }

View file

@ -7,25 +7,26 @@
#pragma once #pragma once
#include "boxes/abstract_box.h"
#include "base/timer.h" #include "base/timer.h"
#include "boxes/abstract_box.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
class EditEditedMarkBox : public Ui::BoxContent { class EditEditedMarkBox : public Ui::BoxContent
{
public: public:
EditEditedMarkBox(QWidget *); EditEditedMarkBox(QWidget*);
protected: protected:
void setInnerFocus() override; void setInnerFocus() override;
void prepare() override; void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent* e) override;
private: private:
void submit(); void submit();
void save(); void save();
object_ptr<Ui::InputField> _text; object_ptr<Ui::InputField> _text;
}; };

View file

@ -6,97 +6,119 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "lang/lang_keys.h"
#include "ui/widgets/buttons.h"
#include "styles/style_layers.h"
#include "voice_confirmation_box.h" #include "voice_confirmation_box.h"
#include "lang/lang_keys.h"
#include "styles/style_layers.h"
#include "ui/widgets/buttons.h"
namespace AyuUi { namespace AyuUi
{
void VoiceConfirmBox(not_null<Ui::GenericBox*> box, Ui::ConfirmBoxArgs&& args)
{
const auto weak = MakeWeak(box);
const auto lifetime = box->lifetime().make_state<rpl::lifetime>();
void VoiceConfirmBox(not_null<Ui::GenericBox *> box, Ui::ConfirmBoxArgs &&args) { v::match(args.text, [](v::null_t)
const auto weak = Ui::MakeWeak(box); {
const auto lifetime = box->lifetime().make_state<rpl::lifetime>(); }, [&](auto&&)
{
const auto label = box->addRow(
object_ptr<Ui::FlatLabel>(
box.get(),
v::text::take_marked(std::move(args.text)),
args.labelStyle ? *args.labelStyle : st::boxLabel),
st::boxPadding);
if (args.labelFilter)
{
label->setClickHandlerFilter(std::move(args.labelFilter));
}
});
v::match(args.text, [](v::null_t) { const auto prepareCallback = [&](Ui::ConfirmBoxArgs::Callback& callback)
}, [&](auto &&) { {
const auto label = box->addRow( return [=, confirmed = std::move(callback)]()
object_ptr<Ui::FlatLabel>( {
box.get(), if (const auto callbackPtr = std::get_if<1>(&confirmed))
v::text::take_marked(std::move(args.text)), {
args.labelStyle ? *args.labelStyle : st::boxLabel), if (auto callback = (*callbackPtr))
st::boxPadding); {
if (args.labelFilter) { callback();
label->setClickHandlerFilter(std::move(args.labelFilter)); }
} }
}); else if (const auto callbackPtr = std::get_if<2>(&confirmed))
{
if (auto callback = (*callbackPtr))
{
callback(crl::guard(weak, [=] { weak->closeBox(); }));
}
}
else if (weak)
{
weak->closeBox();
}
};
};
const auto prepareCallback = [&](Ui::ConfirmBoxArgs::Callback &callback) { const auto& defaultButtonStyle = box->getDelegate()->style().button;
return [=, confirmed = std::move(callback)]() {
if (const auto callbackPtr = std::get_if<1>(&confirmed)) {
if (auto callback = (*callbackPtr)) {
callback();
}
} else if (const auto callbackPtr = std::get_if<2>(&confirmed)) {
if (auto callback = (*callbackPtr)) {
callback(crl::guard(weak, [=] { weak->closeBox(); }));
}
} else if (weak) {
weak->closeBox();
}
};
};
const auto &defaultButtonStyle = box->getDelegate()->style().button; const auto confirmButton = box->addButton(
v::text::take_plain(std::move(args.confirmText), tr::lng_box_ok()),
[=, c = prepareCallback(args.confirmed)]()
{
lifetime->destroy();
c();
const auto confirmButton = box->addButton( weak->closeBox();
v::text::take_plain(std::move(args.confirmText), tr::lng_box_ok()), },
[=, c = prepareCallback(args.confirmed)]() { args.confirmStyle ? *args.confirmStyle : defaultButtonStyle);
lifetime->destroy(); box->events(
c(); ) | start_with_next([=](not_null<QEvent*> e)
{
if ((e->type() != QEvent::KeyPress) || !confirmButton)
{
return;
}
const auto k = static_cast<QKeyEvent*>(e.get());
if (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return)
{
confirmButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
}
}, box->lifetime());
weak->closeBox(); if (!args.inform)
}, {
args.confirmStyle ? *args.confirmStyle : defaultButtonStyle); const auto cancelButton = box->addButton(
box->events( v::text::take_plain(std::move(args.cancelText), tr::lng_cancel()),
) | rpl::start_with_next([=](not_null<QEvent *> e) { crl::guard(weak, [=, c = prepareCallback(args.cancelled)]()
if ((e->type() != QEvent::KeyPress) || !confirmButton) { {
return; lifetime->destroy();
} c();
const auto k = static_cast<QKeyEvent *>(e.get()); }),
if (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return) { args.cancelStyle ? *args.cancelStyle : defaultButtonStyle);
confirmButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
}
}, box->lifetime());
if (!args.inform) { box->boxClosing(
const auto cancelButton = box->addButton( ) | start_with_next(crl::guard(cancelButton, [=]
v::text::take_plain(std::move(args.cancelText), tr::lng_cancel()), {
crl::guard(weak, [=, c = prepareCallback(args.cancelled)]() { cancelButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
lifetime->destroy(); }), *lifetime);
c(); }
}),
args.cancelStyle ? *args.cancelStyle : defaultButtonStyle);
box->boxClosing( if (args.strictCancel)
) | rpl::start_with_next(crl::guard(cancelButton, [=] { {
cancelButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton); lifetime->destroy();
}), *lifetime); }
} }
if (args.strictCancel) { object_ptr<Ui::GenericBox> MakeConfirmBox(Ui::ConfirmBoxArgs&& args)
lifetime->destroy(); {
} return Box(VoiceConfirmBox, std::move(args));
} }
object_ptr<Ui::GenericBox> MakeConfirmBox(Ui::ConfirmBoxArgs &&args) {
return Box(VoiceConfirmBox, std::move(args));
}
object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text) {
return MakeConfirmBox({
.text = std::move(text),
.inform = true,
});
}
object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text)
{
return MakeConfirmBox({
.text = std::move(text),
.inform = true,
});
}
} // namespace AyuUi } // namespace AyuUi

View file

@ -6,16 +6,16 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "ui/boxes/confirm_box.h"
#include "ui/layers/generic_box.h" #include "ui/layers/generic_box.h"
#include "ui/text/text_variant.h" #include "ui/text/text_variant.h"
#include "ui/boxes/confirm_box.h"
namespace AyuUi { namespace AyuUi
void VoiceConfirmBox(not_null<Ui::GenericBox *> box, Ui::ConfirmBoxArgs &&args); {
void VoiceConfirmBox(not_null<Ui::GenericBox*> box, Ui::ConfirmBoxArgs&& args);
[[nodiscard]] object_ptr<Ui::GenericBox> MakeConfirmBox( [[nodiscard]] object_ptr<Ui::GenericBox> MakeConfirmBox(
Ui::ConfirmBoxArgs &&args); Ui::ConfirmBoxArgs&& args);
[[nodiscard]] object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text);
[[nodiscard]] object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text);
} // namespace Ui } // namespace Ui

View file

@ -6,47 +6,56 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "context_menu.h" #include "context_menu.h"
#include "history/history_inner_widget.h"
#include "lang_auto.h" #include "lang_auto.h"
#include "ui/widgets/popup_menu.h"
#include "base/unixtime.h"
#include "styles/style_chat.h"
#include "settings/settings_common.h"
#include "message_history_box.h" #include "message_history_box.h"
#include "ayu/database/ayu_database.h"
#include "ayu/ayu_state.h" #include "ayu/ayu_state.h"
#include "ayu/database/ayu_database.h"
#include "base/unixtime.h"
#include "history/history_inner_widget.h"
#include "settings/settings_common.h"
#include "styles/style_chat.h"
#include "ui/widgets/popup_menu.h"
namespace AyuUi { namespace AyuUi
AyuPopupMenu::AyuPopupMenu(HistoryInner *parent) { {
_ayuSubMenu = std::make_unique<Ui::PopupMenu>(parent, st::popupMenuWithIcons); AyuPopupMenu::AyuPopupMenu(HistoryInner* parent)
} {
_ayuSubMenu = std::make_unique<Ui::PopupMenu>(parent, st::popupMenuWithIcons);
}
void AyuPopupMenu::addHistoryAction(HistoryItem *item) { void AyuPopupMenu::addHistoryAction(HistoryItem* item)
if (AyuDatabase::editedMessagesTableExists() && !((AyuDatabase::getEditedMessages(item)).empty())) { {
_ayuSubMenu->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=] { if (AyuDatabase::editedMessagesTableExists() && !((AyuDatabase::getEditedMessages(item)).empty()))
auto box = Box<MessageHistoryBox>(item); {
Ui::show(std::move(box)); _ayuSubMenu->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=]
}, &st::menuIconInfo); {
} auto box = Box<MessageHistoryBox>(item);
} show(std::move(box));
}, &st::menuIconInfo);
}
}
void AyuPopupMenu::addHideMessageAction(HistoryItem *item) const { void AyuPopupMenu::addHideMessageAction(HistoryItem* item) const
const auto settings = &AyuSettings::getInstance(); {
const auto history = item->history(); const auto settings = &AyuSettings::getInstance();
_ayuSubMenu->addAction(QString("Hide"), [=]() { const auto history = item->history();
const auto initKeepDeleted = settings->keepDeletedMessages; _ayuSubMenu->addAction(QString("Hide"), [=]()
{
const auto initKeepDeleted = settings->keepDeletedMessages;
settings->set_keepDeletedMessages(false); settings->set_keepDeletedMessages(false);
history->destroyMessage(item); history->destroyMessage(item);
settings->set_keepDeletedMessages(initKeepDeleted); settings->set_keepDeletedMessages(initKeepDeleted);
}, &st::menuIconClear); }, &st::menuIconClear);
} }
void AyuPopupMenu::addReadUntilAction(HistoryItem *item) const { void AyuPopupMenu::addReadUntilAction(HistoryItem* item) const
const auto history = item->history(); {
_ayuSubMenu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]() { const auto history = item->history();
AyuState::setAllowSendReadPacket(true); _ayuSubMenu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]()
history->session().data().histories().readInboxOnNewMessage(item); {
}, &st::menuIconShowInChat); AyuState::setAllowSendReadPacket(true);
} history->session().data().histories().readInboxOnNewMessage(item);
} // namespace AyuUi }, &st::menuIconShowInChat);
}
} // namespace AyuUi

View file

@ -7,93 +7,93 @@
#pragma once #pragma once
#include "history/history_inner_widget.h" #include "mainwindow.h"
#include "ui/widgets/popup_menu.h" #include "base/call_delayed.h"
#include "ui/image/image.h" #include "base/unixtime.h"
#include "ui/effects/path_shift_gradient.h"
#include "ui/effects/message_sending_animation_controller.h"
#include "ui/effects/reaction_fly_animation.h"
#include "ui/text/text_options.h"
#include "ui/text/text_entity.h"
#include "ui/boxes/report_box.h"
#include "ui/layers/generic_box.h"
#include "ui/controls/delete_message_context_action.h"
#include "ui/controls/who_reacted_context_action.h"
#include "ui/painter.h"
#include "ui/ui_utility.h"
#include "ui/cached_round_corners.h"
#include "ui/inactive_press.h"
#include "window/window_adaptive.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "window/window_peer_menu.h"
#include "window/window_controller.h"
#include "window/notifications_manager.h"
#include "boxes/about_sponsored_box.h"
#include "boxes/delete_messages_box.h"
#include "boxes/report_messages_box.h"
#include "boxes/sticker_set_box.h"
#include "boxes/premium_preview_box.h"
#include "boxes/translate_box.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/emoji_interactions.h"
#include "history/history_widget.h"
#include "history/view/history_view_translate_tracker.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/qt/qt_common_adapters.h" #include "base/qt/qt_common_adapters.h"
#include "base/qt/qt_key_modifiers.h" #include "base/qt/qt_key_modifiers.h"
#include "base/unixtime.h" #include "boxes/about_sponsored_box.h"
#include "base/call_delayed.h" #include "boxes/delete_messages_box.h"
#include "mainwindow.h" #include "boxes/premium_preview_box.h"
#include "boxes/report_messages_box.h"
#include "boxes/sticker_set_box.h"
#include "boxes/translate_box.h"
#include "chat_helpers/emoji_interactions.h"
#include "chat_helpers/message_field.h"
#include "core/application.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_document.h"
#include "data/data_file_click_handler.h"
#include "data/data_file_origin.h"
#include "data/data_forum_topic.h"
#include "data/data_histories.h"
#include "data/data_media_types.h"
#include "data/data_message_reactions.h"
#include "data/data_peer_values.h"
#include "data/data_photo.h"
#include "data/data_photo_media.h"
#include "data/data_poll.h"
#include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "data/data_user.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/ui/dialogs_video_userpic.h"
#include "history/history_inner_widget.h"
#include "history/history_widget.h"
#include "history/view/history_view_translate_tracker.h"
#include "lang/lang_keys.h"
#include "layout/layout_selection.h" #include "layout/layout_selection.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_session_settings.h" #include "main/main_session_settings.h"
#include "main/session/send_as_peers.h" #include "main/session/send_as_peers.h"
#include "menu/menu_item_download_files.h" #include "menu/menu_item_download_files.h"
#include "core/application.h"
#include "lang/lang_keys.h"
#include "data/data_session.h"
#include "data/data_media_types.h"
#include "data/data_message_reactions.h"
#include "data/data_document.h"
#include "data/data_channel.h"
#include "data/data_forum_topic.h"
#include "data/data_poll.h"
#include "data/data_photo.h"
#include "data/data_photo_media.h"
#include "data/data_peer_values.h"
#include "data/data_chat.h"
#include "data/data_user.h"
#include "data/data_file_click_handler.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "data/data_changes.h"
#include "data/stickers/data_stickers.h"
#include "data/data_sponsored_messages.h"
#include "dialogs/ui/dialogs_video_userpic.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_window.h" // st::windowMinWidth
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "styles/style_window.h" // st::windowMinWidth
#include "ui/cached_round_corners.h"
#include "ui/inactive_press.h"
#include "ui/painter.h"
#include "ui/ui_utility.h"
#include "ui/boxes/report_box.h"
#include "ui/controls/delete_message_context_action.h"
#include "ui/controls/who_reacted_context_action.h"
#include "ui/effects/message_sending_animation_controller.h"
#include "ui/effects/path_shift_gradient.h"
#include "ui/effects/reaction_fly_animation.h"
#include "ui/image/image.h"
#include "ui/layers/generic_box.h"
#include "ui/text/text_entity.h"
#include "ui/text/text_options.h"
#include "ui/widgets/popup_menu.h"
#include "window/notifications_manager.h"
#include "window/window_adaptive.h"
#include "window/window_controller.h"
#include "window/window_controller.h"
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
#include "history/view/history_view_context_menu.h" #include "history/view/history_view_context_menu.h"
#include <styles/style_info.h>
#include <ayu/ayu_settings.h> #include <ayu/ayu_settings.h>
#include <styles/style_info.h>
namespace AyuUi { namespace AyuUi
class AyuPopupMenu { {
class AyuPopupMenu
{
public:
AyuPopupMenu(HistoryInner* parent);
public: void addHistoryAction(HistoryItem* item);
AyuPopupMenu(HistoryInner *parent);
void addHistoryAction(HistoryItem *item); void addHideMessageAction(HistoryItem* item) const;
void addHideMessageAction(HistoryItem *item) const; void addReadUntilAction(HistoryItem* item) const;
void addReadUntilAction(HistoryItem *item) const; std::unique_ptr<Ui::PopupMenu> _ayuSubMenu;
};
std::unique_ptr<Ui::PopupMenu> _ayuSubMenu; }
};
}

View file

@ -5,65 +5,74 @@
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include <styles/style_layers.h>
#include <styles/style_boxes.h>
#include <ui/effects/scroll_content_shadow.h>
#include <styles/style_settings.h>
#include "message_history_box.h" #include "message_history_box.h"
#include "settings/settings_common.h" #include <styles/style_boxes.h>
#include <styles/style_layers.h>
#include <styles/style_settings.h>
#include <ui/effects/scroll_content_shadow.h>
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
#include "ayu/database/ayu_database.h" #include "ayu/database/ayu_database.h"
#include "history/history.h" #include "history/history.h"
#include "settings/settings_common.h"
using namespace Settings; using namespace Settings;
namespace AyuUi { namespace AyuUi
MessageHistoryBox::MessageHistoryBox(QWidget *, HistoryItem *item) {
: _content(this), _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll)) { MessageHistoryBox::MessageHistoryBox(QWidget*, HistoryItem* item)
setupControls(); : _content(this), _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll))
addEditedMessagesToLayout(item); {
} setupControls();
addEditedMessagesToLayout(item);
}
void MessageHistoryBox::setupControls() { void MessageHistoryBox::setupControls()
_content.create(this); {
_content.create(this);
_content->resizeToWidth(st::boxWideWidth); _content->resizeToWidth(st::boxWideWidth);
_content->moveToLeft(0, 0); _content->moveToLeft(0, 0);
_content->heightValue( _content->heightValue(
) | rpl::start_to_stream(_contentHeight, _content->lifetime()); ) | start_to_stream(_contentHeight, _content->lifetime());
_scroll->setOwnedWidget( _scroll->setOwnedWidget(
object_ptr<Ui::RpWidget>::fromRaw(_content)); object_ptr<RpWidget>::fromRaw(_content));
} }
void MessageHistoryBox::resizeEvent(QResizeEvent *e) { void MessageHistoryBox::resizeEvent(QResizeEvent* e)
_scroll->resize(width(), height() - st::boxPhotoPadding.top() - st::boxPadding.bottom()); {
_scroll->move(0, st::boxPadding.top()); _scroll->resize(width(), height() - st::boxPhotoPadding.top() - st::boxPadding.bottom());
_scroll->move(0, st::boxPadding.top());
if (_content) { if (_content)
_content->resize(_scroll->width(), _content->height()); {
} _content->resize(_scroll->width(), _content->height());
} }
}
void MessageHistoryBox::prepare() { void MessageHistoryBox::prepare()
setTitle(tr::ayu_EditsHistoryTitle()); {
setTitle(tr::ayu_EditsHistoryTitle());
// setDimensionsToContent(st::boxWideWidth, _content); // setDimensionsToContent(st::boxWideWidth, _content);
setDimensions(st::boxWideWidth, 900); setDimensions(st::boxWideWidth, 900);
Ui::SetupShadowsToScrollContent(this, _scroll, _contentHeight.events()); SetupShadowsToScrollContent(this, _scroll, _contentHeight.events());
} }
void MessageHistoryBox::addEditedMessagesToLayout(HistoryItem *item) { void MessageHistoryBox::addEditedMessagesToLayout(HistoryItem* item)
auto messages = AyuDatabase::getEditedMessages(item); {
if (messages.empty()) { auto messages = AyuDatabase::getEditedMessages(item);
return; if (messages.empty())
} {
return;
}
for (const auto &message: messages) { for (const auto& message : messages)
AddSkip(_content); {
AddDividerText(_content, rpl::single(QString::fromStdString(message.text))); AddSkip(_content);
AddSkip(_content); AddDividerText(_content, rpl::single(QString::fromStdString(message.text)));
} AddSkip(_content);
} }
} }
}

View file

@ -6,28 +6,30 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include <ui/layers/box_content.h> #include <ui/layers/box_content.h>
#include "ui/wrap/vertical_layout.h"
#include "ui/widgets/scroll_area.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "ui/widgets/scroll_area.h"
#include "ui/wrap/vertical_layout.h"
namespace AyuUi { namespace AyuUi
class MessageHistoryBox : public Ui::BoxContent { {
public: class MessageHistoryBox : public Ui::BoxContent
MessageHistoryBox(QWidget *, HistoryItem *item); {
public:
MessageHistoryBox(QWidget*, HistoryItem* item);
protected: protected:
void prepare() override; void prepare() override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent* e) override;
private: private:
void setupControls(); void setupControls();
void addEditedMessagesToLayout(HistoryItem *item); void addEditedMessagesToLayout(HistoryItem* item);
object_ptr<Ui::VerticalLayout> _content; object_ptr<Ui::VerticalLayout> _content;
const base::unique_qptr<Ui::ScrollArea> _scroll; const base::unique_qptr<Ui::ScrollArea> _scroll;
rpl::event_stream<int> _contentHeight; rpl::event_stream<int> _contentHeight;
}; };
} }

View file

@ -5,429 +5,475 @@
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ayu/sync/ayu_sync_controller.h"
#include "ayu/ui/boxes/edit_edited_mark.h"
#include "ayu/ui/boxes/edit_deleted_mark.h"
#include "ayu/ayu_settings.h"
#include "settings_ayu.h" #include "settings_ayu.h"
#include "ayu/ayu_settings.h"
#include "ayu/sync/ayu_sync_controller.h"
#include "ayu/ui/boxes/edit_deleted_mark.h"
#include "ayu/ui/boxes/edit_edited_mark.h"
#include "apiwrap.h"
#include "lang_auto.h" #include "lang_auto.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "api/api_blocked_peers.h"
#include "boxes/connection_box.h"
#include "core/application.h"
#include "data/data_session.h"
#include "lang/lang_instance.h"
#include "main/main_session.h"
#include "platform/platform_specific.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "ui/wrap/vertical_layout.h" #include "storage/localstorage.h"
#include "styles/style_settings.h"
#include "ui/boxes/single_choice_box.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "boxes/connection_box.h"
#include "platform/platform_specific.h"
#include "window/window_session_controller.h"
#include "lang/lang_instance.h"
#include "core/application.h"
#include "storage/localstorage.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "styles/style_settings.h"
#include "apiwrap.h"
#include "api/api_blocked_peers.h"
#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/continuous_sliders.h"
#include "ui/boxes/single_choice_box.h" #include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h"
namespace Settings { namespace Settings
{
rpl::producer<QString> Ayu::title()
{
return tr::ayu_AyuPreferences();
}
rpl::producer<QString> Ayu::title() { Ayu::Ayu(
return tr::ayu_AyuPreferences(); QWidget* parent,
} not_null<Window::SessionController*> controller)
: Section(parent)
{
setupContent(controller);
}
Ayu::Ayu( void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout*> container)
QWidget *parent, {
not_null<Window::SessionController *> controller) auto settings = &AyuSettings::getInstance();
: Section(parent) {
setupContent(controller);
}
void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container) { AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader());
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader()); AddButton(
container,
tr::ayu_SendReadPackets(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->sendReadPackets)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->sendReadPackets);
}) | start_with_next([=](bool enabled)
{
settings->set_sendReadPackets(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_SendReadPackets(), tr::ayu_SendOnlinePackets(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->sendReadPackets) rpl::single(settings->sendOnlinePackets)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->sendReadPackets); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->sendOnlinePackets);
settings->set_sendReadPackets(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_sendOnlinePackets(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_SendOnlinePackets(), tr::ayu_SendUploadProgress(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->sendOnlinePackets) rpl::single(settings->sendUploadProgress)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->sendOnlinePackets); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->sendUploadProgress);
settings->set_sendOnlinePackets(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_sendUploadProgress(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_SendUploadProgress(), tr::ayu_SendOfflinePacketAfterOnline(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->sendUploadProgress) rpl::single(settings->sendOfflinePacketAfterOnline)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->sendUploadProgress); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->sendOfflinePacketAfterOnline);
settings->set_sendUploadProgress(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_sendOfflinePacketAfterOnline(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_SendOfflinePacketAfterOnline(), tr::ayu_MarkReadAfterSend(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->sendOfflinePacketAfterOnline) rpl::single(settings->markReadAfterSend)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->sendOfflinePacketAfterOnline); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->markReadAfterSend);
settings->set_sendOfflinePacketAfterOnline(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_markReadAfterSend(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_MarkReadAfterSend(), tr::ayu_UseScheduledMessages(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->markReadAfterSend) rpl::single(settings->useScheduledMessages)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->markReadAfterSend); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->useScheduledMessages);
settings->set_markReadAfterSend(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_useScheduledMessages(enabled);
AyuSettings::save();
}, container->lifetime());
}
AddButton( void Ayu::SetupSpyEssentials(not_null<Ui::VerticalLayout*> container)
container, {
tr::ayu_UseScheduledMessages(), auto settings = &AyuSettings::getInstance();
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->useScheduledMessages)
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->useScheduledMessages);
}) | rpl::start_with_next([=](bool enabled) {
settings->set_useScheduledMessages(enabled);
AyuSettings::save();
}, container->lifetime());
}
void Ayu::SetupSpyEssentials(not_null<Ui::VerticalLayout *> container) { AddSubsectionTitle(container, tr::ayu_SpyEssentialsHeader());
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_SpyEssentialsHeader()); AddButton(
container,
tr::ayu_KeepDeletedMessages(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->keepDeletedMessages)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->keepDeletedMessages);
}) | start_with_next([=](bool enabled)
{
settings->set_keepDeletedMessages(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_KeepDeletedMessages(), tr::ayu_KeepMessagesHistory(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->keepDeletedMessages) rpl::single(settings->keepMessagesHistory)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->keepDeletedMessages); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->keepMessagesHistory);
settings->set_keepDeletedMessages(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_keepMessagesHistory(enabled);
AyuSettings::save();
}, container->lifetime());
}
AddButton( void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout*> container)
container, {
tr::ayu_KeepMessagesHistory(), auto settings = &AyuSettings::getInstance();
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->keepMessagesHistory)
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->keepMessagesHistory);
}) | rpl::start_with_next([=](bool enabled) {
settings->set_keepMessagesHistory(enabled);
AyuSettings::save();
}, container->lifetime());
}
void Ayu::SetupQoLToggles(not_null<Ui::VerticalLayout *> container) { AddSubsectionTitle(container, tr::ayu_QoLTogglesHeader());
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_QoLTogglesHeader()); AddButton(
container,
tr::ayu_EnableAds(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->enableAds)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->enableAds);
}) | start_with_next([=](bool enabled)
{
settings->set_enableAds(enabled);
AyuSettings::save();
}, container->lifetime());
}
AddButton( void Ayu::SetupCustomization(not_null<Ui::VerticalLayout*> container,
container, not_null<Window::SessionController*> controller)
tr::ayu_EnableAds(), {
st::settingsButtonNoIcon auto settings = &AyuSettings::getInstance();
)->toggleOn(
rpl::single(settings->enableAds)
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->enableAds);
}) | rpl::start_with_next([=](bool enabled) {
settings->set_enableAds(enabled);
AyuSettings::save();
}, container->lifetime());
}
void Ayu::SetupCustomization(not_null<Ui::VerticalLayout *> container, AddSubsectionTitle(container, tr::ayu_CustomizationHeader());
not_null<Window::SessionController *> controller) {
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_CustomizationHeader()); auto btn = AddButtonWithLabel(
container,
tr::ayu_DeletedMarkText(),
AyuSettings::get_deletedMarkReactive(),
st::settingsButtonNoIcon
);
btn->addClickHandler([=]()
{
auto box = Box<EditDeletedMarkBox>();
Ui::show(std::move(box));
});
auto btn = AddButtonWithLabel( auto btn2 = AddButtonWithLabel(
container, container,
tr::ayu_DeletedMarkText(), tr::ayu_EditedMarkText(),
AyuSettings::get_deletedMarkReactive(), AyuSettings::get_editedMarkReactive(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
); );
btn->addClickHandler([=]() { btn2->addClickHandler([=]()
auto box = Box<EditDeletedMarkBox>(); {
Ui::show(std::move(box)); auto box = Box<EditEditedMarkBox>();
}); Ui::show(std::move(box));
});
auto btn2 = AddButtonWithLabel( SetupRecentStickersLimitSlider(container);
container,
tr::ayu_EditedMarkText(),
AyuSettings::get_editedMarkReactive(),
st::settingsButtonNoIcon
);
btn2->addClickHandler([=]() {
auto box = Box<EditEditedMarkBox>();
Ui::show(std::move(box));
});
SetupRecentStickersLimitSlider(container); SetupShowPeerId(container, controller);
SetupShowPeerId(container, controller); AddButton(
container,
tr::ayu_ShowGhostToggleInDrawer(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->showGhostToggleInDrawer)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->showGhostToggleInDrawer);
}) | start_with_next([=](bool enabled)
{
settings->set_showGhostToggleInDrawer(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
tr::ayu_ShowGhostToggleInDrawer(), tr::ayu_SettingsShowMessageSeconds(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->showGhostToggleInDrawer) rpl::single(settings->showMessageSeconds)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->showGhostToggleInDrawer); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->showMessageSeconds);
settings->set_showGhostToggleInDrawer(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_showMessageSeconds(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddDividerText(container, tr::ayu_SettingsCustomizationHint());
container, }
tr::ayu_SettingsShowMessageSeconds(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->showMessageSeconds)
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->showMessageSeconds);
}) | rpl::start_with_next([=](bool enabled) {
settings->set_showMessageSeconds(enabled);
AyuSettings::save();
}, container->lifetime());
AddDividerText(container, tr::ayu_SettingsCustomizationHint()); void Ayu::SetupShowPeerId(not_null<Ui::VerticalLayout*> container,
} not_null<Window::SessionController*> controller)
{
auto settings = &AyuSettings::getInstance();
void Ayu::SetupShowPeerId(not_null<Ui::VerticalLayout *> container, const auto options = std::vector{
not_null<Window::SessionController *> controller) { QString(tr::ayu_SettingsShowID_Hide(tr::now)),
auto settings = &AyuSettings::getInstance(); QString("Telegram API"),
QString("Bot API")
};
const auto options = std::vector{ auto currentVal = AyuSettings::get_showPeerIdReactive() | rpl::map([=](int val)
QString(tr::ayu_SettingsShowID_Hide(tr::now)), {
QString("Telegram API"), return options[val];
QString("Bot API") });
};
auto currentVal = AyuSettings::get_showPeerIdReactive() | rpl::map([=](int val) { const auto button = AddButtonWithLabel(
return options[val]; container,
}); tr::ayu_SettingsShowID(),
currentVal,
st::settingsButtonNoIcon);
button->addClickHandler([=]
{
controller->show(Box([=](not_null<Ui::GenericBox*> box)
{
const auto save = [=](int index)
{
settings->set_showPeerId(index);
AyuSettings::save();
};
SingleChoiceBox(box, {
.title = tr::ayu_SettingsShowID(),
.options = options,
.initialSelection = settings->showPeerId,
.callback = save,
});
}));
});
}
const auto button = AddButtonWithLabel( void Ayu::SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout*> container)
container, {
tr::ayu_SettingsShowID(), auto settings = &AyuSettings::getInstance();
currentVal,
st::settingsButtonNoIcon);
button->addClickHandler([=] {
controller->show(Box([=](not_null<Ui::GenericBox *> box) {
const auto save = [=](int index) {
settings->set_showPeerId(index);
AyuSettings::save();
};
SingleChoiceBox(box, {
.title = tr::ayu_SettingsShowID(),
.options = options,
.initialSelection = settings->showPeerId,
.callback = save,
});
}));
});
}
void Ayu::SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container) { container->add(
auto settings = &AyuSettings::getInstance(); CreateButton(
container,
tr::ayu_SettingsRecentStickersCount(),
st::settingsButtonNoIcon)
);
container->add( auto recentStickersLimitSlider = MakeSliderWithLabel(
CreateButton( container,
container, st::settingsScale,
tr::ayu_SettingsRecentStickersCount(), st::settingsScaleLabel,
st::settingsButtonNoIcon) st::normalFont->spacew * 2,
); st::settingsScaleLabel.style.font->width("300%"));
container->add(
std::move(recentStickersLimitSlider.widget),
st::settingsScalePadding);
const auto slider = recentStickersLimitSlider.slider;
const auto label = recentStickersLimitSlider.label;
auto recentStickersLimitSlider = MakeSliderWithLabel( const auto updateLabel = [=](int amount)
container, {
st::settingsScale, label->setText(QString::number(amount));
st::settingsScaleLabel, };
st::normalFont->spacew * 2, updateLabel(settings->recentStickersCount);
st::settingsScaleLabel.style.font->width("300%"));
container->add(
std::move(recentStickersLimitSlider.widget),
st::settingsScalePadding);
const auto slider = recentStickersLimitSlider.slider;
const auto label = recentStickersLimitSlider.label;
const auto updateLabel = [=](int amount) { slider->setPseudoDiscrete(
label->setText(QString::number(amount)); 100 + 1, // thx tg
}; [=](int amount) { return amount; },
updateLabel(settings->recentStickersCount); settings->recentStickersCount,
[=](int amount) { updateLabel(amount); },
[=](int amount)
{
updateLabel(amount);
slider->setPseudoDiscrete( settings->set_recentStickersCount(amount);
100 + 1, // thx tg AyuSettings::save();
[=](int amount) { return amount; }, });
settings->recentStickersCount, }
[=](int amount) { updateLabel(amount); },
[=](int amount) {
updateLabel(amount);
settings->set_recentStickersCount(amount); void Ayu::SetupAyuSync(not_null<Ui::VerticalLayout*> container)
AyuSettings::save(); {
}); AddSubsectionTitle(container, rpl::single(QString("AyuSync")));
}
void Ayu::SetupAyuSync(not_null<Ui::VerticalLayout *> container) { auto text = AyuSync::isAgentDownloaded() ? QString("Open preferences") : QString("Download agent");
AddSubsectionTitle(container, rpl::single(QString("AyuSync")));
auto text = AyuSync::isAgentDownloaded() ? AddButton(
QString("Open preferences") : container,
QString("Download agent"); rpl::single(text),
st::settingsButtonNoIcon
)->addClickHandler([=]
{
auto controller = &AyuSync::getControllerInstance();
controller->initializeAgent();
});
}
AddButton( void Ayu::SetupBetaFunctions(not_null<Ui::VerticalLayout*> container)
container, {
rpl::single(text), auto settings = &AyuSettings::getInstance();
st::settingsButtonNoIcon
)->addClickHandler([=] {
auto controller = &AyuSync::getControllerInstance();
controller->initializeAgent();
});
}
void Ayu::SetupBetaFunctions(not_null<Ui::VerticalLayout *> container) { AddSubsectionTitle(container, rpl::single(QString("Beta functions")));
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, rpl::single(QString("Beta functions"))); AddButton(
container,
rpl::single(QString("Send sticker confirmation")),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->stickerConfirmation)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->stickerConfirmation);
}) | start_with_next([=](bool enabled)
{
settings->set_stickerConfirmation(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
rpl::single(QString("Send sticker confirmation")), rpl::single(QString("Send GIF confirmation")),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->stickerConfirmation) rpl::single(settings->GIFConfirmation)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->stickerConfirmation); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->GIFConfirmation);
settings->set_stickerConfirmation(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_GIFConfirmation(enabled);
AyuSettings::save();
}, container->lifetime());
AddButton( AddButton(
container, container,
rpl::single(QString("Send GIF confirmation")), rpl::single(QString("Send voice confirmation")),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn( )->toggleOn(
rpl::single(settings->GIFConfirmation) rpl::single(settings->voiceConfirmation)
)->toggledValue( )->toggledValue(
) | rpl::filter([=](bool enabled) { ) | rpl::filter([=](bool enabled)
return (enabled != settings->GIFConfirmation); {
}) | rpl::start_with_next([=](bool enabled) { return (enabled != settings->voiceConfirmation);
settings->set_GIFConfirmation(enabled); }) | start_with_next([=](bool enabled)
AyuSettings::save(); {
}, container->lifetime()); settings->set_voiceConfirmation(enabled);
AyuSettings::save();
}, container->lifetime());
}
AddButton( void Ayu::SetupAyuGramSettings(not_null<Ui::VerticalLayout*> container,
container, not_null<Window::SessionController*> controller)
rpl::single(QString("Send voice confirmation")), {
st::settingsButtonNoIcon AddSkip(container);
)->toggleOn( SetupGhostEssentials(container);
rpl::single(settings->voiceConfirmation)
)->toggledValue(
) | rpl::filter([=](bool enabled) {
return (enabled != settings->voiceConfirmation);
}) | rpl::start_with_next([=](bool enabled) {
settings->set_voiceConfirmation(enabled);
AyuSettings::save();
}, container->lifetime());
}
void Ayu::SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container, AddDivider(container);
not_null<Window::SessionController *> controller) {
AddSkip(container);
SetupGhostEssentials(container);
AddDivider(container); AddSkip(container);
SetupSpyEssentials(container);
AddSkip(container); AddDivider(container);
SetupSpyEssentials(container);
AddDivider(container); AddSkip(container);
SetupQoLToggles(container);
AddSkip(container); AddDivider(container);
SetupQoLToggles(container);
AddDivider(container); AddSkip(container);
SetupCustomization(container, controller);
AddSkip(container); AddSkip(container);
SetupCustomization(container, controller); SetupAyuSync(container);
AddSkip(container); AddDivider(container);
SetupAyuSync(container);
AddDivider(container); AddSkip(container);
SetupBetaFunctions(container);
AddSkip(container); AddDividerText(container, tr::ayu_SettingsWatermark());
SetupBetaFunctions(container); }
AddDividerText(container, tr::ayu_SettingsWatermark()); void Ayu::setupContent(not_null<Window::SessionController*> controller)
} {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
void Ayu::setupContent(not_null<Window::SessionController *> controller) { SetupAyuGramSettings(content, controller);
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
SetupAyuGramSettings(content, controller); ResizeFitChild(this, content);
}
Ui::ResizeFitChild(this, content);
}
} // namespace Settings } // namespace Settings

View file

@ -11,39 +11,42 @@
class BoxContent; class BoxContent;
namespace Window { namespace Window
class Controller; {
class Controller;
class SessionController; class SessionController;
} // namespace Window } // namespace Window
namespace Settings { namespace Settings
class Ayu : public Section<Ayu> { {
public: class Ayu : public Section<Ayu>
Ayu(QWidget *parent, not_null<Window::SessionController *> controller); {
public:
Ayu(QWidget* parent, not_null<Window::SessionController*> controller);
[[nodiscard]] rpl::producer<QString> title() override; [[nodiscard]] rpl::producer<QString> title() override;
private: private:
void SetupGhostEssentials(not_null<Ui::VerticalLayout *> container); void SetupGhostEssentials(not_null<Ui::VerticalLayout*> container);
void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container); void SetupSpyEssentials(not_null<Ui::VerticalLayout*> container);
void SetupQoLToggles(not_null<Ui::VerticalLayout *> container); void SetupQoLToggles(not_null<Ui::VerticalLayout*> container);
void SetupCustomization(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller); void SetupCustomization(not_null<Ui::VerticalLayout*> container,
not_null<Window::SessionController*> controller);
void SetupShowPeerId(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller); void SetupShowPeerId(not_null<Ui::VerticalLayout*> container, not_null<Window::SessionController*> controller);
void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container); void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout*> container);
void SetupAyuSync(not_null<Ui::VerticalLayout *> container); void SetupAyuSync(not_null<Ui::VerticalLayout*> container);
void SetupBetaFunctions(not_null<Ui::VerticalLayout *> container); void SetupBetaFunctions(not_null<Ui::VerticalLayout*> container);
void SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> null); void SetupAyuGramSettings(not_null<Ui::VerticalLayout*> container, not_null<Window::SessionController*> null);
void setupContent(not_null<Window::SessionController *> controller);
};
void setupContent(not_null<Window::SessionController*> controller);
};
} // namespace Settings } // namespace Settings

View file

@ -5,47 +5,55 @@
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ui/text/text_utilities.h"
#include "ayu/ayu_settings.h"
#include "ayu_profile_values.h" #include "ayu_profile_values.h"
#include "ayu/ayu_settings.h"
#include "data/data_peer.h" #include "data/data_peer.h"
#include "ui/text/text_utilities.h"
constexpr auto kMaxChannelId = -1000000000000; constexpr auto kMaxChannelId = -1000000000000;
QString IDString(not_null<PeerData *> peer) { QString IDString(not_null<PeerData*> peer)
auto resultId = QString::number(peerIsUser(peer->id) {
? peerToUser(peer->id).bare auto resultId = QString::number(peerIsUser(peer->id)
: peerIsChat(peer->id) ? peerToUser(peer->id).bare
? peerToChat(peer->id).bare : peerIsChat(peer->id)
: peerIsChannel(peer->id) ? peerToChat(peer->id).bare
? peerToChannel(peer->id).bare : peerIsChannel(peer->id)
: peer->id.value); ? peerToChannel(peer->id).bare
: peer->id.value);
auto const settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->showPeerId == 2) { if (settings->showPeerId == 2)
if (peer->isChannel()) { {
resultId = QString::number(peerToChannel(peer->id).bare - kMaxChannelId).prepend("-"); if (peer->isChannel())
} else if (peer->isChat()) { {
resultId = resultId.prepend("-"); resultId = QString::number(peerToChannel(peer->id).bare - kMaxChannelId).prepend("-");
} }
} else if (peer->isChat())
{
resultId = resultId.prepend("-");
}
}
return resultId; return resultId;
} }
QString IDString(MsgId topic_root_id) { QString IDString(MsgId topic_root_id)
auto resultId = QString::number(topic_root_id.bare); {
auto resultId = QString::number(topic_root_id.bare);
return resultId; return resultId;
} }
rpl::producer<TextWithEntities> IDValue(not_null<PeerData *> peer) { rpl::producer<TextWithEntities> IDValue(not_null<PeerData*> peer)
return rpl::single(IDString(peer)) | Ui::Text::ToWithEntities(); {
return rpl::single(IDString(peer)) | Ui::Text::ToWithEntities();
} }
rpl::producer<TextWithEntities> IDValue(MsgId topic_root_id) { rpl::producer<TextWithEntities> IDValue(MsgId topic_root_id)
return rpl::single(IDString(topic_root_id)) | Ui::Text::ToWithEntities(); {
} return rpl::single(IDString(topic_root_id)) | Ui::Text::ToWithEntities();
}

View file

@ -8,8 +8,8 @@
#pragma once #pragma once
QString IDString(not_null<PeerData *> peer); QString IDString(not_null<PeerData*> peer);
QString IDString(MsgId topic_root_id); QString IDString(MsgId topic_root_id);
rpl::producer<TextWithEntities> IDValue(not_null<PeerData *> peer); rpl::producer<TextWithEntities> IDValue(not_null<PeerData*> peer);
rpl::producer<TextWithEntities> IDValue(MsgId topic_root_id); rpl::producer<TextWithEntities> IDValue(MsgId topic_root_id);

View file

@ -481,29 +481,32 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
}); });
} }
if (settings->showPeerId != 0) { if (settings->showPeerId != 0)
{
auto idDrawableText = IDValue( auto idDrawableText = IDValue(
user user
) | rpl::map([](TextWithEntities &&text) { ) | rpl::map([](TextWithEntities&& text)
return Ui::Text::Code(text.text); {
}); return Ui::Text::Code(text.text);
auto idInfo = addInfoOneLine( });
rpl::single(QString("ID")), auto idInfo = addInfoOneLine(
std::move(idDrawableText), rpl::single(QString("ID")),
tr::ayu_ContextCopyID(tr::now) std::move(idDrawableText),
); tr::ayu_ContextCopyID(tr::now)
);
idInfo.text->setClickHandlerFilter([=](auto &&...) { idInfo.text->setClickHandlerFilter([=](auto&&...)
const auto idText = IDString(user); {
if (!idText.isEmpty()) { const auto idText = IDString(user);
QGuiApplication::clipboard()->setText(idText); if (!idText.isEmpty())
const auto msg = tr::ayu_IDCopiedToast(tr::now); {
controller->showToast(msg); QGuiApplication::clipboard()->setText(idText);
} const auto msg = tr::ayu_IDCopiedToast(tr::now);
return false; controller->showToast(msg);
}); }
} return false;
});
}
AddMainButton( AddMainButton(
result, result,
@ -566,45 +569,53 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
addTranslateToMenu(about.text, AboutValue(_peer)); addTranslateToMenu(about.text, AboutValue(_peer));
} }
if (settings->showPeerId != 0 && !_topic) { if (settings->showPeerId != 0 && !_topic)
auto idDrawableText = IDValue( {
_peer auto idDrawableText = IDValue(
) | rpl::map([](TextWithEntities &&text) { _peer
return Ui::Text::Code(text.text); ) | rpl::map([](TextWithEntities&& text)
}); {
auto idInfo = addInfoOneLine( return Ui::Text::Code(text.text);
rpl::single(QString("ID")), });
std::move(idDrawableText), auto idInfo = addInfoOneLine(
tr::ayu_ContextCopyID(tr::now) rpl::single(QString("ID")),
); std::move(idDrawableText),
tr::ayu_ContextCopyID(tr::now)
);
idInfo.text->setClickHandlerFilter([=, peer = _peer](auto &&...) { idInfo.text->setClickHandlerFilter([=, peer = _peer](auto&&...)
const auto idText = IDString(peer); {
if (!idText.isEmpty()) { const auto idText = IDString(peer);
QGuiApplication::clipboard()->setText(idText); if (!idText.isEmpty())
const auto msg = tr::ayu_IDCopiedToast(tr::now); {
controller->showToast(msg); QGuiApplication::clipboard()->setText(idText);
} const auto msg = tr::ayu_IDCopiedToast(tr::now);
return false; controller->showToast(msg);
}); }
} return false;
});
}
if (settings->showPeerId != 0 && _topic) { if (settings->showPeerId != 0 && _topic)
{
const auto topicRootId = _topic->rootId(); const auto topicRootId = _topic->rootId();
auto idDrawableText = IDValue( auto idDrawableText = IDValue(
_peer->forumTopicFor(topicRootId)->topicRootId() _peer->forumTopicFor(topicRootId)->topicRootId()
) | rpl::map([](TextWithEntities &&text) { ) | rpl::map([](TextWithEntities&& text)
return Ui::Text::Code(text.text); {
return Ui::Text::Code(text.text);
}); });
auto idInfo = addInfoOneLine( auto idInfo = addInfoOneLine(
rpl::single(QString("ID")), rpl::single(QString("ID")),
std::move(idDrawableText), std::move(idDrawableText),
tr::ayu_ContextCopyID(tr::now) tr::ayu_ContextCopyID(tr::now)
); );
idInfo.text->setClickHandlerFilter([=, peer = _peer](auto &&...) { idInfo.text->setClickHandlerFilter([=, peer = _peer](auto&&...)
{
const auto idText = IDString(peer); const auto idText = IDString(peer);
if (!idText.isEmpty()) { if (!idText.isEmpty())
{
QGuiApplication::clipboard()->setText(idText); QGuiApplication::clipboard()->setText(idText);
const auto msg = tr::ayu_IDCopiedToast(tr::now); const auto msg = tr::ayu_IDCopiedToast(tr::now);
controller->showToast(msg); controller->showToast(msg);