chore: reformat & refactor & remove as not planned for now

This commit is contained in:
ZavaruKitsu 2024-02-04 18:36:11 +03:00
parent 4a6ae07409
commit adb5abf4fb
105 changed files with 2169 additions and 5531 deletions

57
.clang-format Normal file
View file

@ -0,0 +1,57 @@
---
Language: Cpp
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignOperands: false
AlignTrailingComments: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: false
AfterNamespace: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: true
BeforeWhile: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBraces: Custom
ColumnLimit: 120
IncludeCategories:
- Regex: '^<.*'
Priority: 1
- Regex: '^".*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentWidth: 4
InsertNewlineAtEOF: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
TabWidth: 4
UseTab: Always
...

View file

@ -76,8 +76,6 @@ Enjoy using **AyuGram**? Consider sending us a tip!
### Libraries used ### Libraries used
- [JSON for Modern C++](https://github.com/nlohmann/json) - [JSON for Modern C++](https://github.com/nlohmann/json)
- [BitConverter](https://github.com/YanjieHe/BitConverter)
- [Not Enough Standards](https://github.com/Alairion/not-enough-standards)
- [SQLite](https://github.com/sqlite/sqlite) - [SQLite](https://github.com/sqlite/sqlite)
- [sqlite_orm](https://github.com/fnc12/sqlite_orm) - [sqlite_orm](https://github.com/fnc12/sqlite_orm)

View file

@ -148,18 +148,10 @@ PRIVATE
ayu/ui/boxes/message_shot_box.h ayu/ui/boxes/message_shot_box.h
ayu/ui/components/image_view.cpp ayu/ui/components/image_view.cpp
ayu/ui/components/image_view.h ayu/ui/components/image_view.h
ayu/sync/ayu_sync_controller.cpp
ayu/sync/ayu_sync_controller.h
ayu/sync/models.h
ayu/sync/utils/ayu_pipe_wrapper.cpp
ayu/sync/utils/ayu_pipe_wrapper.h
ayu/sync/utils/process_utils.hpp
ayu/messages/ayu_messages_controller.cpp ayu/messages/ayu_messages_controller.cpp
ayu/messages/ayu_messages_controller.h ayu/messages/ayu_messages_controller.h
ayu/libs/pipe.hpp
ayu/libs/json.hpp ayu/libs/json.hpp
ayu/libs/json_ext.hpp ayu/libs/json_ext.hpp
ayu/libs/bit_converter.hpp
ayu/libs/sqlite/sqlite3.c ayu/libs/sqlite/sqlite3.c
ayu/libs/sqlite/sqlite3.h ayu/libs/sqlite/sqlite3.h
ayu/libs/sqlite/sqlite_orm.h ayu/libs/sqlite/sqlite_orm.h

View file

@ -3567,8 +3567,7 @@ void ApiWrap::sendUploadedPhoto(
if (const auto item = _session->data().message(localId)) { if (const auto item = _session->data().message(localId)) {
// AyuGram useScheduledMessages // AyuGram useScheduledMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->useScheduledMessages && !options.scheduled) if (settings->useScheduledMessages && !options.scheduled) {
{
DEBUG_LOG(("[AyuGram] Scheduling message")); DEBUG_LOG(("[AyuGram] Scheduling message"));
auto current = base::unixtime::now(); auto current = base::unixtime::now();
options.scheduled = current + 18; // using 18 seconds because photo can be big options.scheduled = current + 18; // using 18 seconds because photo can be big
@ -3594,8 +3593,7 @@ void ApiWrap::sendUploadedDocument(
// AyuGram useScheduledMessages // AyuGram useScheduledMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->useScheduledMessages && !options.scheduled) if (settings->useScheduledMessages && !options.scheduled) {
{
DEBUG_LOG(("[AyuGram] Scheduling message")); DEBUG_LOG(("[AyuGram] Scheduling message"));
auto current = base::unixtime::now(); auto current = base::unixtime::now();
options.scheduled = current + 60; // well, a document can be really big... options.scheduled = current + 60; // well, a document can be really big...
@ -4078,8 +4076,7 @@ void ApiWrap::sendMediaWithRandomId(
Fn<void(bool)> done) { Fn<void(bool)> done) {
// AyuGram useScheduledMessages // AyuGram useScheduledMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->useScheduledMessages && !options.scheduled) if (settings->useScheduledMessages && !options.scheduled) {
{
DEBUG_LOG(("[AyuGram] Scheduling message")); DEBUG_LOG(("[AyuGram] Scheduling message"));
auto current = base::unixtime::now(); auto current = base::unixtime::now();
options.scheduled = current + 12; options.scheduled = current + 12;
@ -4180,8 +4177,7 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
// AyuGram useScheduledMessages // AyuGram useScheduledMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->useScheduledMessages && !album->options.scheduled) if (settings->useScheduledMessages && !album->options.scheduled) {
{
DEBUG_LOG(("[AyuGram] Scheduling message")); DEBUG_LOG(("[AyuGram] Scheduling message"));
auto current = base::unixtime::now(); auto current = base::unixtime::now();
album->options.scheduled = current + 12; album->options.scheduled = current + 12;

View file

@ -8,9 +8,6 @@
// https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java // https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java
constexpr int DOCUMENT_TYPE_NONE = 0; constexpr int DOCUMENT_TYPE_NONE = 0;
constexpr int DOCUMENT_TYPE_PHOTO = 1; constexpr int DOCUMENT_TYPE_PHOTO = 1;
constexpr int DOCUMENT_TYPE_STICKER = 2; constexpr int DOCUMENT_TYPE_STICKER = 2;
constexpr int DOCUMENT_TYPE_FILE = 3; constexpr int DOCUMENT_TYPE_FILE = 3;

View file

@ -8,15 +8,13 @@
#include "ayu_lang.h" #include "ayu_lang.h"
#include "ayu_worker.h" #include "ayu_worker.h"
#include "ayu/ayu_settings.h"
#include "ayu/database/ayu_database.h" #include "ayu/database/ayu_database.h"
#include "lang/lang_instance.h" #include "lang/lang_instance.h"
#include "ayu/ayu_settings.h"
namespace AyuInfra namespace AyuInfra {
{
void initLang() void initLang() {
{
QString langPackBaseId = Lang::GetInstance().baseId(); QString langPackBaseId = Lang::GetInstance().baseId();
QString langPackId = Lang::GetInstance().id(); QString langPackId = Lang::GetInstance().id();
if (langPackId.isEmpty()) { if (langPackId.isEmpty()) {
@ -27,30 +25,26 @@ void initLang()
CustomLangPack::currentInstance()->fetchCustomLangPack(langPackId, langPackBaseId); CustomLangPack::currentInstance()->fetchCustomLangPack(langPackId, langPackBaseId);
} }
void initFonts() void initFonts() {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AyuFonts::setMainFont(settings->mainFont); AyuFonts::setMainFont(settings->mainFont);
AyuFonts::setMonoFont(settings->monoFont); AyuFonts::setMonoFont(settings->monoFont);
} }
void initDatabase() void initDatabase() {
{
AyuDatabase::initialize(); AyuDatabase::initialize();
} }
void initWorker() void initWorker() {
{
AyuWorker::initialize(); AyuWorker::initialize();
} }
void init() void init() {
{
initLang(); initLang();
initDatabase(); initDatabase();
initFonts(); initFonts();
initWorker(); initWorker();
} }
} }

View file

@ -6,8 +6,7 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
namespace AyuInfra namespace AyuInfra {
{
void init(); void init();

View file

@ -24,26 +24,22 @@ 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 = langMapping.contains(langPackId) ? langMapping[langPackId] : langPackId; auto finalLangPackId = langMapping.contains(langPackId) ? langMapping[langPackId] : langPackId;
const auto proxy = Core::App().settings().proxy().isEnabled() const auto proxy = Core::App().settings().proxy().isEnabled()
? Core::App().settings().proxy().selected() ? Core::App().settings().proxy().selected()
: MTP::ProxyData(); : MTP::ProxyData();
if (proxy.type == MTP::ProxyData::Type::Socks5 || proxy.type == MTP::ProxyData::Type::Http) { if (proxy.type == MTP::ProxyData::Type::Socks5 || proxy.type == MTP::ProxyData::Type::Http) {
QNetworkProxy LocaleProxy = ToNetworkProxy(ToDirectIpProxy(proxy)); QNetworkProxy LocaleProxy = ToNetworkProxy(ToDirectIpProxy(proxy));
networkManager.setProxy(LocaleProxy); networkManager.setProxy(LocaleProxy);
@ -55,8 +51,7 @@ void CustomLangPack::fetchCustomLangPack(const QString &langPackId, const QStrin
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) { if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
url.setUrl(qsl("https://cdn.jsdelivr.net/gh/AyuGram/Languages@l10n_main/values/langs/%1/Shared.json").arg( url.setUrl(qsl("https://cdn.jsdelivr.net/gh/AyuGram/Languages@l10n_main/values/langs/%1/Shared.json").arg(
finalLangPackId)); finalLangPackId));
} } else {
else {
url.setUrl(qsl("https://cdn.jsdelivr.net/gh/AyuGram/Languages@l10n_main/values/langs/%1/Shared.json").arg( url.setUrl(qsl("https://cdn.jsdelivr.net/gh/AyuGram/Languages@l10n_main/values/langs/%1/Shared.json").arg(
needFallback ? langPackBaseId : finalLangPackId)); needFallback ? langPackBaseId : finalLangPackId));
} }
@ -67,8 +62,7 @@ void CustomLangPack::fetchCustomLangPack(const QString &langPackId, const QStrin
needFallback ? (langPackBaseId.isEmpty() ? finalLangPackId : langPackBaseId) : finalLangPackId)); 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();
@ -80,15 +74,13 @@ void CustomLangPack::fetchFinished()
needFallback = true; needFallback = true;
_chkReply->disconnect(); _chkReply->disconnect();
fetchCustomLangPack("", langPackBaseId); fetchCustomLangPack("", langPackBaseId);
} } else {
else {
QByteArray result = _chkReply->readAll().trimmed(); QByteArray result = _chkReply->readAll().trimmed();
QJsonParseError error{}; QJsonParseError error{};
QJsonDocument str = QJsonDocument::fromJson(result, &error); QJsonDocument str = QJsonDocument::fromJson(result, &error);
if (error.error == QJsonParseError::NoError) { if (error.error == QJsonParseError::NoError) {
parseLangFile(str); parseLangFile(str);
} } else {
else {
LOG(("Incorrect JSON File. Fallback to default language: English...")); LOG(("Incorrect JSON File. Fallback to default language: English..."));
loadDefaultLangFile(); loadDefaultLangFile();
} }
@ -97,8 +89,7 @@ void CustomLangPack::fetchFinished()
} }
} }
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) {
@ -110,8 +101,7 @@ void CustomLangPack::fetchError(QNetworkReply::NetworkError e)
needFallback = true; needFallback = true;
_chkReply->disconnect(); _chkReply->disconnect();
fetchCustomLangPack("", langPackBaseId); fetchCustomLangPack("", langPackBaseId);
} } else {
else {
LOG(("AyuGram Language pack not found! Fallback to default language: English...")); LOG(("AyuGram Language pack not found! Fallback to default language: English..."));
loadDefaultLangFile(); loadDefaultLangFile();
_chkReply = nullptr; _chkReply = nullptr;
@ -119,8 +109,7 @@ void CustomLangPack::fetchError(QNetworkReply::NetworkError e)
} }
} }
void CustomLangPack::loadDefaultLangFile() void CustomLangPack::loadDefaultLangFile() {
{
QFile file(":/localization/en.json"); QFile file(":/localization/en.json");
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
QJsonDocument str = QJsonDocument::fromJson(file.readAll()); QJsonDocument str = QJsonDocument::fromJson(file.readAll());
@ -133,8 +122,7 @@ void CustomLangPack::loadDefaultLangFile()
} }
} }
void CustomLangPack::parseLangFile(QJsonDocument str) void CustomLangPack::parseLangFile(QJsonDocument str) {
{
QJsonObject json = str.object(); QJsonObject json = str.object();
for (const QString &brokenKey : json.keys()) { for (const QString &brokenKey : json.keys()) {
auto key = qsl("ayu_") + brokenKey; auto key = qsl("ayu_") + brokenKey;

View file

@ -11,31 +11,24 @@
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() override = default; ~CustomLangPack() override = default;
QNetworkAccessManager networkManager; QNetworkAccessManager networkManager;

View file

@ -22,45 +22,37 @@
using json = nlohmann::json; using json = nlohmann::json;
namespace AyuSettings namespace AyuSettings {
{
const std::string filename = "tdata/ayu_settings.json"; const std::string filename = "tdata/ayu_settings.json";
std::optional<AyuGramSettings> settings = std::nullopt; std::optional<AyuGramSettings> settings = std::nullopt;
rpl::variable<bool> sendReadMessagesReactive; rpl::variable<bool> sendReadMessagesReactive;
rpl::variable<bool> sendReadStoriesReactive; rpl::variable<bool> sendReadStoriesReactive;
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<bool> ghostModeEnabled;
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::lifetime lifetime = rpl::lifetime(); rpl::lifetime lifetime = rpl::lifetime();
bool ghostModeEnabled_util(AyuGramSettings &settingsUtil) bool ghostModeEnabled_util(const AyuGramSettings &settingsUtil) {
{
return return
!settingsUtil.sendReadMessages !settingsUtil.sendReadMessages
&& !settingsUtil.sendReadStories && !settingsUtil.sendReadStories
&& !settingsUtil.sendOnlinePackets && !settingsUtil.sendOnlinePackets
&& !settingsUtil.sendUploadProgress && !settingsUtil.sendUploadProgress
&& settingsUtil.sendOfflinePacketAfterOnline; && settingsUtil.sendOfflinePacketAfterOnline;
} }
void initialize() void initialize() {
{
if (settings.has_value()) { if (settings.has_value()) {
return; return;
} }
@ -76,7 +68,8 @@ void initialize()
{ {
ghostModeEnabled = ghostModeEnabled =
ghostModeEnabled_util(settings.value()); ghostModeEnabled_util(settings.value());
}, lifetime); },
lifetime);
// .. // ..
sendReadStoriesReactive.value() | rpl::filter( sendReadStoriesReactive.value() | rpl::filter(
[=](bool val) [=](bool val)
@ -87,7 +80,8 @@ void initialize()
{ {
ghostModeEnabled = ghostModeEnabled =
ghostModeEnabled_util(settings.value()); ghostModeEnabled_util(settings.value());
}, lifetime); },
lifetime);
// .. // ..
sendOnlinePacketsReactive.value() | rpl::filter( sendOnlinePacketsReactive.value() | rpl::filter(
[=](bool val) [=](bool val)
@ -98,8 +92,9 @@ void initialize()
{ {
ghostModeEnabled = ghostModeEnabled =
ghostModeEnabled_util(settings ghostModeEnabled_util(settings
.value()); .value());
}, lifetime); },
lifetime);
// .. // ..
sendUploadProgressReactive.value() | rpl::filter( sendUploadProgressReactive.value() | rpl::filter(
[=](bool val) [=](bool val)
@ -110,8 +105,9 @@ void initialize()
{ {
ghostModeEnabled = ghostModeEnabled =
ghostModeEnabled_util(settings ghostModeEnabled_util(settings
.value()); .value());
}, lifetime); },
lifetime);
// .. // ..
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter( sendOfflinePacketAfterOnlineReactive.value() | rpl::filter(
[=](bool val) [=](bool val)
@ -124,11 +120,11 @@ void initialize()
ghostModeEnabled = ghostModeEnabled =
ghostModeEnabled_util( ghostModeEnabled_util(
settings.value()); settings.value());
}, lifetime); },
lifetime);
} }
void postinitialize() void postinitialize() {
{
sendReadMessagesReactive = settings->sendReadMessages; sendReadMessagesReactive = settings->sendReadMessages;
sendReadStoriesReactive = settings->sendReadStories; sendReadStoriesReactive = settings->sendReadStories;
sendUploadProgressReactive = settings->sendUploadProgress; sendUploadProgressReactive = settings->sendUploadProgress;
@ -142,14 +138,12 @@ void postinitialize()
ghostModeEnabled = ghostModeEnabled_util(settings.value()); ghostModeEnabled = ghostModeEnabled_util(settings.value());
} }
AyuGramSettings &getInstance() AyuGramSettings &getInstance() {
{
initialize(); initialize();
return settings.value(); return settings.value();
} }
void load() void load() {
{
std::ifstream file(filename); std::ifstream file(filename);
if (!file.good()) { if (!file.good()) {
return; return;
@ -164,19 +158,16 @@ void load()
try { try {
settings = p.get<AyuGramSettings>(); settings = p.get<AyuGramSettings>();
} } catch (...) {
catch (...) {
LOG(("AyuGramSettings: failed to parse settings file")); LOG(("AyuGramSettings: failed to parse settings file"));
} }
} } catch (...) {
catch (...) {
LOG(("AyuGramSettings: failed to read settings file (not json-like)")); LOG(("AyuGramSettings: failed to read settings file (not json-like)"));
} }
postinitialize(); postinitialize();
} }
void save() void save() {
{
initialize(); initialize();
json p = settings.value(); json p = settings.value();
@ -189,8 +180,7 @@ void save()
postinitialize(); postinitialize();
} }
AyuGramSettings::AyuGramSettings() AyuGramSettings::AyuGramSettings() {
{
// ~ Ghost essentials // ~ Ghost essentials
sendReadMessages = true; sendReadMessages = true;
sendReadStories = true; sendReadStories = true;
@ -265,38 +255,32 @@ AyuGramSettings::AyuGramSettings()
voiceConfirmation = false; voiceConfirmation = false;
} }
void AyuGramSettings::set_sendReadMessages(bool val) void AyuGramSettings::set_sendReadMessages(bool val) {
{
sendReadMessages = val; sendReadMessages = val;
sendReadMessagesReactive = val; sendReadMessagesReactive = val;
} }
void AyuGramSettings::set_sendReadStories(bool val) void AyuGramSettings::set_sendReadStories(bool val) {
{
sendReadStories = val; sendReadStories = val;
sendReadStoriesReactive = val; sendReadStoriesReactive = val;
} }
void AyuGramSettings::set_sendOnlinePackets(bool val) void AyuGramSettings::set_sendOnlinePackets(bool val) {
{
sendOnlinePackets = val; sendOnlinePackets = val;
sendOnlinePacketsReactive = val; sendOnlinePacketsReactive = val;
} }
void AyuGramSettings::set_sendUploadProgress(bool val) void AyuGramSettings::set_sendUploadProgress(bool val) {
{
sendUploadProgress = val; sendUploadProgress = val;
sendUploadProgressReactive = val; sendUploadProgressReactive = val;
} }
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val) void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val) {
{
sendOfflinePacketAfterOnline = val; sendOfflinePacketAfterOnline = val;
sendOfflinePacketAfterOnlineReactive = val; sendOfflinePacketAfterOnlineReactive = val;
} }
void AyuGramSettings::set_ghostModeEnabled(bool val) void AyuGramSettings::set_ghostModeEnabled(bool val) {
{
set_sendReadMessages(!val); set_sendReadMessages(!val);
set_sendReadStories(!val); set_sendReadStories(!val);
set_sendOnlinePackets(!val); set_sendOnlinePackets(!val);
@ -310,231 +294,186 @@ void AyuGramSettings::set_ghostModeEnabled(bool val)
} }
} }
void AyuGramSettings::set_markReadAfterSend(bool val) void AyuGramSettings::set_markReadAfterSend(bool val) {
{
markReadAfterSend = val; markReadAfterSend = val;
} }
void AyuGramSettings::set_markReadAfterReaction(bool val) void AyuGramSettings::set_markReadAfterReaction(bool val) {
{
markReadAfterReaction = val; markReadAfterReaction = val;
} }
void AyuGramSettings::set_markReadAfterPoll(bool val) void AyuGramSettings::set_markReadAfterPoll(bool val) {
{
markReadAfterPoll = val; markReadAfterPoll = val;
} }
void AyuGramSettings::set_useScheduledMessages(bool val) void AyuGramSettings::set_useScheduledMessages(bool val) {
{
useScheduledMessages = val; useScheduledMessages = val;
} }
void AyuGramSettings::set_saveDeletedMessages(bool val) void AyuGramSettings::set_saveDeletedMessages(bool val) {
{
saveDeletedMessages = val; saveDeletedMessages = val;
} }
void AyuGramSettings::set_saveMessagesHistory(bool val) void AyuGramSettings::set_saveMessagesHistory(bool val) {
{
saveMessagesHistory = val; saveMessagesHistory = val;
} }
void AyuGramSettings::set_disableAds(bool val) void AyuGramSettings::set_disableAds(bool val) {
{
disableAds = val; disableAds = val;
} }
void AyuGramSettings::set_disableStories(bool val) void AyuGramSettings::set_disableStories(bool val) {
{
disableStories = val; disableStories = val;
} }
void AyuGramSettings::set_collapseSimilarChannels(bool val) void AyuGramSettings::set_collapseSimilarChannels(bool val) {
{
collapseSimilarChannels = val; collapseSimilarChannels = val;
} }
void AyuGramSettings::set_hideSimilarChannels(bool val) void AyuGramSettings::set_hideSimilarChannels(bool val) {
{
hideSimilarChannels = val; hideSimilarChannels = val;
} }
void AyuGramSettings::set_uploadSpeedBoost(bool val) void AyuGramSettings::set_uploadSpeedBoost(bool val) {
{
uploadSpeedBoost = val; uploadSpeedBoost = val;
} }
void AyuGramSettings::set_disableNotificationsDelay(bool val) void AyuGramSettings::set_disableNotificationsDelay(bool val) {
{
disableNotificationsDelay = val; disableNotificationsDelay = val;
} }
void AyuGramSettings::set_localPremium(bool val) void AyuGramSettings::set_localPremium(bool val) {
{
localPremium = val; localPremium = val;
} }
void AyuGramSettings::set_copyUsernameAsLink(bool val) void AyuGramSettings::set_copyUsernameAsLink(bool val) {
{
copyUsernameAsLink = val; copyUsernameAsLink = val;
} }
void AyuGramSettings::set_appIcon(QString val) void AyuGramSettings::set_appIcon(QString val) {
{
appIcon = std::move(val); appIcon = std::move(val);
} }
void AyuGramSettings::set_simpleQuotesAndReplies(bool val) void AyuGramSettings::set_simpleQuotesAndReplies(bool val) {
{
simpleQuotesAndReplies = val; simpleQuotesAndReplies = val;
} }
void AyuGramSettings::set_deletedMark(QString val) void AyuGramSettings::set_deletedMark(QString val) {
{
deletedMark = std::move(val); deletedMark = std::move(val);
deletedMarkReactive = deletedMark; deletedMarkReactive = deletedMark;
} }
void AyuGramSettings::set_editedMark(QString val) void AyuGramSettings::set_editedMark(QString val) {
{
editedMark = std::move(val); editedMark = std::move(val);
editedMarkReactive = editedMark; editedMarkReactive = editedMark;
} }
void AyuGramSettings::set_recentStickersCount(int val) void AyuGramSettings::set_recentStickersCount(int val) {
{
recentStickersCount = val; recentStickersCount = val;
} }
void AyuGramSettings::set_showReactionsPanelInContextMenu(int val) void AyuGramSettings::set_showReactionsPanelInContextMenu(int val) {
{
showReactionsPanelInContextMenu = val; showReactionsPanelInContextMenu = val;
} }
void AyuGramSettings::set_showViewsPanelInContextMenu(int val) void AyuGramSettings::set_showViewsPanelInContextMenu(int val) {
{
showViewsPanelInContextMenu = val; showViewsPanelInContextMenu = val;
} }
void AyuGramSettings::set_showHideMessageInContextMenu(int val) void AyuGramSettings::set_showHideMessageInContextMenu(int val) {
{
showHideMessageInContextMenu = val; showHideMessageInContextMenu = val;
} }
void AyuGramSettings::set_showUserMessagesInContextMenu(int val) void AyuGramSettings::set_showUserMessagesInContextMenu(int val) {
{
showUserMessagesInContextMenu = val; showUserMessagesInContextMenu = val;
} }
void AyuGramSettings::set_showMessageDetailsInContextMenu(int val) void AyuGramSettings::set_showMessageDetailsInContextMenu(int val) {
{
showMessageDetailsInContextMenu = val; showMessageDetailsInContextMenu = val;
} }
void AyuGramSettings::set_showLReadToggleInDrawer(bool val) void AyuGramSettings::set_showLReadToggleInDrawer(bool val) {
{
showLReadToggleInDrawer = val; showLReadToggleInDrawer = val;
} }
void AyuGramSettings::set_showSReadToggleInDrawer(bool val) void AyuGramSettings::set_showSReadToggleInDrawer(bool val) {
{
showSReadToggleInDrawer = val; showSReadToggleInDrawer = val;
} }
void AyuGramSettings::set_showGhostToggleInDrawer(bool val) void AyuGramSettings::set_showGhostToggleInDrawer(bool val) {
{
showGhostToggleInDrawer = val; showGhostToggleInDrawer = val;
} }
void AyuGramSettings::set_showStreamerToggleInDrawer(bool val) void AyuGramSettings::set_showStreamerToggleInDrawer(bool val) {
{
showStreamerToggleInDrawer = val; showStreamerToggleInDrawer = val;
} }
void AyuGramSettings::set_showGhostToggleInTray(bool val) void AyuGramSettings::set_showGhostToggleInTray(bool val) {
{
showGhostToggleInTray = val; showGhostToggleInTray = val;
} }
void AyuGramSettings::set_showStreamerToggleInTray(bool val) void AyuGramSettings::set_showStreamerToggleInTray(bool val) {
{
showStreamerToggleInTray = val; showStreamerToggleInTray = val;
} }
void AyuGramSettings::set_mainFont(QString val) void AyuGramSettings::set_mainFont(QString val) {
{
mainFont = val; mainFont = val;
} }
void AyuGramSettings::set_monoFont(QString val) void AyuGramSettings::set_monoFont(QString val) {
{
monoFont = val; monoFont = val;
} }
void AyuGramSettings::set_showPeerId(int val) void AyuGramSettings::set_showPeerId(int val) {
{
showPeerId = val; showPeerId = val;
showPeerIdReactive = val; showPeerIdReactive = val;
} }
void AyuGramSettings::set_hideNotificationCounters(bool val) void AyuGramSettings::set_hideNotificationCounters(bool val) {
{
hideNotificationCounters = val; hideNotificationCounters = val;
} }
void AyuGramSettings::set_hideAllChatsFolder(bool val) void AyuGramSettings::set_hideAllChatsFolder(bool val) {
{
hideAllChatsFolder = val; hideAllChatsFolder = val;
} }
void AyuGramSettings::set_showMessageSeconds(bool val) void AyuGramSettings::set_showMessageSeconds(bool val) {
{
showMessageSeconds = val; showMessageSeconds = val;
} }
void AyuGramSettings::set_showMessageShot(bool val) void AyuGramSettings::set_showMessageShot(bool val) {
{
showMessageShot = val; showMessageShot = 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

@ -10,8 +10,7 @@
#include "ayu/libs/json_ext.hpp" #include "ayu/libs/json_ext.hpp"
#include "rpl/producer.h" #include "rpl/producer.h"
namespace AyuSettings namespace AyuSettings {
{
class AyuGramSettings class AyuGramSettings
{ {
@ -77,7 +76,6 @@ public:
bool gifConfirmation; bool gifConfirmation;
bool voiceConfirmation; bool voiceConfirmation;
public:
void set_sendReadMessages(bool val); void set_sendReadMessages(bool val);
void set_sendReadStories(bool val); void set_sendReadStories(bool val);
void set_sendOnlinePackets(bool val); void set_sendOnlinePackets(bool val);

View file

@ -6,23 +6,19 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ayu_state.h" #include "ayu_state.h"
namespace AyuState namespace AyuState {
{
std::unordered_map<PeerId, std::unordered_set<MsgId>> hiddenMessages; std::unordered_map<PeerId, std::unordered_set<MsgId>> hiddenMessages;
void hide(PeerId peerId, MsgId messageId) void hide(PeerId peerId, MsgId messageId) {
{
hiddenMessages[peerId].insert(messageId); hiddenMessages[peerId].insert(messageId);
} }
void hide(not_null<HistoryItem *> item) void hide(not_null<HistoryItem *> item) {
{
hide(item->history()->peer->id, item->id); hide(item->history()->peer->id, item->id);
} }
bool isHidden(PeerId peerId, MsgId messageId) bool isHidden(PeerId peerId, MsgId messageId) {
{
const auto it = hiddenMessages.find(peerId); const auto it = hiddenMessages.find(peerId);
if (it != hiddenMessages.end()) { if (it != hiddenMessages.end()) {
return it->second.contains(messageId); return it->second.contains(messageId);
@ -30,8 +26,7 @@ bool isHidden(PeerId peerId, MsgId messageId)
return false; return false;
} }
bool isHidden(not_null<HistoryItem *> item) bool isHidden(not_null<HistoryItem *> item) {
{
return isHidden(item->history()->peer->id, item->id); return isHidden(item->history()->peer->id, item->id);
} }

View file

@ -6,13 +6,10 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "ayu_settings.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
namespace AyuState namespace AyuState {
{
void hide(PeerId peerId, MsgId messageId); void hide(PeerId peerId, MsgId messageId);
void hide(not_null<HistoryItem *> item); void hide(not_null<HistoryItem *> item);

View file

@ -10,23 +10,23 @@
#include "lang_auto.h" #include "lang_auto.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "ui/boxes/confirm_box.h"
#include "ayu/utils/telegram_helpers.h" #include "ayu/utils/telegram_helpers.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "core/application.h" #include "core/application.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "ui/boxes/confirm_box.h"
#include <QDesktopServices> #include <QDesktopServices>
namespace AyuUrlHandlers #include "main/main_session.h"
{
namespace AyuUrlHandlers {
bool ResolveUser( bool ResolveUser(
Window::SessionController *controller, Window::SessionController *controller,
const Match &match, const Match &match,
const QVariant &context) const QVariant &context) {
{
if (!controller) { if (!controller) {
return false; return false;
} }
@ -43,16 +43,19 @@ bool ResolveUser(
return true; return true;
} }
searchById(userId, &controller->session(), false, [=](const QString &title, UserData *data) searchById(userId,
{ &controller->session(),
if (data) { false,
controller->showPeerInfo(data); [=](const QString &title, UserData *data)
return; {
} if (data) {
controller->showPeerInfo(data);
return;
}
Core::App().hideMediaView(); Core::App().hideMediaView();
Ui::show(Ui::MakeInformBox(tr::ayu_UserNotFoundMessage())); Ui::show(Ui::MakeInformBox(tr::ayu_UserNotFoundMessage()));
}); });
return true; return true;
} }
@ -60,8 +63,7 @@ bool ResolveUser(
bool HandleAyu( bool HandleAyu(
Window::SessionController *controller, Window::SessionController *controller,
const Match &match, const Match &match,
const QVariant &context) const QVariant &context) {
{
if (!controller) { if (!controller) {
return false; return false;
} }
@ -69,8 +71,7 @@ bool HandleAyu(
return true; return true;
} }
bool TryHandleSpotify(const QString& url) bool TryHandleSpotify(const QString &url) {
{
if (!url.contains("spotify.com")) { if (!url.contains("spotify.com")) {
return false; return false;
} }
@ -96,12 +97,10 @@ bool TryHandleSpotify(const QString& url)
const auto res = QString("spotify:%1:%2").arg(type).arg(identifier); const auto res = QString("spotify:%1:%2").arg(type).arg(identifier);
if (!res.isEmpty()) { return QDesktopServices::openUrl(QUrl(res));
return QDesktopServices::openUrl(QUrl(res));
}
} }
return false; return false;
} }
} }

View file

@ -6,11 +6,10 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "window/window_session_controller.h"
#include "base/qthelp_regex.h" #include "base/qthelp_regex.h"
#include "window/window_session_controller.h"
namespace AyuUrlHandlers namespace AyuUrlHandlers {
{
using Match = qthelp::RegularExpressionMatch; using Match = qthelp::RegularExpressionMatch;
@ -24,6 +23,6 @@ bool HandleAyu(
const Match &match, const Match &match,
const QVariant &context); const QVariant &context);
bool TryHandleSpotify(const QString& url); bool TryHandleSpotify(const QString &url);
} }

View file

@ -16,17 +16,15 @@
#include "main/main_domain.h" #include "main/main_domain.h"
#include "main/main_session.h" #include "main/main_session.h"
namespace AyuWorker namespace AyuWorker {
{
std::unordered_map<ID, bool> state; std::unordered_map<ID, bool> state;
void markAsOnline(not_null<Main::Session *> session) void markAsOnline(not_null<Main::Session *> session) {
{
state[session->userId().bare] = true; state[session->userId().bare] = true;
} }
void lateInit() void lateInit() {
{
for (const auto &[index, account] : Core::App().domain().accounts()) { for (const auto &[index, account] : Core::App().domain().accounts()) {
if (const auto session = account->maybeSession()) { if (const auto session = account->maybeSession()) {
const auto id = session->userId().bare; const auto id = session->userId().bare;
@ -35,8 +33,7 @@ void lateInit()
} }
} }
void runOnce() void runOnce() {
{
if (!Core::App().domain().started()) { if (!Core::App().domain().started()) {
return; return;
} }
@ -72,17 +69,16 @@ void runOnce()
} }
} }
[[noreturn]] void loop() [[noreturn]] void loop() {
{
while (true) { while (true) {
runOnce(); runOnce();
std::this_thread::sleep_for(std::chrono::seconds(3)); std::this_thread::sleep_for(std::chrono::seconds(3));
} }
} }
void initialize() void initialize() {
{
std::thread t(loop); std::thread t(loop);
t.detach(); t.detach();
} }
} }

View file

@ -8,8 +8,7 @@
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
namespace AyuWorker namespace AyuWorker {
{
void markAsOnline(not_null<Main::Session *> session); void markAsOnline(not_null<Main::Session *> session);
void initialize(); void initialize();

View file

@ -93,25 +93,21 @@ auto storage = make_storage("./tdata/ayudata.db",
) )
); );
namespace AyuDatabase namespace AyuDatabase {
{
void initialize() void initialize() {
{
// move to `tdata` from legacy version // move to `tdata` from legacy version
if (std::filesystem::exists("ayugram.db")) { if (std::filesystem::exists("ayugram.db")) {
try { try {
std::filesystem::rename("ayugram.db", "./tdata/ayudata.db"); std::filesystem::rename("ayugram.db", "./tdata/ayudata.db");
} } catch (std::filesystem::filesystem_error &e) {
catch (std::filesystem::filesystem_error &e) {
LOG(("Failed to move database: %1").arg(e.what())); LOG(("Failed to move database: %1").arg(e.what()));
} }
} }
try { try {
storage.sync_schema(); storage.sync_schema();
} } catch (...) {
catch (...) {
auto time = base::unixtime::now(); auto time = base::unixtime::now();
LOG(("Failed to sync database schema")); LOG(("Failed to sync database schema"));
@ -138,31 +134,28 @@ void initialize()
storage.commit(); storage.commit();
} }
void addEditedMessage(const EditedMessage &message) void addEditedMessage(const EditedMessage &message) {
{
storage.begin_transaction(); storage.begin_transaction();
storage.insert(message); storage.insert(message);
storage.commit(); storage.commit();
} }
std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId) std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId) {
{
return storage.get_all<EditedMessage>( return storage.get_all<EditedMessage>(
where( where(
c(&EditedMessage::userId) == userId and c(&EditedMessage::userId) == userId and
c(&EditedMessage::dialogId) == dialogId and c(&EditedMessage::dialogId) == dialogId and
c(&EditedMessage::messageId) == messageId c(&EditedMessage::messageId) == messageId
) )
); );
} }
bool hasRevisions(ID userId, ID dialogId, ID messageId) bool hasRevisions(ID userId, ID dialogId, ID messageId) {
{
return storage.count<EditedMessage>( return storage.count<EditedMessage>(
where( where(
c(&EditedMessage::userId) == userId and c(&EditedMessage::userId) == userId and
c(&EditedMessage::dialogId) == dialogId and c(&EditedMessage::dialogId) == dialogId and
c(&EditedMessage::messageId) == messageId c(&EditedMessage::messageId) == messageId
) )
) > 0; ) > 0;
} }

View file

@ -10,8 +10,7 @@
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
namespace AyuDatabase namespace AyuDatabase {
{
void initialize(); void initialize();

View file

@ -8,30 +8,24 @@
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "data/data_cloud_themes.h"
#include "data/data_photo.h"
#include "data/data_session.h"
#include "history/history_inner_widget.h"
#include "history/view/media/history_view_media.h"
#include "main/main_session.h"
#include "data/data_peer.h"
#include "history/history.h"
#include "qguiapplication.h" #include "qguiapplication.h"
#include "ayu/ui/boxes/message_shot_box.h" #include "ayu/ui/boxes/message_shot_box.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "ui/chat/chat_theme.h" #include "data/data_cloud_themes.h"
#include "ui/painter.h" #include "data/data_peer.h"
#include "data/data_session.h"
#include "history/history_inner_widget.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
#include "history/view/history_view_message.h" #include "history/view/media/history_view_media.h"
#include "styles/style_boxes.h" #include "main/main_session.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_ayu_styles.h" #include "ui/painter.h"
#include "ui/layers/box_content.h" #include "ui/chat/chat_theme.h"
#include "ui/effects/path_shift_gradient.h" #include "ui/effects/path_shift_gradient.h"
#include "ui/layers/box_content.h"
namespace AyuFeatures::MessageShot namespace AyuFeatures::MessageShot {
{
ShotConfig *config; ShotConfig *config;
@ -49,78 +43,64 @@ bool choosingTheme = false;
rpl::event_stream<Data::CloudTheme> themeChosenStream; rpl::event_stream<Data::CloudTheme> themeChosenStream;
rpl::event_stream<style::palette> paletteChosenStream; rpl::event_stream<style::palette> paletteChosenStream;
void setShotConfig(ShotConfig &config) void setShotConfig(ShotConfig &config) {
{
MessageShot::config = &config; MessageShot::config = &config;
} }
void resetShotConfig() void resetShotConfig() {
{
config = nullptr; config = nullptr;
} }
ShotConfig getShotConfig() ShotConfig getShotConfig() {
{
return *config; return *config;
} }
void setDefaultSelected(const Window::Theme::EmbeddedType type) void setDefaultSelected(const Window::Theme::EmbeddedType type) {
{
resetCustomSelected(); resetCustomSelected();
defaultSelected = type; defaultSelected = type;
} }
Window::Theme::EmbeddedType getSelectedFromDefault() Window::Theme::EmbeddedType getSelectedFromDefault() {
{
return defaultSelected; return defaultSelected;
} }
void setDefaultSelectedColor(const QColor color) void setDefaultSelectedColor(const QColor color) {
{
resetCustomSelected(); resetCustomSelected();
defaultSelectedColor = color; defaultSelectedColor = color;
} }
std::optional<QColor> getSelectedColorFromDefault() std::optional<QColor> getSelectedColorFromDefault() {
{
return defaultSelectedColor; return defaultSelectedColor;
} }
void setCustomSelected(const Data::CloudTheme theme) void setCustomSelected(const Data::CloudTheme theme) {
{
resetDefaultSelected(); resetDefaultSelected();
customSelected = theme; customSelected = theme;
} }
std::optional<Data::CloudTheme> getSelectedFromCustom() std::optional<Data::CloudTheme> getSelectedFromCustom() {
{
return customSelected; return customSelected;
} }
void resetDefaultSelected() void resetDefaultSelected() {
{
defaultSelected = Window::Theme::EmbeddedType(-1); defaultSelected = Window::Theme::EmbeddedType(-1);
resetDefaultSelectedStream.fire({}); resetDefaultSelectedStream.fire({});
} }
void resetCustomSelected() void resetCustomSelected() {
{
customSelected = std::nullopt; customSelected = std::nullopt;
resetCustomSelectedStream.fire({}); resetCustomSelectedStream.fire({});
} }
rpl::producer<> resetDefaultSelectedEvents() rpl::producer<> resetDefaultSelectedEvents() {
{
return resetDefaultSelectedStream.events(); return resetDefaultSelectedStream.events();
} }
rpl::producer<> resetCustomSelectedEvents() rpl::producer<> resetCustomSelectedEvents() {
{
return resetCustomSelectedStream.events(); return resetCustomSelectedStream.events();
} }
bool ignoreRender(RenderPart part) bool ignoreRender(RenderPart part) {
{
if (!config) { if (!config) {
return false; return false;
} }
@ -133,39 +113,32 @@ bool ignoreRender(RenderPart part)
(part == RenderPart::Reactions && ignoreReactions)); (part == RenderPart::Reactions && ignoreReactions));
} }
bool isTakingShot() bool isTakingShot() {
{
return takingShot; return takingShot;
} }
bool setChoosingTheme(bool val) bool setChoosingTheme(bool val) {
{
choosingTheme = val; choosingTheme = val;
return choosingTheme; return choosingTheme;
} }
bool isChoosingTheme() bool isChoosingTheme() {
{
return choosingTheme; return choosingTheme;
} }
rpl::producer<Data::CloudTheme> themeChosen() rpl::producer<Data::CloudTheme> themeChosen() {
{
return themeChosenStream.events(); return themeChosenStream.events();
} }
void setTheme(Data::CloudTheme theme) void setTheme(Data::CloudTheme theme) {
{
themeChosenStream.fire(std::move(theme)); themeChosenStream.fire(std::move(theme));
} }
void setPalette(style::palette &palette) void setPalette(style::palette &palette) {
{
paletteChosenStream.fire(std::move(palette)); paletteChosenStream.fire(std::move(palette));
} }
rpl::producer<style::palette> paletteChosen() rpl::producer<style::palette> paletteChosen() {
{
return paletteChosenStream.events(); return paletteChosenStream.events();
} }
@ -192,33 +165,27 @@ MessageShotDelegate::MessageShotDelegate(
not_null<Ui::ChatStyle *> st, not_null<Ui::ChatStyle *> st,
Fn<void()> update) Fn<void()> update)
: _parent(parent) : _parent(parent)
, _pathGradient(HistoryView::MakePathShiftGradient(st, update)) , _pathGradient(HistoryView::MakePathShiftGradient(st, update)) {
{
} }
bool MessageShotDelegate::elementAnimationsPaused() bool MessageShotDelegate::elementAnimationsPaused() {
{
return _parent->window()->isActiveWindow(); return _parent->window()->isActiveWindow();
} }
auto MessageShotDelegate::elementPathShiftGradient() auto MessageShotDelegate::elementPathShiftGradient()
-> not_null<Ui::PathShiftGradient *> -> not_null<Ui::PathShiftGradient *> {
{
return _pathGradient.get(); return _pathGradient.get();
} }
HistoryView::Context MessageShotDelegate::elementContext() HistoryView::Context MessageShotDelegate::elementContext() {
{
return HistoryView::Context::AdminLog; return HistoryView::Context::AdminLog;
} }
bool MessageShotDelegate::elementIsChatWide() bool MessageShotDelegate::elementIsChatWide() {
{
return true; return true;
} }
QImage removePadding(const QImage &original) QImage removePadding(const QImage &original) {
{
if (original.isNull()) { if (original.isNull()) {
return {}; return {};
} }
@ -248,8 +215,7 @@ QImage removePadding(const QImage &original)
return original.copy(bounds); return original.copy(bounds);
} }
QImage addPadding(const QImage &original, int padding) QImage addPadding(const QImage &original, int padding) {
{
if (original.isNull()) { if (original.isNull()) {
return {}; return {};
} }
@ -268,8 +234,7 @@ QImage addPadding(const QImage &original, int padding)
return paddedImage; return paddedImage;
} }
QImage Make(not_null<QWidget *> box, const ShotConfig &config) QImage Make(not_null<QWidget *> box, const ShotConfig &config) {
{
const auto controller = config.controller; const auto controller = config.controller;
const auto st = config.st; const auto st = config.st;
const auto messages = config.messages; const auto messages = config.messages;
@ -281,11 +246,11 @@ QImage Make(not_null<QWidget *> box, const ShotConfig &config)
takingShot = true; takingShot = true;
auto delegate = std::make_unique<MessageShotDelegate>(box, auto delegate = std::make_unique<MessageShotDelegate>(box,
st.get(), st.get(),
[=] [=]
{ {
box->update(); box->update();
}); });
std::unordered_map<not_null<HistoryItem *>, std::shared_ptr<HistoryView::Element>> createdViews; std::unordered_map<not_null<HistoryItem *>, std::shared_ptr<HistoryView::Element>> createdViews;
createdViews.reserve(messages.size()); createdViews.reserve(messages.size());
@ -306,8 +271,7 @@ QImage Make(not_null<QWidget *> box, const ShotConfig &config)
const auto nextMsg = messages[i].get(); const auto nextMsg = messages[i].get();
if (getView(nextMsg)->isHidden()) { if (getView(nextMsg)->isHidden()) {
getView(nextMsg)->setDisplayDate(false); getView(nextMsg)->setDisplayDate(false);
} } else {
else {
const auto viewDate = getView(currentMsg)->dateTime(); const auto viewDate = getView(currentMsg)->dateTime();
const auto nextDate = getView(nextMsg)->dateTime(); const auto nextDate = getView(nextMsg)->dateTime();
getView(nextMsg)->setDisplayDate(nextDate.date() != viewDate.date()); getView(nextMsg)->setDisplayDate(nextDate.date() != viewDate.date());
@ -319,8 +283,7 @@ QImage Make(not_null<QWidget *> box, const ShotConfig &config)
} }
getView(messages[messages.size() - 1])->setAttachToNext(false); getView(messages[messages.size() - 1])->setAttachToNext(false);
} } else {
else {
getView(messages[0])->setAttachToPrevious(false); getView(messages[0])->setAttachToPrevious(false);
getView(messages[0])->setAttachToNext(false); getView(messages[0])->setAttachToNext(false);
} }
@ -394,8 +357,7 @@ QImage Make(not_null<QWidget *> box, const ShotConfig &config)
return overlay; return overlay;
} }
void Wrapper(not_null<HistoryView::ListWidget *> widget) void Wrapper(not_null<HistoryView::ListWidget *> widget) {
{
const auto items = widget->getSelectedIds(); const auto items = widget->getSelectedIds();
if (items.empty()) { if (items.empty()) {
return; return;

View file

@ -6,17 +6,18 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "window/window_session_controller.h"
#include "history/view/history_view_list_widget.h" #include "history/view/history_view_list_widget.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h" #include "window/themes/window_themes_embedded.h"
namespace AyuFeatures::MessageShot { namespace AyuFeatures::MessageShot {
struct ShotConfig { struct ShotConfig
not_null<Window::SessionController*> controller; {
not_null<Window::SessionController *> controller;
std::shared_ptr<Ui::ChatStyle> st; std::shared_ptr<Ui::ChatStyle> st;
std::vector<not_null<HistoryItem*>> messages; std::vector<not_null<HistoryItem *>> messages;
bool showDate; bool showDate;
bool showReactions; bool showReactions;
@ -28,7 +29,7 @@ enum RenderPart
Reactions, Reactions,
}; };
void setShotConfig(ShotConfig& config); void setShotConfig(ShotConfig &config);
void resetShotConfig(); void resetShotConfig();
ShotConfig getShotConfig(); ShotConfig getShotConfig();
@ -59,11 +60,11 @@ bool setChoosingTheme(bool val);
void setTheme(Data::CloudTheme theme); void setTheme(Data::CloudTheme theme);
rpl::producer<Data::CloudTheme> themeChosen(); rpl::producer<Data::CloudTheme> themeChosen();
void setPalette(style::palette& palette); void setPalette(style::palette &palette);
rpl::producer<style::palette> paletteChosen(); rpl::producer<style::palette> paletteChosen();
QImage Make(not_null<QWidget*> box, const ShotConfig &config); QImage Make(not_null<QWidget *> box, const ShotConfig &config);
void Wrapper(not_null<HistoryView::ListWidget*> widget); void Wrapper(not_null<HistoryView::ListWidget *> widget);
} }

View file

@ -6,10 +6,7 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "ui/rp_widget.h" namespace AyuFeatures::StreamerMode {
namespace AyuFeatures::StreamerMode
{
bool isEnabled(); bool isEnabled();
void enable(); void enable();

View file

@ -12,40 +12,34 @@
#include "core/application.h" #include "core/application.h"
#include "window/window_controller.h" #include "window/window_controller.h"
namespace AyuFeatures::StreamerMode namespace AyuFeatures::StreamerMode {
{
bool isEnabledVal; bool isEnabledVal;
bool isEnabled() bool isEnabled() {
{
return isEnabledVal; return isEnabledVal;
} }
void enable() void enable() {
{
auto handle = Core::App().activeWindow()->widget()->psHwnd(); auto handle = Core::App().activeWindow()->widget()->psHwnd();
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE); SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
isEnabledVal = true; isEnabledVal = true;
} }
void disable() void disable() {
{
auto handle = Core::App().activeWindow()->widget()->psHwnd(); auto handle = Core::App().activeWindow()->widget()->psHwnd();
SetWindowDisplayAffinity(handle, WDA_NONE); SetWindowDisplayAffinity(handle, WDA_NONE);
isEnabledVal = false; isEnabledVal = false;
} }
void hideWidgetWindow(QWidget *widget) void hideWidgetWindow(QWidget *widget) {
{
auto handle = reinterpret_cast<HWND>(widget->window()->winId()); auto handle = reinterpret_cast<HWND>(widget->window()->winId());
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE); SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
} }
void showWidgetWindow(QWidget *widget) void showWidgetWindow(QWidget *widget) {
{
auto handle = reinterpret_cast<HWND>(widget->window()->winId()); auto handle = reinterpret_cast<HWND>(widget->window()->winId());
SetWindowDisplayAffinity(handle, WDA_NONE); SetWindowDisplayAffinity(handle, WDA_NONE);
} }

View file

@ -1,368 +0,0 @@
/*
MIT License
Copyright (c) 2021 Yanjie He
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <vector>
namespace bit_converter {
using std::vector;
/**
* @brief Convert the specified 16-bit signed integer value to bytes.
*/
template <typename OutputIt>
inline OutputIt i16_to_bytes(int16_t value, bool is_big_endian,
OutputIt output_it) {
if (is_big_endian) {
*output_it = static_cast<uint8_t>(value >> 8);
output_it++;
*output_it = static_cast<uint8_t>(value & 0xFF);
output_it++;
} else {
*output_it = static_cast<uint8_t>(value & 0xFF);
output_it++;
*output_it = static_cast<uint8_t>(value >> 8);
output_it++;
}
return output_it;
}
/**
* @brief Convert the specified 16-bit unsigned integer value to bytes.
*/
template <typename OutputIt>
inline OutputIt u16_to_bytes(uint16_t value, bool is_big_endian,
OutputIt output_it) {
return i16_to_bytes(static_cast<uint16_t>(value), is_big_endian, output_it);
}
/**
* @brief Convert the specified 32-bit signed integer value to bytes.
*/
template <typename OutputIt>
inline OutputIt i32_to_bytes(int32_t value, bool is_big_endian,
OutputIt output_it) {
if (is_big_endian) {
for (int i = 0; i < static_cast<int>(sizeof(int32_t)); i++) {
*output_it = static_cast<uint8_t>((value >> (24 - i * 8)) & 0xFF);
output_it++;
}
} else {
for (int i = static_cast<int>(sizeof(int32_t)) - 1; i >= 0; i--) {
*output_it = static_cast<uint8_t>((value >> (24 - i * 8)) & 0xFF);
output_it++;
}
}
return output_it;
}
/**
* @brief Convert the specified 32-bit unsigned integer value to bytes.
*/
template <typename OutputIt>
inline OutputIt u32_to_bytes(uint32_t value, bool is_big_endian,
OutputIt output_it) {
return i32_to_bytes(static_cast<int32_t>(value), is_big_endian, output_it);
}
/**
* @brief Convert the specified 64-bit signed integer value to bytes.
*/
template <typename OutputIt>
inline OutputIt i64_to_bytes(int64_t value, bool is_big_endian,
OutputIt output_it) {
if (is_big_endian) {
for (int i = 0; i < static_cast<int>(sizeof(int64_t)); i++) {
*output_it = static_cast<uint8_t>((value >> (56 - i * 8)) & 0xFF);
output_it++;
}
} else {
for (int i = static_cast<int>(sizeof(int64_t)) - 1; i >= 0; i--) {
*output_it = static_cast<uint8_t>((value >> (56 - i * 8)) & 0xFF);
output_it++;
}
}
return output_it;
}
/**
* @brief Convert the specified 64-bit unsigned integer value to bytes.
*/
template <typename OutputIt>
inline OutputIt u64_to_bytes(uint64_t value, bool is_big_endian,
OutputIt output_it) {
return i64_to_bytes(static_cast<int64_t>(value), is_big_endian, output_it);
}
template <typename OutputIt>
inline OutputIt create_bytes_from_bits(const vector<bool> &bits,
OutputIt output_it) {
for (int i = 0; i < static_cast<int>(bits.size() / 8); i++) {
uint8_t b = 0;
for (int j = 0; j < 8; j++) {
b = b + (bits[i * 8 + j] << j);
}
*output_it = b;
output_it++;
}
return output_it;
}
/**
* @brief Convert the specified single-precision floating-point value to bytes.
*/
template <typename OutputIt>
inline OutputIt f32_to_bytes(float_t value, bool is_big_endian,
OutputIt output_it) {
vector<bool> bits;
bits.reserve(sizeof(float_t) * 8);
bits.push_back(value < 0);
int exponent;
float_t mantissa = std::frexp(value, &exponent);
exponent = (exponent - 1) + 127;
for (int i = 0; i < 8; i++) {
bits.push_back(exponent % 2);
exponent = exponent / 2;
}
std::reverse(bits.begin() + 1, bits.begin() + 1 + 8);
mantissa = mantissa * 2 - 1;
for (int i = 0; i < 23; i++) {
mantissa = mantissa * 2;
if (mantissa >= 1.0) {
mantissa = mantissa - 1.0;
bits.push_back(true);
} else {
bits.push_back(false);
}
}
if (is_big_endian) {
return create_bytes_from_bits(bits, output_it);
} else {
std::reverse(bits.begin(), bits.end());
return create_bytes_from_bits(bits, output_it);
}
}
/**
* @brief Convert the specified double-precision floating-point value to bytes.
*/
template <typename OutputIt>
inline OutputIt f64_to_bytes(double_t value, bool is_big_endian,
OutputIt output_it) {
vector<bool> bits;
bits.reserve(sizeof(double_t) * 8);
bits.push_back(value < 0);
int exponent;
double_t mantissa = std::frexp(value, &exponent);
exponent = (exponent - 1) + 1023;
for (int i = 0; i < 11; i++) {
bits.push_back(exponent % 2);
exponent = exponent / 2;
}
std::reverse(bits.begin() + 1, bits.begin() + 1 + 11);
mantissa = mantissa * 2 - 1;
for (int i = 0; i < 52; i++) {
mantissa = mantissa * 2;
if (mantissa >= 1.0) {
mantissa = mantissa - 1.0;
bits.push_back(true);
} else {
bits.push_back(false);
}
}
if (is_big_endian) {
return create_bytes_from_bits(bits, output_it);
} else {
std::reverse(bits.begin(), bits.end());
return create_bytes_from_bits(bits, output_it);
}
}
/**
* @brief Returns a 16-bit signed integer converted from two bytes at a
* specified position in a byte sequence.
*/
template <typename InputIt>
inline int16_t bytes_to_i16(InputIt input_it, bool is_big_endian) {
if (is_big_endian) {
int16_t result = *input_it;
input_it++;
result = (result << 8) + *input_it;
input_it++;
return result;
} else {
int16_t result = *input_it;
input_it++;
result = result + (static_cast<int16_t>(*input_it) << 8);
input_it++;
return result;
}
}
/**
* @brief Returns a 16-bit unsigned integer converted from two bytes at a
* specified position in a byte sequence.
*/
template <typename InputIt>
inline uint16_t bytes_to_u16(InputIt input_it, bool is_big_endian) {
return static_cast<uint16_t>(bytes_to_i16(input_it, is_big_endian));
}
/**
* @brief Returns a 32-bit signed integer converted from four bytes at a
* specified position in a byte sequence.
*/
template <typename InputIt>
inline int32_t bytes_to_i32(InputIt input_it, bool is_big_endian) {
int32_t result = 0;
if (is_big_endian) {
for (int i = 0; i < static_cast<int>(sizeof(int32_t)); i++) {
result = result + ((*input_it) << (8 * (4 - 1 - i)));
input_it++;
}
return result;
} else {
for (int i = 0; i < static_cast<int>(sizeof(int32_t)); i++) {
result = result + ((*input_it) << (8 * i));
input_it++;
}
return result;
}
}
/**
* @brief Returns a 32-bit unsigned integer converted from four bytes at a
* specified position in a byte sequence.
*/
template <typename InputIt>
inline uint32_t bytes_to_u32(InputIt input_it, bool is_big_endian) {
return static_cast<uint32_t>(bytes_to_i32(input_it, is_big_endian));
}
/**
* @brief Returns a 64-bit signed integer converted from eight bytes at a
* specified position in a byte sequence.
*/
template <typename InputIt>
inline int64_t bytes_to_i64(InputIt input_it, bool is_big_endian) {
int64_t result = 0;
if (is_big_endian) {
for (int i = 0; i < static_cast<int>(sizeof(int64_t)); i++) {
result = result + (static_cast<int64_t>(*input_it) << (8 * (8 - 1 - i)));
input_it++;
}
return result;
} else {
for (int i = 0; i < static_cast<int>(sizeof(int64_t)); i++) {
result = result + (static_cast<int64_t>(*input_it) << (8 * i));
input_it++;
}
return result;
}
}
/**
* @brief Returns a 64-bit unsigned integer converted from eight bytes at a
* specified position in a byte sequence.
*/
template <typename InputIt>
inline uint64_t bytes_to_u64(InputIt input_it, bool is_big_endian) {
return static_cast<uint64_t>(input_it, is_big_endian);
}
/**
* @brief Returns a single-precision floating-point number converted from four
* bytes at a specified position in a byte sequence.
*/
template <typename InputIt>
inline float_t bytes_to_f32(InputIt input_it, bool is_big_endian) {
vector<bool> bits;
bits.reserve(sizeof(float_t) * 8);
for (int i = 0; i < static_cast<int>(sizeof(float_t)); i++) {
uint8_t b = *input_it;
input_it++;
for (int j = 0; j < 8; j++) {
bits.push_back(b % 2);
b = b / 2;
}
}
if (!is_big_endian) {
std::reverse(bits.begin(), bits.end());
}
int sign = bits[0] ? (-1) : (+1);
int exponent = 0;
for (int i = 0; i < 8; i++) {
exponent = exponent + bits[1 + i] * (1 << (8 - 1 - i));
}
exponent = exponent - 127;
float_t mantissa = 1.0;
float_t cur = 0.5;
for (int i = 0; i < 23; i++) {
mantissa = mantissa + bits[1 + 8 + i] * cur;
cur = cur / 2;
}
return sign * std::ldexp(mantissa, exponent);
}
/**
* @brief Returns a double-precision floating-point number converted from eight
* bytes at a specified position in a byte sequence.
*/
template <typename InputIt>
inline double_t bytes_to_f64(InputIt input_it, bool is_big_endian) {
vector<bool> bits;
bits.reserve(sizeof(double_t) * 8);
for (int i = 0; i < static_cast<int>(sizeof(double_t)); i++) {
uint8_t b = *input_it;
input_it++;
for (int j = 0; j < 8; j++) {
bits.push_back(b % 2);
b = b / 2;
}
}
if (!is_big_endian) {
std::reverse(bits.begin(), bits.end());
}
int sign = bits[0] ? (-1) : (+1);
int exponent = 0;
for (int i = 0; i < 11; i++) {
exponent = exponent + bits[1 + i] * (1 << (11 - 1 - i));
}
exponent = exponent - 1023;
double_t mantissa = 1.0;
double_t cur = 0.5;
for (int i = 0; i < 52; i++) {
mantissa = mantissa + bits[1 + 11 + i] * cur;
cur = cur / 2;
}
return sign * std::ldexp(mantissa, exponent);
}
}; // namespace bit_converter

View file

@ -1,856 +0,0 @@
///////////////////////////////////////////////////////////
/// Copyright 2019 Alexy Pellegrini
///
/// Permission is hereby granted, free of charge,
/// to any person obtaining a copy of this software
/// and associated documentation files (the "Software"),
/// to deal in the Software without restriction,
/// including without limitation the rights to use,
/// copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit
/// persons to whom the Software is furnished to do so,
/// subject to the following conditions:
///
/// The above copyright notice and this permission notice
/// shall be included in all copies or substantial portions
/// of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
/// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
/// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
/// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
/// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
/// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
/// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
/// OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////////////////////
#ifndef NOT_ENOUGH_STANDARDS_PIPE
#define NOT_ENOUGH_STANDARDS_PIPE
#if defined(_WIN32)
#define NES_WIN32_PIPE
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#elif defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
#define NES_POSIX_PIPE
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#else
#error "Not enough standards does not support this environment."
#endif
#include <vector>
#include <algorithm>
#include <streambuf>
#include <istream>
#include <ostream>
#include <memory>
#include <cassert>
#include <utility>
#if defined(NES_WIN32_PIPE)
namespace nes
{
inline constexpr const char pipe_root[] = "\\\\.\\pipe\\";
template<typename CharT, typename Traits>
class basic_pipe_istream;
template<typename CharT, typename Traits>
class basic_pipe_ostream;
template<typename CharT = char, typename Traits = std::char_traits<CharT>>
std::pair<basic_pipe_istream<CharT, Traits>, basic_pipe_ostream<CharT, Traits>> make_anonymous_pipe();
template<typename CharT, typename Traits = std::char_traits<CharT>>
class basic_pipe_streambuf : public std::basic_streambuf<CharT, Traits>
{
private:
using parent_type = std::basic_streambuf<CharT, Traits>;
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename Traits::int_type;
using pos_type = typename Traits::pos_type;
using off_type = typename Traits::off_type;
public:
static constexpr std::size_t buf_size{4096};
public:
basic_pipe_streambuf() = default;
explicit basic_pipe_streambuf(const std::string& name, std::ios_base::openmode mode)
{
open(name, mode);
}
virtual ~basic_pipe_streambuf()
{
close();
}
basic_pipe_streambuf(const basic_pipe_streambuf&) = delete;
basic_pipe_streambuf& operator=(const basic_pipe_streambuf&) = delete;
basic_pipe_streambuf(basic_pipe_streambuf&& other) noexcept
:parent_type{other}
,m_buffer{std::move(other.m_buffer)}
,m_handle{std::exchange(other.m_handle, INVALID_HANDLE_VALUE)}
,m_mode{std::exchange(other.m_mode, std::ios_base::openmode{})}
{
}
basic_pipe_streambuf& operator=(basic_pipe_streambuf&& other) noexcept
{
parent_type::operator=(other);
m_buffer = std::move(other.m_buffer);
m_handle = std::exchange(other.m_handle, m_handle);
m_mode = std::exchange(other.m_mode, m_mode);
return *this;
}
bool open(const std::string& name, std::ios_base::openmode mode)
{
assert(!((mode & std::ios_base::in) && (mode & std::ios_base::out)) && "nes::basic_pipe_streambuf::open called with mode = std::ios_base::in | std::ios_base::out.");
close();
const auto native_name{to_wide(pipe_root + name)};
DWORD native_mode{mode & std::ios_base::in ? GENERIC_READ : GENERIC_WRITE};
HANDLE handle = CreateFileW(std::data(native_name), native_mode, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if(handle == INVALID_HANDLE_VALUE)
{
if(GetLastError() == ERROR_FILE_NOT_FOUND)
{
native_mode = mode & std::ios_base::in ? PIPE_ACCESS_INBOUND : PIPE_ACCESS_OUTBOUND;
handle = CreateNamedPipeW(std::data(native_name), native_mode, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, buf_size, buf_size, 0, nullptr);
if(handle == INVALID_HANDLE_VALUE)
return false;
if(!ConnectNamedPipe(handle, nullptr))
{
CloseHandle(handle);
return false;
}
}
}
m_buffer.resize(buf_size);
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
m_handle = handle;
m_mode = mode;
return true;
}
bool is_open() const noexcept
{
return m_handle != INVALID_HANDLE_VALUE;
}
void close()
{
if(is_open())
{
sync();
m_mode = std::ios_base::openmode{};
CloseHandle(std::exchange(m_handle, INVALID_HANDLE_VALUE));
parent_type::setp(nullptr, nullptr);
parent_type::setg(nullptr, nullptr, nullptr);
}
}
private:
friend class process;
friend std::pair<basic_pipe_istream<char_type, traits_type>, basic_pipe_ostream<char_type, traits_type>> make_anonymous_pipe<char_type, traits_type>();
basic_pipe_streambuf(HANDLE handle, std::ios_base::openmode mode)
:m_handle{handle}
,m_mode{mode}
{
m_buffer.resize(buf_size);
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
}
protected:
virtual int sync() override
{
if(m_mode & std::ios_base::out)
{
const std::ptrdiff_t count{parent_type::pptr() - parent_type::pbase()};
DWORD written{};
if(!WriteFile(m_handle, reinterpret_cast<const CHAR*>(std::data(m_buffer)), static_cast<DWORD>(count)* sizeof(char_type), &written, nullptr))
return -1;
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
}
return 0;
}
virtual int_type overflow(int_type c = traits_type::eof()) override
{
assert(m_mode & std::ios_base::out && "Write operation on a read only pipe.");
if(traits_type::eq_int_type(c, traits_type::eof()))
{
DWORD written{};
if(!WriteFile(m_handle, reinterpret_cast<const CHAR*>(std::data(m_buffer)), static_cast<DWORD>(buf_size) * sizeof(char_type), &written, nullptr))
return traits_type::eof();
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
}
else
{
*parent_type::pptr() = traits_type::to_char_type(c);
parent_type::pbump(1);
}
return traits_type::not_eof(c);
}
virtual std::streamsize xsputn(const char_type* s, std::streamsize count) override
{
assert(m_mode & std::ios_base::out && "Write operation on a read only pipe.");
DWORD written{};
if(!WriteFile(m_handle, reinterpret_cast<const CHAR*>(s), static_cast<DWORD>(count) * sizeof(char_type), &written, nullptr))
return 0;
return static_cast<std::streamsize>(written);
}
virtual int_type underflow() override
{
assert(m_mode & std::ios_base::in && "Read operation on a write only pipe.");
if(parent_type::gptr() == parent_type::egptr())
{
DWORD readed{};
if(!ReadFile(m_handle, reinterpret_cast<CHAR*>(std::data(m_buffer)), static_cast<DWORD>(buf_size * sizeof(char_type)), &readed, nullptr) || readed == 0)
return traits_type::eof();
parent_type::setg(std::data(m_buffer), std::data(m_buffer), std::data(m_buffer) + (readed / sizeof(char_type)));
}
return traits_type::to_int_type(*parent_type::gptr());
}
virtual std::streamsize xsgetn(char_type* s, std::streamsize count) override
{
assert(m_mode & std::ios_base::in && "Read operation on a write only pipe.");
DWORD readed{};
if(!ReadFile(m_handle, reinterpret_cast<CHAR*>(s), static_cast<DWORD>(count) * sizeof(char_type), &readed, nullptr))
return 0;
return static_cast<std::streamsize>(readed / sizeof(char_type));
}
private:
std::wstring to_wide(std::string path)
{
assert(std::size(path) < 0x7FFFFFFFu && "Wrong path.");
if(std::empty(path))
return {};
std::transform(std::begin(path), std::end(path), std::begin(path), [](char c){return c == '/' ? '\\' : c;});
std::wstring out_path{};
out_path.resize(static_cast<std::size_t>(MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, std::data(path), static_cast<int>(std::size(path)), nullptr, 0)));
if (!MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, std::data(path), static_cast<int>(std::size(path)), std::data(out_path), static_cast<int>(std::size(out_path))))
throw std::runtime_error{"Failed to convert the path to wide."};
return out_path;
}
private:
std::vector<CharT> m_buffer{};
HANDLE m_handle{INVALID_HANDLE_VALUE};
std::ios_base::openmode m_mode{};
};
template<typename CharT, typename Traits = std::char_traits<CharT>>
class basic_pipe_istream : public std::basic_istream<CharT, Traits>
{
private:
using parent_type = std::basic_istream<CharT, Traits>;
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename Traits::int_type;
using pos_type = typename Traits::pos_type;
using off_type = typename Traits::off_type;
public:
basic_pipe_istream() = default;
explicit basic_pipe_istream(const std::string& name, std::ios_base::openmode mode = std::ios_base::in)
:parent_type{nullptr}
{
parent_type::rdbuf(m_buffer.get());
open(name, mode);
}
virtual ~basic_pipe_istream() = default;
basic_pipe_istream(const basic_pipe_istream&) = delete;
basic_pipe_istream& operator=(const basic_pipe_istream&) = delete;
basic_pipe_istream(basic_pipe_istream&& other) noexcept
:parent_type{std::move(other)}
{
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
}
basic_pipe_istream& operator=(basic_pipe_istream&& other) noexcept
{
parent_type::operator=(std::move(other));
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
return *this;
}
void open(const std::string& name, std::ios_base::openmode mode = std::ios_base::in)
{
m_buffer->open(name, mode);
parent_type::clear(m_buffer->is_open() ? std::ios_base::goodbit : std::ios_base::failbit);
}
bool is_open() const noexcept
{
return m_buffer->is_open();
}
void close()
{
m_buffer->close();
}
basic_pipe_streambuf<char_type, traits_type>* rdbuf() const noexcept
{
return m_buffer.get();
}
private:
friend class process;
friend std::pair<basic_pipe_istream<char_type, traits_type>, basic_pipe_ostream<char_type, traits_type>> make_anonymous_pipe<char_type, traits_type>();
basic_pipe_istream(basic_pipe_streambuf<char_type, traits_type> buffer)
:parent_type{nullptr}
,m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>(std::move(buffer))}
{
parent_type::rdbuf(m_buffer.get());
}
private:
std::unique_ptr<basic_pipe_streambuf<char_type, traits_type>> m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>()};
};
template<typename CharT, typename Traits = std::char_traits<CharT>>
class basic_pipe_ostream : public std::basic_ostream<CharT, Traits>
{
private:
using parent_type = std::basic_ostream<CharT, Traits>;
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename Traits::int_type;
using pos_type = typename Traits::pos_type;
using off_type = typename Traits::off_type;
public:
basic_pipe_ostream() = default;
explicit basic_pipe_ostream(const std::string& name, std::ios_base::openmode mode = std::ios_base::out)
:parent_type{nullptr}
{
parent_type::rdbuf(m_buffer.get());
open(name, mode);
}
virtual ~basic_pipe_ostream() = default;
basic_pipe_ostream(const basic_pipe_ostream&) = delete;
basic_pipe_ostream& operator=(const basic_pipe_ostream&) = delete;
basic_pipe_ostream(basic_pipe_ostream&& other) noexcept
:parent_type{std::move(other)}
{
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
}
basic_pipe_ostream& operator=(basic_pipe_ostream&& other) noexcept
{
parent_type::operator=(std::move(other));
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
return *this;
}
void open(const std::string& name, std::ios_base::openmode mode = std::ios_base::out)
{
m_buffer->open(name, mode);
parent_type::clear(m_buffer->is_open() ? std::ios_base::goodbit : std::ios_base::failbit);
}
bool is_open() const noexcept
{
return m_buffer->is_open();
}
void close()
{
m_buffer->close();
}
basic_pipe_streambuf<char_type, traits_type>* rdbuf() const noexcept
{
return m_buffer.get();
}
private:
friend class process;
friend std::pair<basic_pipe_istream<char_type, traits_type>, basic_pipe_ostream<char_type, traits_type>> make_anonymous_pipe<char_type, traits_type>();
basic_pipe_ostream(basic_pipe_streambuf<char_type, traits_type> buffer)
:parent_type{nullptr}
,m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>(std::move(buffer))}
{
parent_type::rdbuf(m_buffer.get());
}
private:
std::unique_ptr<basic_pipe_streambuf<char_type, traits_type>> m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>()};
};
template<typename CharT, typename Traits>
std::pair<basic_pipe_istream<CharT, Traits>, basic_pipe_ostream<CharT, Traits>> make_anonymous_pipe()
{
HANDLE input{};
HANDLE output{};
if(!CreatePipe(&input, &output, nullptr, 0))
throw std::runtime_error{"Failed to create pipe"};
return std::make_pair(basic_pipe_istream<CharT, Traits>{basic_pipe_streambuf<CharT, Traits>{input, std::ios_base::in}},
basic_pipe_ostream<CharT, Traits>{basic_pipe_streambuf<CharT, Traits>{output, std::ios_base::out}});
}
using pipe_streambuf = basic_pipe_streambuf<char>;
using pipe_istream = basic_pipe_istream<char>;
using pipe_ostream = basic_pipe_ostream<char>;
}
#elif defined(NES_POSIX_PIPE)
namespace nes
{
inline constexpr const char pipe_root[] = "/tmp/";
template<typename CharT, typename Traits>
class basic_pipe_istream;
template<typename CharT, typename Traits>
class basic_pipe_ostream;
template<typename CharT = char, typename Traits = std::char_traits<CharT>>
std::pair<basic_pipe_istream<CharT, Traits>, basic_pipe_ostream<CharT, Traits>> make_anonymous_pipe();
template<typename CharT, typename Traits = std::char_traits<CharT>>
class basic_pipe_streambuf : public std::basic_streambuf<CharT, Traits>
{
private:
using parent_type = std::basic_streambuf<CharT, Traits>;
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename Traits::int_type;
using pos_type = typename Traits::pos_type;
using off_type = typename Traits::off_type;
public:
static constexpr std::size_t buf_size{1024};
public:
basic_pipe_streambuf() = default;
explicit basic_pipe_streambuf(const std::string& name, std::ios_base::openmode mode)
:parent_type{nullptr}
{
open(name, mode);
}
virtual ~basic_pipe_streambuf()
{
close();
}
basic_pipe_streambuf(const basic_pipe_streambuf&) = delete;
basic_pipe_streambuf& operator=(const basic_pipe_streambuf&) = delete;
basic_pipe_streambuf(basic_pipe_streambuf&& other) noexcept
:parent_type{std::move(other)}
,m_buffer{std::move(other.m_buffer)}
,m_handle{std::exchange(other.m_handle, 0)}
,m_mode{std::exchange(other.m_mode, std::ios_base::openmode{})}
{
}
basic_pipe_streambuf& operator=(basic_pipe_streambuf&& other) noexcept
{
parent_type::operator=(std::move(other));
m_buffer = std::move(other.m_buffer);
m_handle = std::exchange(other.m_handle, m_handle);
m_mode = std::exchange(other.m_mode, m_mode);
return *this;
}
bool open(const std::string& name, std::ios_base::openmode mode)
{
assert(!((mode & std::ios_base::in) && (mode & std::ios_base::out)) && "nes::basic_pipe_streambuf::open called with mode = std::ios_base::in | std::ios_base::out.");
close();
const auto native_name{pipe_root + name};
if(mkfifo(std::data(native_name), 0660) != 0 && errno != EEXIST)
return false;
const int native_mode{mode & std::ios_base::in ? O_RDONLY : O_WRONLY};
int handle = ::open(std::data(native_name), native_mode);
if(handle < 0)
return false;
m_buffer.resize(buf_size);
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
m_handle = handle;
m_mode = mode;
return true;
}
bool is_open() const noexcept
{
return m_handle;
}
void close()
{
if(is_open())
{
sync();
m_mode = std::ios_base::openmode{};
::close(std::exchange(m_handle, 0));
parent_type::setp(nullptr, nullptr);
parent_type::setg(nullptr, nullptr, nullptr);
}
}
private:
friend class process;
friend std::pair<basic_pipe_istream<char_type, traits_type>, basic_pipe_ostream<char_type, traits_type>> make_anonymous_pipe<char_type, traits_type>();
basic_pipe_streambuf(int handle, std::ios_base::openmode mode)
:m_handle{handle}
,m_mode{mode}
{
m_buffer.resize(buf_size);
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
}
protected:
virtual int sync() override
{
if(m_mode & std::ios_base::out)
{
const std::ptrdiff_t count{parent_type::pptr() - parent_type::pbase()};
if(write(m_handle, reinterpret_cast<const char*>(std::data(m_buffer)), count * sizeof(char_type)) < 0)
return -1;
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
}
return 0;
}
virtual int_type overflow(int_type c = traits_type::eof()) override
{
assert(m_mode & std::ios_base::out && "Write operation on a read only pipe.");
if(traits_type::eq_int_type(c, traits_type::eof()))
{
if(write(m_handle, reinterpret_cast<const char*>(std::data(m_buffer)), std::size(m_buffer) * sizeof(char_type)))
return traits_type::eof();
parent_type::setp(std::data(m_buffer), std::data(m_buffer) + buf_size);
}
else
{
*parent_type::pptr() = traits_type::to_char_type(c);
parent_type::pbump(1);
}
return traits_type::not_eof(c);
}
virtual std::streamsize xsputn(const char_type* s, std::streamsize count) override
{
assert(m_mode & std::ios_base::out && "Write operation on a read only pipe.");
const auto written = write(m_handle, reinterpret_cast<const char*>(s), count * sizeof(char_type));
if(written < 0)
return 0;
return static_cast<std::streamsize>(written);
}
virtual int_type underflow() override
{
assert(m_mode & std::ios_base::in && "Read operation on a write only pipe.");
if(parent_type::gptr() == parent_type::egptr())
{
const auto readed = read(m_handle, reinterpret_cast<char*>(std::data(m_buffer)), buf_size * sizeof(char_type));
if(readed <= 0)
return traits_type::eof();
parent_type::setg(std::data(m_buffer), std::data(m_buffer), std::data(m_buffer) + (readed / sizeof(char_type)));
}
return traits_type::to_int_type(*parent_type::gptr());
}
virtual std::streamsize xsgetn(char_type* s, std::streamsize count) override
{
assert(m_mode & std::ios_base::in && "Read operation on a write only pipe.");
const auto readed = read(m_handle, reinterpret_cast<char*>(s), count * sizeof(char_type));
if(readed < 0)
return 0;
return static_cast<std::streamsize>(readed / sizeof(char_type));
}
private:
std::vector<CharT> m_buffer{};
int m_handle{};
std::ios_base::openmode m_mode{};
};
template<typename CharT, typename Traits = std::char_traits<CharT>>
class basic_pipe_istream : public std::basic_istream<CharT, Traits>
{
private:
using parent_type = std::basic_istream<CharT, Traits>;
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename Traits::int_type;
using pos_type = typename Traits::pos_type;
using off_type = typename Traits::off_type;
public:
basic_pipe_istream() = default;
explicit basic_pipe_istream(const std::string& name, std::ios_base::openmode mode = std::ios_base::in)
:parent_type{nullptr}
{
parent_type::rdbuf(m_buffer.get());
open(name, mode);
}
virtual ~basic_pipe_istream() = default;
basic_pipe_istream(const basic_pipe_istream&) = delete;
basic_pipe_istream& operator=(const basic_pipe_istream&) = delete;
basic_pipe_istream(basic_pipe_istream&& other) noexcept
:parent_type{std::move(other)}
{
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
}
basic_pipe_istream& operator=(basic_pipe_istream&& other) noexcept
{
parent_type::operator=(std::move(other));
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
return *this;
}
void open(const std::string& name, std::ios_base::openmode mode = std::ios_base::in)
{
m_buffer->open(name, mode);
parent_type::clear(m_buffer->is_open() ? std::ios_base::goodbit : std::ios_base::failbit);
}
bool is_open() const noexcept
{
return m_buffer->is_open();
}
void close()
{
m_buffer->close();
}
basic_pipe_streambuf<char_type, traits_type>* rdbuf() const noexcept
{
return m_buffer.get();
}
private:
friend class process;
friend std::pair<basic_pipe_istream<char_type, traits_type>, basic_pipe_ostream<char_type, traits_type>> make_anonymous_pipe<char_type, traits_type>();
basic_pipe_istream(basic_pipe_streambuf<char_type, traits_type> buffer)
:parent_type{nullptr}
,m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>(std::move(buffer))}
{
parent_type::rdbuf(m_buffer.get());
}
private:
std::unique_ptr<basic_pipe_streambuf<char_type, traits_type>> m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>()};
};
template<typename CharT, typename Traits = std::char_traits<CharT>>
class basic_pipe_ostream : public std::basic_ostream<CharT, Traits>
{
private:
using parent_type = std::basic_ostream<CharT, Traits>;
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename Traits::int_type;
using pos_type = typename Traits::pos_type;
using off_type = typename Traits::off_type;
public:
basic_pipe_ostream() = default;
explicit basic_pipe_ostream(const std::string& name, std::ios_base::openmode mode = std::ios_base::out)
:parent_type{nullptr}
{
parent_type::rdbuf(m_buffer.get());
open(name, mode);
}
virtual ~basic_pipe_ostream() = default;
basic_pipe_ostream(const basic_pipe_ostream&) = delete;
basic_pipe_ostream& operator=(const basic_pipe_ostream&) = delete;
basic_pipe_ostream(basic_pipe_ostream&& other) noexcept
:parent_type{std::move(other)}
{
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
}
basic_pipe_ostream& operator=(basic_pipe_ostream&& other) noexcept
{
parent_type::operator=(std::move(other));
std::swap(m_buffer, other.m_buffer);
parent_type::rdbuf(m_buffer.get());
return *this;
}
void open(const std::string& name, std::ios_base::openmode mode = std::ios_base::out)
{
m_buffer->open(name, mode);
parent_type::clear(m_buffer->is_open() ? std::ios_base::goodbit : std::ios_base::failbit);
}
bool is_open() const noexcept
{
return m_buffer->is_open();
}
void close()
{
m_buffer->close();
}
basic_pipe_streambuf<char_type, traits_type>* rdbuf() const noexcept
{
return m_buffer.get();
}
private:
friend class process;
friend std::pair<basic_pipe_istream<char_type, traits_type>, basic_pipe_ostream<char_type, traits_type>> make_anonymous_pipe<char_type, traits_type>();
basic_pipe_ostream(basic_pipe_streambuf<char_type, traits_type> buffer)
:parent_type{nullptr}
,m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>(std::move(buffer))}
{
parent_type::rdbuf(m_buffer.get());
}
private:
std::unique_ptr<basic_pipe_streambuf<char_type, traits_type>> m_buffer{std::make_unique<basic_pipe_streambuf<char_type, traits_type>>()};
};
template<typename CharT, typename Traits>
std::pair<basic_pipe_istream<CharT, Traits>, basic_pipe_ostream<CharT, Traits>> make_anonymous_pipe()
{
int fd[2];
if(pipe(fd))
throw std::runtime_error{"Failed to create pipe"};
return std::make_pair(basic_pipe_istream<CharT, Traits>{basic_pipe_streambuf<CharT, Traits>{fd[0], std::ios_base::in}},
basic_pipe_ostream<CharT, Traits>{basic_pipe_streambuf<CharT, Traits>{fd[1], std::ios_base::out}});
}
using pipe_streambuf = basic_pipe_streambuf<char>;
using pipe_istream = basic_pipe_istream<char>;
using pipe_ostream = basic_pipe_ostream<char>;
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -22,28 +22,24 @@
#include "main/main_session.h" #include "main/main_session.h"
namespace AyuMessages namespace AyuMessages {
{
std::optional<ayu_messages_controller> controller = std::nullopt; std::optional<AyuMessagesController> controller = std::nullopt;
void initialize() void initialize() {
{
if (controller.has_value()) { if (controller.has_value()) {
return; return;
} }
controller = ayu_messages_controller(); controller = AyuMessagesController();
} }
ayu_messages_controller &getInstance() AyuMessagesController &getInstance() {
{
initialize(); initialize();
return controller.value(); return controller.value();
} }
void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMessage &message) void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMessage &message) {
{
message.userId = item->history()->owner().session().userId().bare; message.userId = item->history()->owner().session().userId().bare;
message.dialogId = getDialogIdFromPeer(item->history()->peer); message.dialogId = getDialogIdFromPeer(item->history()->peer);
message.groupedId = item->groupId().value; message.groupedId = item->groupId().value;
@ -58,8 +54,7 @@ void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMes
if (auto edited = item->Get<HistoryMessageEdited>()) { if (auto edited = item->Get<HistoryMessageEdited>()) {
message.editDate = edited->date; message.editDate = edited->date;
} } else {
else {
message.editDate = base::unixtime::now(); message.editDate = base::unixtime::now();
} }
@ -68,7 +63,7 @@ void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMes
auto serializedText = serializeTextWithEntities(item); auto serializedText = serializeTextWithEntities(item);
message.text = serializedText.first; message.text = serializedText.first;
// message.textEntities = serializedText.second; // message.textEntities = serializedText.second;
// todo: // todo:
message.mediaPath = "/"; message.mediaPath = "/";
@ -80,16 +75,14 @@ void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMes
// message.mimeType; // message.mimeType;
} }
void ayu_messages_controller::addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item) void AyuMessagesController::addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item) {
{
EditedMessage message; EditedMessage message;
map(edition, item, message); map(edition, item, message);
AyuDatabase::addEditedMessage(message); AyuDatabase::addEditedMessage(message);
} }
std::vector<EditedMessage> ayu_messages_controller::getEditedMessages(HistoryItem *item) std::vector<EditedMessage> AyuMessagesController::getEditedMessages(HistoryItem *item) {
{
auto userId = item->history()->owner().session().userId().bare; auto userId = item->history()->owner().session().userId().bare;
auto dialogId = getDialogIdFromPeer(item->history()->peer); auto dialogId = getDialogIdFromPeer(item->history()->peer);
auto msgId = item->id.bare; auto msgId = item->id.bare;
@ -97,8 +90,7 @@ std::vector<EditedMessage> ayu_messages_controller::getEditedMessages(HistoryIte
return AyuDatabase::getEditedMessages(userId, dialogId, msgId); return AyuDatabase::getEditedMessages(userId, dialogId, msgId);
} }
bool ayu_messages_controller::hasRevisions(not_null<HistoryItem *> item) bool AyuMessagesController::hasRevisions(not_null<HistoryItem *> item) {
{
auto userId = item->history()->owner().session().userId().bare; auto userId = item->history()->owner().session().userId().bare;
auto dialogId = getDialogIdFromPeer(item->history()->peer); auto dialogId = getDialogIdFromPeer(item->history()->peer);
auto msgId = item->id.bare; auto msgId = item->id.bare;

View file

@ -10,10 +10,9 @@
#include "history/history_item_edition.h" #include "history/history_item_edition.h"
namespace AyuMessages namespace AyuMessages {
{
class ayu_messages_controller class AyuMessagesController
{ {
public: public:
void addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item); void addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item);
@ -21,6 +20,6 @@ public:
bool hasRevisions(not_null<HistoryItem *> item); bool hasRevisions(not_null<HistoryItem *> item);
}; };
ayu_messages_controller &getInstance(); AyuMessagesController &getInstance();
} }

View file

@ -1,205 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2023
#include "ayu_sync_controller.h"
#include "ayu/libs/process.hpp"
#include "ayu/sync/models.h"
#include "ayu/sync/utils/process_utils.hpp"
#include "ayu/utils/telegram_helpers.h"
#include "data/data_session.h"
#include "history/history.h"
#include <QString>
#include <thread>
#include "data/data_histories.h"
#include "history/history_item.h"
#include "history/view/history_view_element.h"
namespace AyuSync
{
std::optional<ayu_sync_controller> controller = std::nullopt;
bool isAgentDownloaded()
{
return std::filesystem::exists(AgentPath);
}
bool isAgentRunning()
{
return isProcessRunning(AgentFilename);
}
void initialize()
{
if (controller.has_value()) {
return;
}
controller = ayu_sync_controller();
}
ayu_sync_controller &getInstance()
{
initialize();
return controller.value();
}
void ayu_sync_controller::initializeAgent()
{
if (!isAgentDownloaded()) {
return;
}
if (isAgentRunning()) {
killProcess(AgentFilename);
}
auto configPath = std::filesystem::absolute("./tdata/sync_preferences.json");
auto process = nes::process{AgentPath, {configPath.string(), ""}, nes::process_options::none};
process.detach();
std::thread receiverThread(&ayu_sync_controller::receiver, this);
receiverThread.detach();
initialized = true;
}
void ayu_sync_controller::syncRead(not_null<History *> history, MsgId untilId)
{
if (!initialized) {
return;
}
SyncRead ev;
ev.userId = history->owner().session().userId().bare;
ev.args.dialogId = getDialogIdFromPeer(history->peer);
ev.args.untilId = untilId.bare;
ev.args.unread = history->unreadCount();
pipe->send(ev);
}
void ayu_sync_controller::receiver()
{
pipe = std::make_unique<ayu_pipe_wrapper>();
pipe->connect();
LOG(("Pipe created"));
while (true) {
auto p = pipe->receive();
if (p == std::nullopt) {
continue;
}
std::string s = p->dump();
LOG(("[AyuSync] Received message: %1").arg(QString::fromStdString(s)));
invokeHandler(p.value());
}
}
void ayu_sync_controller::invokeHandler(json p)
{
LOG(("Invoking handler on %1").arg(p.dump().c_str()));
auto userId = p["userId"].get<long>();
auto type = p["type"].get<std::string>();
LOG(("userId: %1, type: %2").arg(userId).arg(type.c_str()));
if (!accountExists(userId)) {
LOG(("Sync for unknown account: %1").arg(userId));
return;
}
if (type == "sync_force") {
auto ev = p.get<SyncForce>();
onSyncForce(ev);
}
else if (type == "sync_batch") {
onSyncBatch(p);
}
else if (type == "sync_read") {
auto ev = p.get<SyncRead>();
onSyncRead(ev);
}
else {
LOG(("Unknown sync type: %1").arg(type.c_str()));
}
}
void ayu_sync_controller::onSyncForce(SyncForce ev)
{
auto session = getSession(ev.userId);
auto histories = session->data().chatsList();
SyncBatch readsBatchEvent;
readsBatchEvent.userId = ev.userId;
for (const auto &row : histories->indexed()->all()) {
if (const auto history = row->history()) {
auto dialogId = getDialogIdFromPeer(history->peer);
SyncRead readEv;
readEv.userId = ev.userId;
history->calculateFirstUnreadMessage();
auto unreadElement = history->firstUnreadMessage();
if (!unreadElement && history->unreadCount()) {
LOG(("No unread can be calculated for %1").arg(dialogId));
continue;
}
auto untilId = unreadElement ? unreadElement->data()->id.bare : history->lastMessage()->id.bare;
readEv.args.dialogId = dialogId;
readEv.args.untilId = untilId;
readEv.args.unread = history->unreadCount();
readsBatchEvent.args.events.emplace_back(readEv);
}
}
pipe->send(readsBatchEvent);
// send finish event
SyncForceFinish newEv;
newEv.userId = ev.userId;
pipe->send(newEv);
}
void ayu_sync_controller::onSyncBatch(json ev)
{
for (auto &item : ev["args"]["events"]) {
invokeHandler(item);
}
}
void ayu_sync_controller::onSyncRead(SyncRead ev)
{
dispatchToMainThread([=]
{
auto session = getSession(ev.userId);
auto history = getHistoryFromDialogId(ev.args.dialogId, session);
if (history->folderKnown()) {
history->inboxRead(ev.args.untilId, ev.args.unread);
}
else {
LOG(("Unknown dialog %1").arg(ev.args.dialogId));
}
});
}
}

View file

@ -1,58 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2023
#pragma once
#include "models.h"
#include "ayu/libs/json.hpp"
#include "history/history.h"
#include "utils/ayu_pipe_wrapper.h"
using json = nlohmann::json;
#ifdef _WIN32
const std::string AgentFilename = "AyuSync.Agent.exe";
#else
const std::string AgentFilename = "AyuSync.Agent";
#endif
const std::string AgentPath = "./AyuSync/" + AgentFilename;
namespace AyuSync
{
class ayu_sync_controller
{
public:
void initializeAgent();
void syncRead(not_null<History *> history, MsgId untilId);
void onSyncForce(SyncForce ev);
void onSyncBatch(json ev);
void onSyncRead(SyncRead ev);
void invokeHandler(json p);
private:
void receiver();
std::unique_ptr<ayu_pipe_wrapper> pipe;
bool initialized;
};
ayu_sync_controller &getInstance();
bool isAgentDownloaded();
bool isAgentRunning();
}

View file

@ -1,140 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2023
#pragma once
#include <string>
#include <vector>
#include "ayu/libs/json.hpp"
#include "ayu/database/entities.h"
using json = nlohmann::json;
class SyncEvent
{
public:
std::string type = "sync_unspecified";
ID userId = 0;
};
class SyncBatch : public SyncEvent
{
public:
explicit SyncBatch()
{
type = "sync_batch";
}
class SyncBatchArgs
{
public:
std::vector<json> events;
};
SyncBatchArgs args{};
};
class SyncForce : public SyncEvent
{
public:
explicit SyncForce()
{
type = "sync_force";
}
class SyncForceArgs
{
public:
int fromDate;
};
SyncForceArgs args{};
};
class SyncForceFinish : public SyncEvent
{
public:
explicit SyncForceFinish()
{
type = "sync_force_finish";
}
class SyncForceFinishArgs
{
public:
short dummy; // required to be JSON serializable
};
SyncForceFinishArgs args{};
};
class SyncRead : public SyncEvent
{
public:
explicit SyncRead()
{
type = "sync_read";
}
class SyncReadArgs
{
public:
ID dialogId;
int untilId;
int unread;
};
SyncReadArgs args{};
};
class SyncDeletedMessage : public SyncEvent
{
public:
explicit SyncDeletedMessage()
{
type = "sync_deleted_message";
}
class SyncDeletedMessageArgs
{
public:
json message;
};
SyncDeletedMessageArgs args{};
};
class SyncEditedMessage : public SyncEvent
{
public:
explicit SyncEditedMessage()
{
type = "sync_edited_message";
}
class SyncEditedMessageArgs
{
public:
json message;
};
SyncEditedMessageArgs args{};
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEvent, type, userId)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncBatch::SyncBatchArgs, events)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncBatch, type, userId, args)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce::SyncForceArgs, fromDate)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce, type, userId, args)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish::SyncForceFinishArgs, dummy)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish, type, userId, args)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncRead::SyncReadArgs, dialogId, untilId, unread)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncRead, type, userId, args)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncDeletedMessage::SyncDeletedMessageArgs, message)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncDeletedMessage, type, userId, args)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEditedMessage::SyncEditedMessageArgs, message)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEditedMessage, type, userId, args)

View file

@ -1,64 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2023
#include "ayu_pipe_wrapper.h"
#include "ayu/libs/bit_converter.hpp"
#include <sstream>
using stringbuf = std::basic_stringbuf<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char>>;
void ayu_pipe_wrapper::connect()
{
is = std::make_unique<pipein>("AyuSync");
receive();
os = std::make_unique<pipeout>("AyuSync1338");
}
void ayu_pipe_wrapper::send(json p)
{
auto s = p.dump();
auto length = s.length();
unsigned char lengthBuff[4];
bit_converter::i32_to_bytes(length, false, lengthBuff);
os->write(lengthBuff, 4);
os->write(reinterpret_cast<const unsigned char *>(s.c_str()), length);
os->flush();
}
std::optional<json> ayu_pipe_wrapper::receive()
{
if (!is->is_open()) {
return std::nullopt;
}
unsigned char lengthBuff[4];
is->read(lengthBuff, 4);
auto length = bit_converter::bytes_to_i32(lengthBuff, false);
LOG(("ayu_pipe_wrapper::receive() length: %1").arg(length));
if (length <= 0) {
return std::nullopt;
}
auto sb = stringbuf();
unsigned char buff[4096];
while (length > 0) {
auto readSize = std::min(length, static_cast<int>(sizeof(buff)));
is->read(buff, readSize);
auto reallyRead = is->gcount();
sb.sputn(buff, reallyRead);
length -= reallyRead;
}
auto p = json::parse(sb.str());
return p;
}

View file

@ -1,28 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2023
#pragma once
#include "ayu/libs/json.hpp"
#include "ayu/libs/pipe.hpp"
#include "ayu/sync/models.h"
using json = nlohmann::json;
using pipein = nes::basic_pipe_istream<unsigned char>;
using pipeout = nes::basic_pipe_ostream<unsigned char>;
class ayu_pipe_wrapper
{
public:
void connect();
void send(json p);
std::optional<json> receive();
private:
std::unique_ptr<pipein> is;
std::unique_ptr<pipeout> os;
};

View file

@ -1,93 +0,0 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2023
#include <codecvt>
#include <iostream>
#include <locale>
#include <string>
#ifdef _WIN32
#include <tlhelp32.h>
#include <windows.h>
#endif
// A function to check if a process is running by its name
// Bing AI generated
inline bool isProcessRunning(const std::string &name)
{
#ifdef _WIN32
// Create a snapshot of all processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to create snapshot\n";
return false;
}
// Iterate over the processes and compare the names
PROCESSENTRY32 entry;
entry.dwSize = sizeof(entry);
if (!Process32First(snapshot, &entry)) {
std::cerr << "Failed to get first process\n";
CloseHandle(snapshot);
return false;
}
do {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string entry_name = converter.to_bytes(entry.szExeFile);
if (name == entry_name) {
// Found a match
CloseHandle(snapshot);
return true;
}
}
while (Process32Next(snapshot, &entry));
// No match found
CloseHandle(snapshot);
return false;
#else
throw std::logic_error("not implemented");
#endif
}
// Copilot generated
void killProcess(const std::string &name)
{
#ifdef _WIN32
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to create snapshot\n";
return;
}
// Iterate over the processes and compare the names
PROCESSENTRY32 entry;
entry.dwSize = sizeof(entry);
if (!Process32First(snapshot, &entry)) {
std::cerr << "Failed to get first process\n";
CloseHandle(snapshot);
return;
}
do {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string entry_name = converter.to_bytes(entry.szExeFile);
if (name == entry_name) {
// Found a match
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
if (hProcess != nullptr) {
TerminateProcess(hProcess, 9);
CloseHandle(hProcess);
}
CloseHandle(snapshot);
return;
}
}
while (Process32Next(snapshot, &entry));
// No match found
CloseHandle(snapshot);
#else
throw std::logic_error("not implemented");
#endif
}

View file

@ -8,16 +8,12 @@
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
static QString LAST_LOADED_NAME; static QString LAST_LOADED_NAME;
static QImage LAST_LOADED; static QImage LAST_LOADED;
static QImage LAST_LOADED_NO_MARGIN; static QImage LAST_LOADED_NO_MARGIN;
namespace AyuAssets namespace AyuAssets {
{
void loadAppIco() void loadAppIco() {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
QString appDataPath = QDir::fromNativeSeparators(qgetenv("APPDATA")); QString appDataPath = QDir::fromNativeSeparators(qgetenv("APPDATA"));
@ -33,8 +29,7 @@ void loadAppIco()
QFile::copy(qsl(":/gui/art/ayu/%1/app_icon.ico").arg(settings->appIcon), tempIconPath); QFile::copy(qsl(":/gui/art/ayu/%1/app_icon.ico").arg(settings->appIcon), tempIconPath);
} }
void loadIcons() void loadIcons() {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
if (LAST_LOADED_NAME != settings->appIcon) { if (LAST_LOADED_NAME != settings->appIcon) {
LAST_LOADED_NAME = settings->appIcon; LAST_LOADED_NAME = settings->appIcon;
@ -44,24 +39,20 @@ void loadIcons()
} }
} }
QImage loadPreview(QString name) QImage loadPreview(QString name) {
{
return QImage(qsl(":/gui/art/ayu/%1/app_preview.png").arg(name)); return QImage(qsl(":/gui/art/ayu/%1/app_preview.png").arg(name));
} }
QString currentAppLogoName() QString currentAppLogoName() {
{
return LAST_LOADED_NAME; return LAST_LOADED_NAME;
} }
QImage currentAppLogo() QImage currentAppLogo() {
{
loadIcons(); loadIcons();
return LAST_LOADED; return LAST_LOADED;
} }
QImage currentAppLogoNoMargin() QImage currentAppLogoNoMargin() {
{
loadIcons(); loadIcons();
return LAST_LOADED_NO_MARGIN; return LAST_LOADED_NO_MARGIN;
} }

View file

@ -8,23 +8,15 @@
#define ICON(name, value) const auto name##_ICON = QStringLiteral(value) #define ICON(name, value) const auto name##_ICON = QStringLiteral(value)
namespace AyuAssets namespace AyuAssets {
{
ICON(DEFAULT, "default"); ICON(DEFAULT, "default");
ICON(ALT, "alt"); ICON(ALT, "alt");
ICON(DISCORD, "discord"); ICON(DISCORD, "discord");
ICON(SPOTIFY, "spotify"); ICON(SPOTIFY, "spotify");
ICON(EXTERA, "extera"); ICON(EXTERA, "extera");
ICON(NOTHING, "nothing"); ICON(NOTHING, "nothing");
ICON(BARD, "bard"); ICON(BARD, "bard");
ICON(YAPLUS, "yaplus"); ICON(YAPLUS, "yaplus");
void loadAppIco(); void loadAppIco();

View file

@ -6,40 +6,26 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "edit_deleted_mark.h" #include "edit_deleted_mark.h"
#include "base/random.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h"
#include "data/data_cloud_file.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
#include "ui/ui_utility.h"
#include "ui/unread_badge.h"
#include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/fields/input_field.h" #include "ui/widgets/fields/input_field.h"
#include "ui/widgets/fields/special_fields.h" #include "ui/widgets/fields/special_fields.h"
#include <QtGui/QGuiApplication>
#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,
tr::ayu_DeletedMarkText(), tr::ayu_DeletedMarkText(),
AyuSettings::getInstance().deletedMark) AyuSettings::getInstance().deletedMark) {
{
} }
void EditDeletedMarkBox::prepare() void EditDeletedMarkBox::prepare() {
{
const auto defaultDeletedMark = "🧹"; const auto defaultDeletedMark = "🧹";
auto newHeight = st::contactPadding.top() + _text->height(); auto newHeight = st::contactPadding.top() + _text->height();
@ -48,53 +34,59 @@ void EditDeletedMarkBox::prepare()
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom(); newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
setDimensions(st::boxWidth, newHeight); setDimensions(st::boxWidth, newHeight);
addLeftButton(tr::ayu_BoxActionReset(), [=] addLeftButton(tr::ayu_BoxActionReset(),
{ _text->setText(defaultDeletedMark); }); [=]
{
_text->setText(defaultDeletedMark);
});
addButton(tr::lng_settings_save(), [=] addButton(tr::lng_settings_save(),
{ save(); }); [=]
addButton(tr::lng_cancel(), [=] {
{ closeBox(); }); save();
});
addButton(tr::lng_cancel(),
[=]
{
closeBox();
});
const auto submitted = [=] const auto submitted = [=]
{ submit(); }; {
submit();
};
_text->submits( _text->submits(
) | rpl::start_with_next(submitted, _text->lifetime()); ) | rpl::start_with_next(submitted, _text->lifetime());
} }
void EditDeletedMarkBox::setInnerFocus() void EditDeletedMarkBox::setInnerFocus() {
{
_text->setFocusFast(); _text->setFocusFast();
} }
void EditDeletedMarkBox::submit() void EditDeletedMarkBox::submit() {
{
if (_text->getLastText().trimmed().isEmpty()) { if (_text->getLastText().trimmed().isEmpty()) {
_text->setFocus(); _text->setFocus();
_text->showError(); _text->showError();
} } else {
else {
save(); 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(); const auto settings = &AyuSettings::getInstance();
settings->set_deletedMark(_text->getLastText()); settings->set_deletedMark(_text->getLastText());
AyuSettings::save(); AyuSettings::save();

View file

@ -8,7 +8,6 @@
#include "base/timer.h" #include "base/timer.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "mtproto/sender.h"
class EditDeletedMarkBox : public Ui::BoxContent class EditDeletedMarkBox : public Ui::BoxContent
{ {
@ -17,14 +16,11 @@ public:
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,40 +6,26 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "edit_edited_mark.h" #include "edit_edited_mark.h"
#include "base/random.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h"
#include "data/data_cloud_file.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
#include "ui/ui_utility.h"
#include "ui/unread_badge.h"
#include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/fields/input_field.h" #include "ui/widgets/fields/input_field.h"
#include "ui/widgets/fields/special_fields.h" #include "ui/widgets/fields/special_fields.h"
#include <QtGui/QGuiApplication>
#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,
tr::ayu_EditedMarkText(), tr::ayu_EditedMarkText(),
AyuSettings::getInstance().editedMark) AyuSettings::getInstance().editedMark) {
{
} }
void EditEditedMarkBox::prepare() void EditEditedMarkBox::prepare() {
{
const auto defaultEditedMark = tr::lng_edited(tr::now); const auto defaultEditedMark = tr::lng_edited(tr::now);
auto newHeight = st::contactPadding.top() + _text->height(); auto newHeight = st::contactPadding.top() + _text->height();
@ -48,52 +34,58 @@ void EditEditedMarkBox::prepare()
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom(); newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
setDimensions(st::boxWidth, newHeight); setDimensions(st::boxWidth, newHeight);
addLeftButton(tr::ayu_BoxActionReset(), [=] addLeftButton(tr::ayu_BoxActionReset(),
{ _text->setText(defaultEditedMark); }); [=]
addButton(tr::lng_settings_save(), [=] {
{ save(); }); _text->setText(defaultEditedMark);
addButton(tr::lng_cancel(), [=] });
{ closeBox(); }); addButton(tr::lng_settings_save(),
[=]
{
save();
});
addButton(tr::lng_cancel(),
[=]
{
closeBox();
});
const auto submitted = [=] const auto submitted = [=]
{ submit(); }; {
submit();
};
_text->submits( _text->submits(
) | rpl::start_with_next(submitted, _text->lifetime()); ) | rpl::start_with_next(submitted, _text->lifetime());
} }
void EditEditedMarkBox::setInnerFocus() void EditEditedMarkBox::setInnerFocus() {
{
_text->setFocusFast(); _text->setFocusFast();
} }
void EditEditedMarkBox::submit() void EditEditedMarkBox::submit() {
{
if (_text->getLastText().trimmed().isEmpty()) { if (_text->getLastText().trimmed().isEmpty()) {
_text->setFocus(); _text->setFocus();
_text->showError(); _text->showError();
} } else {
else {
save(); 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(); const auto settings = &AyuSettings::getInstance();
settings->set_editedMark(_text->getLastText()); settings->set_editedMark(_text->getLastText());
AyuSettings::save(); AyuSettings::save();

View file

@ -17,14 +17,11 @@ public:
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

@ -50,8 +50,7 @@ struct Font
QString id; QString id;
}; };
namespace AyuUi namespace AyuUi {
{
class Rows : public Ui::RpWidget class Rows : public Ui::RpWidget
{ {
@ -62,38 +61,23 @@ public:
const QString &chosen); const QString &chosen);
void filter(const QString &query); void filter(const QString &query);
int count() const; int count() const;
int selected() const; int selected() const;
void setSelected(int selected); void setSelected(int selected);
rpl::producer<bool> hasSelection() const; rpl::producer<bool> hasSelection() const;
rpl::producer<bool> isEmpty() const; rpl::producer<bool> isEmpty() const;
void activateSelected(); void activateSelected();
rpl::producer<Font> activations() const; rpl::producer<Font> activations() const;
void changeChosen(const QString &chosen); void changeChosen(const QString &chosen);
Ui::ScrollToRequest rowScrollRequest(int index) const; Ui::ScrollToRequest rowScrollRequest(int index) const;
static int DefaultRowHeight(); static int DefaultRowHeight();
protected: protected:
int resizeGetHeight(int newWidth) override; int resizeGetHeight(int newWidth) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void leaveEventHook(QEvent *e) override; void leaveEventHook(QEvent *e) override;
private: private:
@ -118,8 +102,7 @@ private:
{ {
int index = 0; int index = 0;
inline bool operator==(const RowSelection &other) const inline bool operator==(const RowSelection &other) const {
{
return (index == other.index); return (index == other.index);
} }
}; };
@ -224,15 +207,14 @@ private:
}; };
std::vector<Font> PrepareFonts() std::vector<Font> PrepareFonts() {
{
auto fonts = std::vector<Font>(); auto fonts = std::vector<Font>();
QFontDatabase base; QFontDatabase base;
for (const auto &font : base.families()) { for (const auto &font : base.families()) {
Font fontItem = { Font fontItem = {
.FontName=font, .FontName = font,
.id=font .id = font
}; };
fonts.push_back(fontItem); fonts.push_back(fontItem);
@ -246,8 +228,7 @@ Rows::Rows(
QWidget *parent, QWidget *parent,
const std::vector<Font> &data, const std::vector<Font> &data,
const QString &chosen) const QString &chosen)
: RpWidget(parent), _chosen(chosen) : RpWidget(parent), _chosen(chosen) {
{
const auto descriptionOptions = TextParseOptions{ const auto descriptionOptions = TextParseOptions{
TextParseMultiline, TextParseMultiline,
0, 0,
@ -262,7 +243,9 @@ Rows::Rows(
st::langsRadio, st::langsRadio,
(row.data.id == _chosen), (row.data.id == _chosen),
[=, row = &row] [=, row = &row]
{ repaint(*row); }); {
repaint(*row);
});
row.title.setText( row.title.setText(
st::defaultTextStyle, st::defaultTextStyle,
item.FontName, item.FontName,
@ -275,8 +258,7 @@ Rows::Rows(
update(); update();
} }
void Rows::mouseMoveEvent(QMouseEvent *e) void Rows::mouseMoveEvent(QMouseEvent *e) {
{
const auto position = e->globalPos(); const auto position = e->globalPos();
if (!_mouseSelection && position == _globalMousePosition) { if (!_mouseSelection && position == _globalMousePosition) {
return; return;
@ -300,17 +282,14 @@ void Rows::mouseMoveEvent(QMouseEvent *e)
const auto row = (index >= 0) ? &rowByIndex(index) : nullptr; const auto row = (index >= 0) ? &rowByIndex(index) : nullptr;
if (index < 0) { if (index < 0) {
updateSelected({}); updateSelected({});
} } else if (!row->removed) {
else if (!row->removed) {
updateSelected(RowSelection{index}); updateSelected(RowSelection{index});
} } else {
else {
updateSelected({}); updateSelected({});
} }
} }
void Rows::mousePressEvent(QMouseEvent *e) void Rows::mousePressEvent(QMouseEvent *e) {
{
updatePressed(_selected); updatePressed(_selected);
if (!v::is_null(_pressed) if (!v::is_null(_pressed)
&& !rowBySelection(_pressed).menuToggleForceRippled) { && !rowBySelection(_pressed).menuToggleForceRippled) {
@ -318,8 +297,7 @@ void Rows::mousePressEvent(QMouseEvent *e)
} }
} }
void Rows::addRipple(Selection selected, QPoint position) void Rows::addRipple(Selection selected, QPoint position) {
{
Expects(!v::is_null(selected)); Expects(!v::is_null(selected));
ensureRippleBySelection(selected); ensureRippleBySelection(selected);
@ -330,13 +308,11 @@ void Rows::addRipple(Selection selected, QPoint position)
ripple->add(position - topleft); ripple->add(position - topleft);
} }
void Rows::ensureRippleBySelection(Selection selected) void Rows::ensureRippleBySelection(Selection selected) {
{
ensureRippleBySelection(&rowBySelection(selected), selected); ensureRippleBySelection(&rowBySelection(selected), selected);
} }
void Rows::ensureRippleBySelection(not_null<Row *> row, Selection selected) void Rows::ensureRippleBySelection(not_null<Row *> row, Selection selected) {
{
auto &ripple = rippleBySelection(row, selected); auto &ripple = rippleBySelection(row, selected);
if (ripple) { if (ripple) {
return; return;
@ -346,44 +322,43 @@ void Rows::ensureRippleBySelection(not_null<Row *> row, Selection selected)
st::defaultRippleAnimation, st::defaultRippleAnimation,
std::move(mask), std::move(mask),
[=] [=]
{ repaintChecked(row); }); {
repaintChecked(row);
});
} }
void Rows::mouseReleaseEvent(QMouseEvent *e) void Rows::mouseReleaseEvent(QMouseEvent *e) {
{
const auto pressed = _pressed; const auto pressed = _pressed;
updatePressed({}); updatePressed({});
if (pressed == _selected) { if (pressed == _selected) {
v::match(pressed, [&](RowSelection data) v::match(pressed,
{ [&](RowSelection data)
activateByIndex(data.index); {
}, [](v::null_t) activateByIndex(data.index);
{ }); },
[](v::null_t)
{
});
} }
} }
void Rows::restore(not_null<Row *> row) void Rows::restore(not_null<Row *> row) {
{
row->removed = false; row->removed = false;
} }
void Rows::setForceRippled(not_null<Row *> row, bool rippled) void Rows::setForceRippled(not_null<Row *> row, bool rippled) {
{
repaint(*row); repaint(*row);
} }
void Rows::activateByIndex(int index) void Rows::activateByIndex(int index) {
{
_activations.fire_copy(rowByIndex(index).data); _activations.fire_copy(rowByIndex(index).data);
} }
void Rows::leaveEventHook(QEvent *e) void Rows::leaveEventHook(QEvent *e) {
{
updateSelected({}); updateSelected({});
} }
void Rows::filter(const QString &query) void Rows::filter(const QString &query) {
{
updateSelected({}); updateSelected({});
updatePressed({}); updatePressed({});
@ -418,8 +393,7 @@ void Rows::filter(const QString &query)
for (auto &row : _rows) { for (auto &row : _rows) {
if (!skip(row.keywords, _query)) { if (!skip(row.keywords, _query)) {
_filtered.push_back(&row); _filtered.push_back(&row);
} } else {
else {
row.ripple = nullptr; row.ripple = nullptr;
} }
} }
@ -431,103 +405,92 @@ void Rows::filter(const QString &query)
_isEmpty.fire(count() == 0); _isEmpty.fire(count() == 0);
} }
int Rows::count() const int Rows::count() const {
{
return _query.isEmpty() ? _rows.size() : _filtered.size(); return _query.isEmpty() ? _rows.size() : _filtered.size();
} }
int Rows::indexFromSelection(Selection selected) const int Rows::indexFromSelection(Selection selected) const {
{ return v::match(selected,
return v::match(selected, [&](RowSelection data) [&](RowSelection data)
{ {
return data.index; return data.index;
}, [](v::null_t) },
[](v::null_t)
{ {
return -1; return -1;
}); });
} }
int Rows::selected() const int Rows::selected() const {
{
return indexFromSelection(_selected); return indexFromSelection(_selected);
} }
void Rows::activateSelected() void Rows::activateSelected() {
{
const auto index = selected(); const auto index = selected();
if (index >= 0) { if (index >= 0) {
activateByIndex(index); activateByIndex(index);
} }
} }
rpl::producer<Font> Rows::activations() const rpl::producer<Font> Rows::activations() const {
{
return _activations.events(); return _activations.events();
} }
void Rows::changeChosen(const QString &chosen) void Rows::changeChosen(const QString &chosen) {
{
for (const auto &row : _rows) { for (const auto &row : _rows) {
row.check->setChecked(row.data.id == chosen, anim::type::normal); row.check->setChecked(row.data.id == chosen, anim::type::normal);
} }
} }
void Rows::setSelected(int selected) void Rows::setSelected(int selected) {
{
_mouseSelection = false; _mouseSelection = false;
const auto limit = count(); const auto limit = count();
if (selected >= 0 && selected < limit) { if (selected >= 0 && selected < limit) {
updateSelected(RowSelection{selected}); updateSelected(RowSelection{selected});
} } else {
else {
updateSelected({}); updateSelected({});
} }
} }
rpl::producer<bool> Rows::hasSelection() const rpl::producer<bool> Rows::hasSelection() const {
{
return _hasSelection.events(); return _hasSelection.events();
} }
rpl::producer<bool> Rows::isEmpty() const rpl::producer<bool> Rows::isEmpty() const {
{
return _isEmpty.events_starting_with( return _isEmpty.events_starting_with(
count() == 0 count() == 0
) | rpl::distinct_until_changed(); ) | rpl::distinct_until_changed();
} }
void Rows::repaint(Selection selected) void Rows::repaint(Selection selected) {
{ v::match(selected,
v::match(selected, [](v::null_t) [](v::null_t)
{ {
}, [&](const auto &data) },
[&](const auto &data)
{ {
repaint(data.index); repaint(data.index);
}); });
} }
void Rows::repaint(int index) void Rows::repaint(int index) {
{
if (index >= 0) { if (index >= 0) {
repaint(rowByIndex(index)); repaint(rowByIndex(index));
} }
} }
void Rows::repaint(const Row &row) void Rows::repaint(const Row &row) {
{
update(0, row.top, width(), row.height); update(0, row.top, width(), row.height);
} }
void Rows::repaintChecked(not_null<const Row *> row) void Rows::repaintChecked(not_null<const Row *> row) {
{
const auto found = (ranges::find(_filtered, row) != end(_filtered)); const auto found = (ranges::find(_filtered, row) != end(_filtered));
if (_query.isEmpty() || found) { if (_query.isEmpty() || found) {
repaint(*row); repaint(*row);
} }
} }
void Rows::updateSelected(Selection selected) void Rows::updateSelected(Selection selected) {
{
const auto changed = (v::is_null(_selected) != v::is_null(selected)); const auto changed = (v::is_null(_selected) != v::is_null(selected));
repaint(_selected); repaint(_selected);
_selected = selected; _selected = selected;
@ -537,8 +500,7 @@ void Rows::updateSelected(Selection selected)
} }
} }
void Rows::updatePressed(Selection pressed) void Rows::updatePressed(Selection pressed) {
{
if (!v::is_null(_pressed)) { if (!v::is_null(_pressed)) {
if (!rowBySelection(_pressed).menuToggleForceRippled) { if (!rowBySelection(_pressed).menuToggleForceRippled) {
if (const auto ripple = rippleBySelection(_pressed).get()) { if (const auto ripple = rippleBySelection(_pressed).get()) {
@ -549,66 +511,56 @@ void Rows::updatePressed(Selection pressed)
_pressed = pressed; _pressed = pressed;
} }
Rows::Row &Rows::rowByIndex(int index) Rows::Row &Rows::rowByIndex(int index) {
{
Expects(index >= 0 && index < count()); Expects(index >= 0 && index < count());
return _query.isEmpty() ? _rows[index] : *_filtered[index]; return _query.isEmpty() ? _rows[index] : *_filtered[index];
} }
const Rows::Row &Rows::rowByIndex(int index) const const Rows::Row &Rows::rowByIndex(int index) const {
{
Expects(index >= 0 && index < count()); Expects(index >= 0 && index < count());
return _query.isEmpty() ? _rows[index] : *_filtered[index]; return _query.isEmpty() ? _rows[index] : *_filtered[index];
} }
Rows::Row &Rows::rowBySelection(Selection selected) Rows::Row &Rows::rowBySelection(Selection selected) {
{
return rowByIndex(indexFromSelection(selected)); return rowByIndex(indexFromSelection(selected));
} }
const Rows::Row &Rows::rowBySelection(Selection selected) const const Rows::Row &Rows::rowBySelection(Selection selected) const {
{
return rowByIndex(indexFromSelection(selected)); return rowByIndex(indexFromSelection(selected));
} }
std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection( std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection(
Selection selected) Selection selected) {
{
return rippleBySelection(&rowBySelection(selected), selected); return rippleBySelection(&rowBySelection(selected), selected);
} }
const std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection( const std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection(
Selection selected) const Selection selected) const {
{
return rippleBySelection(&rowBySelection(selected), selected); return rippleBySelection(&rowBySelection(selected), selected);
} }
std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection( std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection(
not_null<Row *> row, not_null<Row *> row,
Selection selected) Selection selected) {
{
return row->ripple; return row->ripple;
} }
const std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection( const std::unique_ptr<Ui::RippleAnimation> &Rows::rippleBySelection(
not_null<const Row *> row, not_null<const Row *> row,
Selection selected) const Selection selected) const {
{
return const_cast<Rows *>(this)->rippleBySelection( return const_cast<Rows *>(this)->rippleBySelection(
const_cast<Row *>(row.get()), const_cast<Row *>(row.get()),
selected); selected);
} }
Ui::ScrollToRequest Rows::rowScrollRequest(int index) const Ui::ScrollToRequest Rows::rowScrollRequest(int index) const {
{
const auto &row = rowByIndex(index); const auto &row = rowByIndex(index);
return Ui::ScrollToRequest(row.top, row.top + row.height); return Ui::ScrollToRequest(row.top, row.top + row.height);
} }
int Rows::DefaultRowHeight() int Rows::DefaultRowHeight() {
{
return st::passportRowPadding.top() return st::passportRowPadding.top()
+ st::semiboldFont->height + st::semiboldFont->height
+ st::passportRowSkip + st::passportRowSkip
@ -616,8 +568,7 @@ int Rows::DefaultRowHeight()
+ st::passportRowPadding.bottom(); + st::passportRowPadding.bottom();
} }
int Rows::resizeGetHeight(int newWidth) int Rows::resizeGetHeight(int newWidth) {
{
const auto availableWidth = countAvailableWidth(newWidth); const auto availableWidth = countAvailableWidth(newWidth);
auto result = 0; auto result = 0;
for (auto i = 0, till = count(); i != till; ++i) { for (auto i = 0, till = count(); i != till; ++i) {
@ -635,8 +586,7 @@ int Rows::resizeGetHeight(int newWidth)
return result; return result;
} }
int Rows::countAvailableWidth(int newWidth) const int Rows::countAvailableWidth(int newWidth) const {
{
const auto right = 0; const auto right = 0;
return newWidth return newWidth
- st::passportRowPadding.left() - st::passportRowPadding.left()
@ -646,13 +596,11 @@ int Rows::countAvailableWidth(int newWidth) const
- st::passportRowIconSkip; - st::passportRowIconSkip;
} }
int Rows::countAvailableWidth() const int Rows::countAvailableWidth() const {
{
return countAvailableWidth(width()); return countAvailableWidth(width());
} }
void Rows::paintEvent(QPaintEvent *e) void Rows::paintEvent(QPaintEvent *e) {
{
Painter p(this); Painter p(this);
const auto clip = e->rect(); const auto clip = e->rect();
@ -667,14 +615,15 @@ void Rows::paintEvent(QPaintEvent *e)
const auto &row = rowByIndex(i); const auto &row = rowByIndex(i);
if (row.top + row.height <= clip.y()) { if (row.top + row.height <= clip.y()) {
continue; continue;
} } else if (row.top >= clip.y() + clip.height()) {
else if (row.top >= clip.y() + clip.height()) {
break; break;
} }
p.setOpacity(row.removed ? st::stickersRowDisabledOpacity : 1.); p.setOpacity(row.removed ? st::stickersRowDisabledOpacity : 1.);
p.translate(0, row.top); p.translate(0, row.top);
const auto guard = gsl::finally([&] const auto guard = gsl::finally([&]
{ p.translate(0, -row.top); }); {
p.translate(0, -row.top);
});
const auto selected = (selectedIndex == i); const auto selected = (selectedIndex == i);
if (selected && !row.removed) { if (selected && !row.removed) {
@ -706,14 +655,12 @@ void Rows::paintEvent(QPaintEvent *e)
Content::Content( Content::Content(
QWidget *parent, QWidget *parent,
const std::vector<Font> &fonts) const std::vector<Font> &fonts)
: RpWidget(parent) : RpWidget(parent) {
{
setupContent(fonts); setupContent(fonts);
} }
void Content::setupContent( void Content::setupContent(
const std::vector<Font> &fonts) const std::vector<Font> &fonts) {
{
using namespace rpl::mappers; using namespace rpl::mappers;
const auto current = AyuFonts::getMainFont(); const auto current = AyuFonts::getMainFont();
@ -742,7 +689,8 @@ void Content::setupContent(
rows->isEmpty() | rpl::start_with_next([=](bool empty) rows->isEmpty() | rpl::start_with_next([=](bool empty)
{ {
wrap->toggle(!empty, anim::type::instant); wrap->toggle(!empty, anim::type::instant);
}, rows->lifetime()); },
rows->lifetime());
return rows; return rows;
}; };
@ -767,7 +715,8 @@ void Content::setupContent(
label->move( label->move(
(size.width() - label->width()) / 2, (size.width() - label->width()) / 2,
(size.height() - label->height()) / 2); (size.height() - label->height()) / 2);
}, label->lifetime()); },
label->lifetime());
empty->toggleOn( empty->toggleOn(
main ? main->isEmpty() : rpl::single(true), main ? main->isEmpty() : rpl::single(true),
@ -805,8 +754,7 @@ void Content::setupContent(
if (main) { if (main) {
main->setSelected(-1); main->setSelected(-1);
} }
} } else {
else {
if (main) { if (main) {
main->setSelected(index); main->setSelected(index);
} }
@ -836,15 +784,12 @@ void Content::setupContent(
const auto changed = now + rows; const auto changed = now + rows;
if (changed < 0) { if (changed < 0) {
setSelectedIndex((now > 0) ? 0 : -1); setSelectedIndex((now > 0) ? 0 : -1);
} } else if (changed >= count) {
else if (changed >= count) {
setSelectedIndex(count - 1); setSelectedIndex(count - 1);
} } else {
else {
setSelectedIndex(changed); setSelectedIndex(changed);
} }
} } else if (rows > 0) {
else if (rows > 0) {
setSelectedIndex(0); setSelectedIndex(0);
} }
return selectedCoords(); return selectedCoords();
@ -885,70 +830,68 @@ void Content::setupContent(
}; };
}; };
void Content::filter(const QString &query) void Content::filter(const QString &query) {
{
_filter(query); _filter(query);
} }
rpl::producer<Font> Content::activations() const rpl::producer<Font> Content::activations() const {
{
return _activations(); return _activations();
} }
void Content::changeChosen(const QString &chosen) void Content::changeChosen(const QString &chosen) {
{
_changeChosen(chosen); _changeChosen(chosen);
} }
void Content::activateBySubmit() void Content::activateBySubmit() {
{
_activateBySubmit(); _activateBySubmit();
} }
Ui::ScrollToRequest Content::jump(int rows) Ui::ScrollToRequest Content::jump(int rows) {
{
return _jump(rows); return _jump(rows);
} }
} // namespace } // namespace
AyuUi::FontSelectorBox::FontSelectorBox(QWidget *, Window::SessionController *controller, Fn<void(QString font)> hook) AyuUi::FontSelectorBox::FontSelectorBox(QWidget *, Window::SessionController *controller, Fn<void(QString font)> hook)
: _controller(controller), _hook(hook) : _controller(controller), _hook(hook) {
{
} }
void AyuUi::FontSelectorBox::prepare() void AyuUi::FontSelectorBox::prepare() {
{ addButton(tr::lng_box_ok(),
addButton(tr::lng_box_ok(), [=] [=]
{ {
_hook(_selectedFont);
_hook(_selectedFont); _controller->show(Ui::MakeConfirmBox({
.text = tr::lng_settings_need_restart(),
.confirmed = []
{
Core::Restart();
},
.confirmText = tr::lng_settings_restart_now(),
.cancelText = tr::lng_settings_restart_later(),
}));
closeBox();
});
_controller->show(Ui::MakeConfirmBox({ addLeftButton(tr::ayu_BoxActionReset(),
.text = tr::lng_settings_need_restart(), [=]
.confirmed = [] {
{ Core::Restart(); }, _hook(qs(""));
.confirmText = tr::lng_settings_restart_now(),
.cancelText = tr::lng_settings_restart_later(),
}));
closeBox();
});
addLeftButton(tr::ayu_BoxActionReset(), [=] _controller->show(Ui::MakeConfirmBox({
{ .text = tr::lng_settings_need_restart(),
_hook(qs("")); .confirmed = []
{
_controller->show(Ui::MakeConfirmBox({ Core::Restart();
.text = tr::lng_settings_need_restart(), },
.confirmed = [] .confirmText = tr::lng_settings_restart_now(),
{ Core::Restart(); }, .cancelText = tr::lng_settings_restart_later(),
.confirmText = tr::lng_settings_restart_now(), }));
.cancelText = tr::lng_settings_restart_later(),
}));
closeBox(); closeBox();
}); });
setTitle(tr::ayu_CustomizeFontTitle()); setTitle(tr::ayu_CustomizeFontTitle());
@ -979,25 +922,27 @@ void AyuUi::FontSelectorBox::prepare()
{ {
accumulate_max(*max, height); accumulate_max(*max, height);
setDimensions(st::boxWidth, qMin(*max, st::boxMaxListHeight)); setDimensions(st::boxWidth, qMin(*max, st::boxMaxListHeight));
}, inner->lifetime()); },
inner->lifetime());
topContainer->heightValue( topContainer->heightValue(
) | rpl::start_with_next([=](int height) ) | rpl::start_with_next([=](int height)
{ {
setInnerTopSkip(height); setInnerTopSkip(height);
}, inner->lifetime()); },
inner->lifetime());
select->setSubmittedCallback([=](Qt::KeyboardModifiers) select->setSubmittedCallback([=](Qt::KeyboardModifiers)
{ {
inner->activateBySubmit(); inner->activateBySubmit();
}); });
select->setQueryChangedCallback([=](const QString &query) select->setQueryChangedCallback([=](const QString &query)
{ {
inner->filter(query); inner->filter(query);
}); });
select->setCancelledCallback([=] select->setCancelledCallback([=]
{ {
select->clearQuery(); select->clearQuery();
}); });
inner->activations( inner->activations(
) | rpl::start_with_next([=](const Font &font) ) | rpl::start_with_next([=](const Font &font)
@ -1006,7 +951,8 @@ void AyuUi::FontSelectorBox::prepare()
inner->changeChosen(font.id); inner->changeChosen(font.id);
_selectedFont = font.id; _selectedFont = font.id;
} }
}, inner->lifetime()); },
inner->lifetime());
_setInnerFocus = [=] _setInnerFocus = [=]
{ {
@ -1018,15 +964,13 @@ void AyuUi::FontSelectorBox::prepare()
}; };
} }
void AyuUi::FontSelectorBox::setupTop(not_null<Ui::VerticalLayout *> container) void AyuUi::FontSelectorBox::setupTop(not_null<Ui::VerticalLayout *> container) {
{
if (!_controller) { if (!_controller) {
return; return;
} }
} }
void AyuUi::FontSelectorBox::keyPressEvent(QKeyEvent *e) void AyuUi::FontSelectorBox::keyPressEvent(QKeyEvent *e) {
{
const auto key = e->key(); const auto key = e->key();
if (key == Qt::Key_Escape) { if (key == Qt::Key_Escape) {
closeBox(); closeBox();
@ -1036,14 +980,11 @@ void AyuUi::FontSelectorBox::keyPressEvent(QKeyEvent *e)
{ {
if (key == Qt::Key_Up) { if (key == Qt::Key_Up) {
return _jump(-1); return _jump(-1);
} } else if (key == Qt::Key_Down) {
else if (key == Qt::Key_Down) {
return _jump(1); return _jump(1);
} } else if (key == Qt::Key_PageUp) {
else if (key == Qt::Key_PageUp) {
return _jump(-rowsInPage()); return _jump(-rowsInPage());
} } else if (key == Qt::Key_PageDown) {
else if (key == Qt::Key_PageDown) {
return _jump(rowsInPage()); return _jump(rowsInPage());
} }
return Ui::ScrollToRequest(-1, -1); return Ui::ScrollToRequest(-1, -1);
@ -1053,19 +994,16 @@ void AyuUi::FontSelectorBox::keyPressEvent(QKeyEvent *e)
} }
} }
int AyuUi::FontSelectorBox::rowsInPage() const int AyuUi::FontSelectorBox::rowsInPage() const {
{
return std::max(height() / AyuUi::Rows::DefaultRowHeight(), 1); return std::max(height() / AyuUi::Rows::DefaultRowHeight(), 1);
} }
void AyuUi::FontSelectorBox::setInnerFocus() void AyuUi::FontSelectorBox::setInnerFocus() {
{
_setInnerFocus(); _setInnerFocus();
} }
base::binary_guard base::binary_guard
AyuUi::FontSelectorBox::Show(Window::SessionController *controller, const Fn<void(QString font)> hook) AyuUi::FontSelectorBox::Show(Window::SessionController *controller, const Fn<void(QString font)> hook) {
{
auto result = base::binary_guard(); auto result = base::binary_guard();
Ui::show(Box<FontSelectorBox>(controller, hook)); Ui::show(Box<FontSelectorBox>(controller, hook));

View file

@ -12,8 +12,7 @@
struct LanguageId; struct LanguageId;
struct Font; struct Font;
namespace Ui namespace Ui {
{
class MultiSelect; class MultiSelect;
struct ScrollToRequest; struct ScrollToRequest;
@ -21,16 +20,13 @@ class VerticalLayout;
} // namespace Ui } // namespace Ui
namespace Window namespace Window {
{
class SessionController; class SessionController;
} // namespace Window } // namespace Window
namespace AyuUi {
namespace AyuUi
{
class FontSelectorBox : public Ui::BoxContent class FontSelectorBox : public Ui::BoxContent
{ {
@ -38,19 +34,17 @@ public:
FontSelectorBox(QWidget *, Window::SessionController *controller, Fn<void(QString font)> hook); FontSelectorBox(QWidget *, Window::SessionController *controller, Fn<void(QString font)> hook);
void setInnerFocus() override; void setInnerFocus() override;
static base::binary_guard Show(Window::SessionController *controller, const Fn<void(QString font)> hook); static base::binary_guard Show(Window::SessionController *controller, const Fn<void(QString font)> hook);
private: private:
QString _selectedFont; QString _selectedFont;
protected: protected:
void prepare() override; void prepare() override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
private: private:
void setupTop(not_null<Ui::VerticalLayout *> container); void setupTop(not_null<Ui::VerticalLayout *> container);
[[nodiscard]] int rowsInPage() const; [[nodiscard]] int rowsInPage() const;
Window::SessionController *_controller = nullptr; Window::SessionController *_controller = nullptr;

View file

@ -10,35 +10,32 @@
#include <QGuiApplication> #include <QGuiApplication>
#include "styles/style_ayu_styles.h" #include "styles/style_ayu_styles.h"
#include "boxes/abstract_box.h" #include "lang_auto.h"
#include "theme_selector_box.h"
#include "ayu/ayu_settings.h"
#include "ayu/ui/components/image_view.h" #include "ayu/ui/components/image_view.h"
#include "boxes/abstract_box.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "lang_auto.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/vertical_list.h"
#include "theme_selector_box.h"
#include "ayu/ayu_settings.h"
MessageShotBox::MessageShotBox( MessageShotBox::MessageShotBox(
QWidget *parent, QWidget *parent,
AyuFeatures::MessageShot::ShotConfig config) AyuFeatures::MessageShot::ShotConfig config)
: _config(std::move(config)) : _config(std::move(config)) {
{
} }
void MessageShotBox::prepare() void MessageShotBox::prepare() {
{
setupContent(); setupContent();
} }
void MessageShotBox::setupContent() void MessageShotBox::setupContent() {
{
_selectedPalette = std::make_shared<style::palette>(); _selectedPalette = std::make_shared<style::palette>();
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
@ -70,7 +67,7 @@ void MessageShotBox::setupContent()
}; };
auto selectedTheme = auto selectedTheme =
content->lifetime().make_state<rpl::variable<QString> >(tr::ayu_MessageShotThemeDefault(tr::now)); content->lifetime().make_state<rpl::variable<QString>>(tr::ayu_MessageShotThemeDefault(tr::now));
AddButtonWithLabel( AddButtonWithLabel(
content, content,
@ -163,24 +160,24 @@ void MessageShotBox::setupContent()
AddSkip(content); AddSkip(content);
addButton(tr::ayu_MessageShotSave(), addButton(tr::ayu_MessageShotSave(),
[=] [=]
{ {
const auto image = imageView->getImage(); const auto image = imageView->getImage();
const auto path = QFileDialog::getSaveFileName( const auto path = QFileDialog::getSaveFileName(
this, this,
tr::lng_save_file(tr::now), tr::lng_save_file(tr::now),
QString(), QString(),
"*.png"); "*.png");
if (!path.isEmpty()) { if (!path.isEmpty()) {
image.save(path); image.save(path);
} }
}); });
addButton(tr::ayu_MessageShotCopy(), addButton(tr::ayu_MessageShotCopy(),
[=] [=]
{ {
QGuiApplication::clipboard()->setImage(imageView->getImage()); QGuiApplication::clipboard()->setImage(imageView->getImage());
}); });
updatePreview(); updatePreview();

View file

@ -9,9 +9,10 @@
#include "ayu/features/messageshot/message_shot.h" #include "ayu/features/messageshot/message_shot.h"
#include "ui/layers/box_content.h" #include "ui/layers/box_content.h"
class MessageShotBox : public Ui::BoxContent { class MessageShotBox : public Ui::BoxContent
{
public: public:
MessageShotBox(QWidget* parent, AyuFeatures::MessageShot::ShotConfig config); MessageShotBox(QWidget *parent, AyuFeatures::MessageShot::ShotConfig config);
protected: protected:
void prepare() override; void prepare() override;
@ -21,5 +22,4 @@ private:
AyuFeatures::MessageShot::ShotConfig _config; AyuFeatures::MessageShot::ShotConfig _config;
std::shared_ptr<style::palette> _selectedPalette; std::shared_ptr<style::palette> _selectedPalette;
}; };

View file

@ -14,19 +14,16 @@
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
namespace AyuUi namespace AyuUi {
{
ServerReadConfirmationBox::ServerReadConfirmationBox( ServerReadConfirmationBox::ServerReadConfirmationBox(
QWidget *, QWidget *,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller)
: _controller(controller) : _controller(controller) {
{
// //
} }
void ServerReadConfirmationBox::prepare() void ServerReadConfirmationBox::prepare() {
{
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel); _text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
auto fullHeight = st::boxPadding.top() auto fullHeight = st::boxPadding.top()
@ -35,25 +32,27 @@ void ServerReadConfirmationBox::prepare()
setDimensions(st::boxWidth, fullHeight); setDimensions(st::boxWidth, fullHeight);
addButton(tr::ayu_ReadConfirmationBoxActionText(), [=, this] addButton(tr::ayu_ReadConfirmationBoxActionText(),
{ [=, this]
ReadAllPeers(); {
closeBox(); ReadAllPeers();
}); closeBox();
addButton(tr::lng_cancel(), [=, this] });
{ closeBox(); }); addButton(tr::lng_cancel(),
[=, this]
{
closeBox();
});
} }
void ServerReadConfirmationBox::resizeEvent(QResizeEvent *e) void ServerReadConfirmationBox::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 ServerReadConfirmationBox::ReadAllPeers() void ServerReadConfirmationBox::ReadAllPeers() {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
auto prev = settings->sendReadMessages; auto prev = settings->sendReadMessages;
settings->set_sendReadMessages(true); settings->set_sendReadMessages(true);

View file

@ -9,8 +9,7 @@
#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 ServerReadConfirmationBox : public Ui::BoxContent class ServerReadConfirmationBox : public Ui::BoxContent
{ {

View file

@ -6,48 +6,43 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "theme_selector_box.h" #include "theme_selector_box.h"
#include "lang_auto.h"
#include "ayu/features/messageshot/message_shot.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "lang_auto.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_chat.h" #include "settings/settings_chat.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/themes/window_theme_preview.h"
#include "ui/vertical_list.h"
#include "window/themes/window_themes_cloud_list.h" #include "window/themes/window_themes_cloud_list.h"
#include "ayu/features/messageshot/message_shot.h" #include "window/themes/window_theme_preview.h"
ThemeSelectorBox::ThemeSelectorBox( ThemeSelectorBox::ThemeSelectorBox(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller)
: _controller(controller) : _controller(controller) {
{
} }
rpl::producer<style::palette> ThemeSelectorBox::paletteSelected() rpl::producer<style::palette> ThemeSelectorBox::paletteSelected() {
{
return _palettes.events(); return _palettes.events();
} }
rpl::producer<QString> ThemeSelectorBox::themeNameChanged() rpl::producer<QString> ThemeSelectorBox::themeNameChanged() {
{
return _themeNames.events(); return _themeNames.events();
} }
void ThemeSelectorBox::prepare() void ThemeSelectorBox::prepare() {
{
setupContent(); setupContent();
} }
void ThemeSelectorBox::setupContent() void ThemeSelectorBox::setupContent() {
{
using namespace Settings; using namespace Settings;
setTitle(tr::ayu_MessageShotThemeSelectTitle()); setTitle(tr::ayu_MessageShotThemeSelectTitle());
@ -70,7 +65,7 @@ void ThemeSelectorBox::setupContent()
using namespace rpl::mappers; using namespace rpl::mappers;
const auto wrap = container->add( const auto wrap = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout> >( object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container, container,
object_ptr<Ui::VerticalLayout>(container)) object_ptr<Ui::VerticalLayout>(container))
)->setDuration(0); )->setDuration(0);
@ -91,13 +86,13 @@ void ThemeSelectorBox::setupContent()
inner->widthValue(), inner->widthValue(),
showAll->widthValue() showAll->widthValue()
) | rpl::start_with_next([=](int top, int outerWidth, int width) ) | rpl::start_with_next([=](int top, int outerWidth, int width)
{ {
showAll->moveToRight( showAll->moveToRight(
st::defaultSubsectionTitlePadding.left(), st::defaultSubsectionTitlePadding.left(),
top, top,
outerWidth); outerWidth);
}, },
showAll->lifetime()); showAll->lifetime());
Ui::AddSkip(inner, st::settingsThemesTopSkip); Ui::AddSkip(inner, st::settingsThemesTopSkip);
@ -114,10 +109,10 @@ void ThemeSelectorBox::setupContent()
list->allShown( list->allShown(
) | rpl::start_with_next([=](bool shown) ) | rpl::start_with_next([=](bool shown)
{ {
showAll->setVisible(!shown); showAll->setVisible(!shown);
}, },
showAll->lifetime()); showAll->lifetime());
showAll->addClickHandler([=] showAll->addClickHandler([=]
{ {
@ -154,8 +149,7 @@ void ThemeSelectorBox::setupContent()
if (documentView->loaded()) { if (documentView->loaded()) {
innerCallback(); innerCallback();
} } else {
else {
_controller->session().downloaderTaskFinished( _controller->session().downloaderTaskFinished(
) | rpl::filter( ) | rpl::filter(
[=] [=]
@ -173,18 +167,18 @@ void ThemeSelectorBox::setupContent()
AyuFeatures::MessageShot::paletteChosen( AyuFeatures::MessageShot::paletteChosen(
) | rpl::start_with_next([=](const auto &palette) ) | rpl::start_with_next([=](const auto &palette)
{ {
_themeNames.fire(tr::ayu_MessageShotThemeDefault(tr::now)); _themeNames.fire(tr::ayu_MessageShotThemeDefault(tr::now));
_selectedPalette = palette; _selectedPalette = palette;
}, },
lifetime()); lifetime());
addButton(tr::ayu_MessageShotThemeApply(), addButton(tr::ayu_MessageShotThemeApply(),
[=] [=]
{ {
_palettes.fire(std::move(_selectedPalette)); _palettes.fire(std::move(_selectedPalette));
closeBox(); closeBox();
}); });
setDimensionsToContent(st::boxWidth, container); setDimensionsToContent(st::boxWidth, container);
} }

View file

@ -6,15 +6,16 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "ui/style/style_core_palette.h"
#include "ui/layers/box_content.h" #include "ui/layers/box_content.h"
#include "ui/style/style_core_palette.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
using Callback = Fn<void(style::palette&)>; using Callback = Fn<void(style::palette &)>;
class ThemeSelectorBox : public Ui::BoxContent { class ThemeSelectorBox : public Ui::BoxContent
{
public: public:
ThemeSelectorBox(QWidget* parent, not_null<Window::SessionController*> controller); ThemeSelectorBox(QWidget *parent, not_null<Window::SessionController *> controller);
rpl::producer<style::palette> paletteSelected(); rpl::producer<style::palette> paletteSelected();
rpl::producer<QString> themeNameChanged(); rpl::producer<QString> themeNameChanged();
@ -25,11 +26,10 @@ protected:
private: private:
void setupContent(); void setupContent();
not_null<Window::SessionController*> _controller; not_null<Window::SessionController *> _controller;
rpl::event_stream<style::palette> _palettes; rpl::event_stream<style::palette> _palettes;
rpl::event_stream<QString> _themeNames; rpl::event_stream<QString> _themeNames;
style::palette _selectedPalette; style::palette _selectedPalette;
}; };

View file

@ -10,21 +10,20 @@
#include "ayu/utils/telegram_helpers.h" #include "ayu/utils/telegram_helpers.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "window/themes/window_theme.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "window/themes/window_theme.h"
ImageView::ImageView(QWidget *parent) ImageView::ImageView(QWidget *parent)
: RpWidget(parent) : RpWidget(parent) {
{
} }
void ImageView::setImage(const QImage &image) void ImageView::setImage(const QImage &image) {
{
if (this->image == image) { if (this->image == image) {
return; return;
} }
const auto set = [=] { const auto set = [=]
{
this->prevImage = this->image; this->prevImage = this->image;
this->image = image; this->image = image;
@ -41,7 +40,13 @@ void ImageView::setImage(const QImage &image)
this->animation.start( this->animation.start(
[=] [=]
{ update(); }, 0.0, 1.0, 300, anim::easeInCubic); {
update();
},
0.0,
1.0,
300,
anim::easeInCubic);
}; };
if (this->image.isNull()) { if (this->image.isNull()) {
@ -52,22 +57,19 @@ void ImageView::setImage(const QImage &image)
dispatchToMainThread(set, 100); dispatchToMainThread(set, 100);
} }
QImage ImageView::getImage() const QImage ImageView::getImage() const {
{
return image; return image;
} }
void ImageView::paintEvent(QPaintEvent *e) void ImageView::paintEvent(QPaintEvent *e) {
{
Painter p(this); Painter p(this);
// PainterHighQualityEnabler hq(p); // PainterHighQualityEnabler hq(p);
auto brush = QBrush(st::boxBg); // copy auto brush = QBrush(st::boxBg); // copy
if (Window::Theme::IsNightMode()) { if (Window::Theme::IsNightMode()) {
brush.setColor(brush.color().lighter(120)); brush.setColor(brush.color().lighter(120));
} } else {
else {
brush.setColor(brush.color().darker(105)); brush.setColor(brush.color().darker(105));
} }
@ -107,6 +109,5 @@ void ImageView::paintEvent(QPaintEvent *e)
} }
} }
void ImageView::mousePressEvent(QMouseEvent *e) void ImageView::mousePressEvent(QMouseEvent *e) {
{
} }

View file

@ -6,7 +6,6 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
@ -15,7 +14,7 @@ class ImageView : public Ui::RpWidget
public: public:
ImageView(QWidget *parent); ImageView(QWidget *parent);
void setImage(const QImage& image); void setImage(const QImage &image);
QImage getImage() const; QImage getImage() const;
protected: protected:

View file

@ -5,87 +5,94 @@
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ayu/ui/context_menu/context_menu.h" #include "ayu/ui/context_menu/context_menu.h"
#include "ayu/utils/qt_key_modifiers_extended.h"
#include "history/history_item_components.h" #include <styles/style_menu_icons.h>
#include "lang_auto.h" #include "lang_auto.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "ayu/ayu_settings.h"
#include "ayu/ayu_state.h" #include "ayu/ayu_state.h"
#include "ayu/messages/ayu_messages_controller.h" #include "ayu/messages/ayu_messages_controller.h"
#include "ayu/ui/context_menu/menu_item_subtext.h" #include "ayu/ui/context_menu/menu_item_subtext.h"
#include "ayu/utils/qt_key_modifiers_extended.h"
#include "history/history_item_components.h"
#include "mainwidget.h"
#include "core/mime_type.h" #include "core/mime_type.h"
#include "styles/style_ayu_icons.h" #include "styles/style_ayu_icons.h"
#include "window/window_peer_menu.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "window/window_peer_menu.h"
#include "ayu/ui/sections/edited/edited_log_section.h" #include "ayu/ui/sections/edited/edited_log_section.h"
#include "ayu/utils/telegram_helpers.h" #include "ayu/utils/telegram_helpers.h"
#include "base/unixtime.h"
#include "history/view/history_view_element.h"
#include "window/window_session_controller.h"
namespace AyuUi {
namespace AyuUi bool needToShowItem(int state) {
{
bool needToShowItem(int state)
{
return state == 1 || state == 2 && base::IsExtendedContextMenuModifierPressed(); return state == 1 || state == 2 && base::IsExtendedContextMenuModifierPressed();
} }
void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) {
{
if (AyuMessages::getInstance().hasRevisions(item)) { if (AyuMessages::getInstance().hasRevisions(item)) {
menu->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=] menu->addAction(tr::ayu_EditsHistoryMenuText(tr::now),
{ [=]
item->history()->session().tryResolveWindow() {
->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item)); item->history()->session().tryResolveWindow()
}, &st::ayuEditsHistoryIcon); ->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item));
},
&st::ayuEditsHistoryIcon);
} }
} }
void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) {
{
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!needToShowItem(settings->showHideMessageInContextMenu)) { if (!needToShowItem(settings->showHideMessageInContextMenu)) {
return; return;
} }
const auto history = item->history(); const auto history = item->history();
menu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]() menu->addAction(tr::ayu_ContextHideMessage(tr::now),
{ [=]()
item->destroy(); {
history->requestChatListMessage(); item->destroy();
history->requestChatListMessage();
AyuState::hide(item); AyuState::hide(item);
}, &st::menuIconClear); },
&st::menuIconClear);
} }
void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) {
{
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!needToShowItem(settings->showUserMessagesInContextMenu)) { if (!needToShowItem(settings->showUserMessagesInContextMenu)) {
return; return;
} }
if (item->history()->peer->isChat() || item->history()->peer->isMegagroup()) { if (item->history()->peer->isChat() || item->history()->peer->isMegagroup()) {
menu->addAction(tr::ayu_UserMessagesMenuText(tr::now), [=] menu->addAction(tr::ayu_UserMessagesMenuText(tr::now),
{ [=]
if (const auto window = item->history()->session().tryResolveWindow()) { {
if (const auto mainWidget = window->widget()->sessionController()) { if (const auto window = item->history()->session().tryResolveWindow()) {
const auto peer = item->history()->peer; if (const auto mainWidget = window->widget()->sessionController()) {
const auto key = (peer && !peer->isUser()) const auto peer = item->history()->peer;
? item->topic() const auto key = (peer && !peer->isUser())
? Dialogs::Key{item->topic()} ? item->topic()
: Dialogs::Key{item->history()} ? Dialogs::Key{item->topic()}
: Dialogs::Key(); : Dialogs::Key{item->history()}
mainWidget->content()->searchMessages(QString(), key, item->from()->asUser()); : Dialogs::Key();
} mainWidget->content()->searchMessages(QString(), key, item->from()->asUser());
} }
}, &st::menuIconTTL); }
},
&st::menuIconTTL);
} }
} }
void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) {
{
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!needToShowItem(settings->showMessageDetailsInContextMenu)) { if (!needToShowItem(settings->showMessageDetailsInContextMenu)) {
return; return;
@ -110,8 +117,9 @@ void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma ide diagnostic ignored "NullDereference" #pragma ide diagnostic ignored "NullDereference"
const auto messageForwardedDate = const auto messageForwardedDate =
isForwarded ? base::unixtime::parse(forwarded->originalDate) isForwarded
: QDateTime(); ? base::unixtime::parse(forwarded->originalDate)
: QDateTime();
#pragma clang diagnostic pop #pragma clang diagnostic pop
const auto const auto
@ -127,14 +135,14 @@ void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
const auto hasAnyPostField = const auto hasAnyPostField =
!messageViews.isEmpty() || !messageViews.isEmpty() ||
!messageForwards.isEmpty(); !messageForwards.isEmpty();
const auto hasAnyMediaField = const auto hasAnyMediaField =
!mediaSize.isEmpty() || !mediaSize.isEmpty() ||
!mediaMime.isEmpty() || !mediaMime.isEmpty() ||
!mediaName.isEmpty() || !mediaName.isEmpty() ||
!mediaResolution.isEmpty() || !mediaResolution.isEmpty() ||
!mediaDC.isEmpty(); !mediaDC.isEmpty();
const auto callback = Ui::Menu::CreateAddActionCallback(menu); const auto callback = Ui::Menu::CreateAddActionCallback(menu);
@ -270,8 +278,7 @@ void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
}); });
} }
void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item) {
{
if (item->isLocal()) { if (item->isLocal()) {
return; return;
} }
@ -281,10 +288,12 @@ void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item)
return; return;
} }
menu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]() menu->addAction(tr::ayu_ReadUntilMenuText(tr::now),
{ [=]()
readHistory(item); {
}, &st::menuIconShowInChat); readHistory(item);
},
&st::menuIconShowInChat);
} }
} // namespace AyuUi } // namespace AyuUi

View file

@ -6,95 +6,17 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "mainwindow.h"
#include "base/call_delayed.h"
#include "base/unixtime.h"
#include "base/platform/base_platform_info.h"
#include "base/qt/qt_common_adapters.h"
#include "base/qt/qt_key_modifiers.h"
#include "boxes/about_sponsored_box.h"
#include "boxes/delete_messages_box.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_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 "main/main_session.h"
#include "main/main_session_settings.h"
#include "main/session/send_as_peers.h"
#include "menu/menu_item_download_files.h"
#include "settings/settings_premium.h"
#include "styles/style_chat.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 "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" namespace AyuUi {
#include "ayu/ayu_settings.h"
#include "ayu/utils/qt_key_modifiers_extended.h"
#include "styles/style_info.h"
namespace AyuUi
{
bool needToShowItem(int state); bool needToShowItem(int state);
void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item); void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item); void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item); void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item); void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item); void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
} }

View file

@ -8,25 +8,23 @@
#include "ayu/ui/context_menu/menu_item_subtext.h" #include "ayu/ui/context_menu/menu_item_subtext.h"
#include "ayu/utils/telegram_helpers.h"
#include "ayu/database/entities.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "qguiapplication.h" #include "qguiapplication.h"
#include "ayu/database/entities.h"
#include "ayu/utils/telegram_helpers.h"
#include "ui/widgets/menu/menu_action.h" #include "base/unixtime.h"
#include "ui/effects/ripple_animation.h"
#include "ui/painter.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "base/unixtime.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "ui/painter.h"
#include "ui/effects/ripple_animation.h"
#include "ui/widgets/menu/menu_action.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
namespace Ui namespace Ui {
{ namespace {
namespace
{
class ActionWithSubText : public Menu::ItemBase class ActionWithSubText : public Menu::ItemBase
{ {
@ -95,10 +93,9 @@ ActionWithSubText::ActionWithSubText(
_icon(icon), _icon(icon),
_subText(std::move(subtext)), _subText(std::move(subtext)),
_height(st::ttlItemPadding.top() _height(st::ttlItemPadding.top()
+ _st.itemStyle.font->height + _st.itemStyle.font->height
+ st::ttlItemTimerFont->height + st::ttlItemTimerFont->height
+ st::ttlItemPadding.bottom()) + st::ttlItemPadding.bottom()) {
{
setAcceptBoth(true); setAcceptBoth(true);
initResizeHook(parent->sizeValue()); initResizeHook(parent->sizeValue());
setClickedCallback(std::move(callback)); setClickedCallback(std::move(callback));
@ -108,14 +105,14 @@ ActionWithSubText::ActionWithSubText(
{ {
Painter p(this); Painter p(this);
paint(p); paint(p);
}, lifetime()); },
lifetime());
enableMouseSelecting(); enableMouseSelecting();
prepare(title); prepare(title);
} }
void ActionWithSubText::paint(Painter &p) void ActionWithSubText::paint(Painter &p) {
{
const auto selected = isSelected(); const auto selected = isSelected();
if (selected && _st.itemBgOver->c.alpha() < 255) { if (selected && _st.itemBgOver->c.alpha() < 255) {
p.fillRect(0, 0, width(), _height, _st.itemBg); p.fillRect(0, 0, width(), _height, _st.itemBg);
@ -151,8 +148,7 @@ void ActionWithSubText::paint(Painter &p)
_subText); _subText);
} }
void ActionWithSubText::prepare(const QString &title) void ActionWithSubText::prepare(const QString &title) {
{
_title.setMarkedText( _title.setMarkedText(
_st.itemStyle, _st.itemStyle,
{title}, {title},
@ -176,33 +172,27 @@ void ActionWithSubText::prepare(const QString &title)
update(); update();
} }
bool ActionWithSubText::isEnabled() const bool ActionWithSubText::isEnabled() const {
{
return true; return true;
} }
not_null<QAction *> ActionWithSubText::action() const not_null<QAction *> ActionWithSubText::action() const {
{
return _dummyAction; return _dummyAction;
} }
QPoint ActionWithSubText::prepareRippleStartPosition() const QPoint ActionWithSubText::prepareRippleStartPosition() const {
{
return mapFromGlobal(QCursor::pos()); return mapFromGlobal(QCursor::pos());
} }
QImage ActionWithSubText::prepareRippleMask() const QImage ActionWithSubText::prepareRippleMask() const {
{
return Ui::RippleAnimation::RectMask(size()); return Ui::RippleAnimation::RectMask(size());
} }
int ActionWithSubText::contentHeight() const int ActionWithSubText::contentHeight() const {
{
return _height; return _height;
} }
void ActionWithSubText::handleKeyPress(not_null<QKeyEvent *> e) void ActionWithSubText::handleKeyPress(not_null<QKeyEvent *> e) {
{
if (!isSelected()) { if (!isSelected()) {
return; return;
} }
@ -215,64 +205,69 @@ void ActionWithSubText::handleKeyPress(not_null<QKeyEvent *> e)
ActionStickerPackAuthor::ActionStickerPackAuthor(not_null<Menu::Menu *> menu, ActionStickerPackAuthor::ActionStickerPackAuthor(not_null<Menu::Menu *> menu,
not_null<Main::Session *> session, not_null<Main::Session *> session,
ID authorId) ID authorId)
: ActionWithSubText(menu, menu->st(), st::menuIconStickers, [=] : ActionWithSubText(menu,
{ }, tr::ayu_MessageDetailsPackOwnerPC(tr::now), QString(tr::ayu_MessageDetailsPackOwnerFetchingPC(tr::now))), menu->st(),
_session(session) st::menuIconStickers,
{ [=]
{
},
tr::ayu_MessageDetailsPackOwnerPC(tr::now),
QString(tr::ayu_MessageDetailsPackOwnerFetchingPC(tr::now))),
_session(session) {
searchAuthor(authorId); searchAuthor(authorId);
} }
void ActionStickerPackAuthor::searchAuthor(ID authorId) void ActionStickerPackAuthor::searchAuthor(ID authorId) {
{
const auto pointer = Ui::MakeWeak(this); const auto pointer = Ui::MakeWeak(this);
searchById(authorId, _session, [=](const QString &username, UserData *user) searchById(authorId,
{ _session,
if (!pointer) { [=](const QString &username, UserData *user)
LOG(("ContextActionStickerAuthor: searchById callback after destruction")); {
return; if (!pointer) {
} LOG(("ContextActionStickerAuthor: searchById callback after destruction"));
if (username.isEmpty() && !user) { return;
_subText = QString(tr::ayu_MessageDetailsPackOwnerNotFoundPC(tr::now)); }
setClickedCallback( if (username.isEmpty() && !user) {
[=] _subText = QString(tr::ayu_MessageDetailsPackOwnerNotFoundPC(tr::now));
{ setClickedCallback(
const auto text = [=]
QString("int32: %1\nint64: %2").arg(authorId).arg(0x100000000L + authorId); {
QGuiApplication::clipboard()->setText(text); const auto text =
}); QString("int32: %1\nint64: %2").arg(authorId).arg(0x100000000L + authorId);
QGuiApplication::clipboard()->setText(text);
});
crl::on_main( crl::on_main(
[=] [=]
{ {
update(); update();
}); });
return; return;
} }
const auto title = username.isEmpty() ? user ? user->name() : QString() : username; const auto title = username.isEmpty() ? user ? user->name() : QString() : username;
const auto callback = [=] const auto callback = [=]
{ {
if (user) { if (user) {
if (const auto window = _session->tryResolveWindow()) { if (const auto window = _session->tryResolveWindow()) {
if (const auto mainWidget = window->widget()->sessionController()) { if (const auto mainWidget = window->widget()->sessionController()) {
mainWidget->showPeer(user); mainWidget->showPeer(user);
} }
} }
} } else {
else { QGuiApplication::clipboard()->setText(title);
QGuiApplication::clipboard()->setText(title); }
} };
};
setClickedCallback(callback); setClickedCallback(callback);
_subText = QString(title); _subText = QString(title);
crl::on_main( crl::on_main(
[=] [=]
{ {
update(); update();
}); });
}); });
} }
} // namespace } // namespace
@ -282,8 +277,7 @@ base::unique_qptr<Menu::ItemBase> ContextActionWithSubText(
const style::icon &icon, const style::icon &icon,
const QString &title, const QString &title,
const QString &subtext, const QString &subtext,
Fn<void()> callback) Fn<void()> callback) {
{
if (!callback) { if (!callback) {
callback = [=]() callback = [=]()
{ {
@ -303,8 +297,7 @@ base::unique_qptr<Menu::ItemBase> ContextActionWithSubText(
base::unique_qptr<Menu::ItemBase> ContextActionStickerAuthor( base::unique_qptr<Menu::ItemBase> ContextActionStickerAuthor(
not_null<Menu::Menu *> menu, not_null<Menu::Menu *> menu,
not_null<Main::Session *> session, not_null<Main::Session *> session,
ID authorId) ID authorId) {
{
return base::make_unique_q<ActionStickerPackAuthor>(menu, session, authorId); return base::make_unique_q<ActionStickerPackAuthor>(menu, session, authorId);
} }

View file

@ -11,10 +11,8 @@
#include "base/unique_qptr.h" #include "base/unique_qptr.h"
namespace Ui namespace Ui {
{ namespace Menu {
namespace Menu
{
class Menu; class Menu;
class ItemBase; class ItemBase;
} // namespace Menu } // namespace Menu

View file

@ -6,25 +6,23 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "history/view/history_view_element.h"
#include "ayu/ui/sections/edited/edited_log_item.h" #include "ayu/ui/sections/edited/edited_log_item.h"
#include "ayu/ui/sections/edited/edited_log_section.h" #include "ayu/ui/sections/edited/edited_log_section.h"
#include "base/timer.h"
#include "history/view/history_view_element.h"
#include "menu/menu_antispam_validator.h" #include "menu/menu_antispam_validator.h"
#include "mtproto/sender.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/widgets/tooltip.h" #include "ui/widgets/tooltip.h"
#include "mtproto/sender.h"
#include "base/timer.h"
struct ChatRestrictionsInfo; struct ChatRestrictionsInfo;
namespace Main namespace Main {
{
class Session; class Session;
} // namespace Main } // namespace Main
namespace HistoryView namespace HistoryView {
{
class Element; class Element;
struct TextState; struct TextState;
struct StateRequest; struct StateRequest;
@ -32,20 +30,17 @@ enum class CursorState : char;
enum class PointState : char; enum class PointState : char;
} // namespace HistoryView } // namespace HistoryView
namespace Ui namespace Ui {
{
class PopupMenu; class PopupMenu;
class ChatStyle; class ChatStyle;
struct PeerUserpicView; struct PeerUserpicView;
} // namespace Ui } // namespace Ui
namespace Window namespace Window {
{
class SessionController; class SessionController;
} // namespace Window } // namespace Window
namespace EditedLog namespace EditedLog {
{
class SectionMemento; class SectionMemento;
@ -60,23 +55,21 @@ public:
not_null<HistoryItem *> item); not_null<HistoryItem *> item);
[[nodiscard]] Main::Session &session() const; [[nodiscard]] Main::Session &session() const;
[[nodiscard]] not_null<Ui::ChatTheme *> theme() const
{ [[nodiscard]] not_null<Ui::ChatTheme *> theme() const {
return _theme.get(); return _theme.get();
} }
[[nodiscard]] rpl::producer<int> scrollToSignal() const; [[nodiscard]] rpl::producer<int> scrollToSignal() const;
[[nodiscard]] not_null<PeerData *> channel() const [[nodiscard]] not_null<PeerData *> channel() const {
{
return _peer; return _peer;
} }
// Set the correct scroll position after being resized. // Set the correct scroll position after being resized.
void restoreScrollPosition(); void restoreScrollPosition();
void resizeToWidth(int newWidth, int minHeight) void resizeToWidth(int newWidth, int minHeight) {
{
_minHeight = minHeight; _minHeight = minHeight;
return TWidget::resizeToWidth(newWidth); return TWidget::resizeToWidth(newWidth);
} }
@ -161,11 +154,13 @@ protected:
private: private:
using Element = HistoryView::Element; using Element = HistoryView::Element;
enum class Direction enum class Direction
{ {
Up, Up,
Down, Down,
}; };
enum class MouseAction enum class MouseAction
{ {
None, None,
@ -173,11 +168,13 @@ private:
Dragging, Dragging,
Selecting, Selecting,
}; };
enum class EnumItemsDirection enum class EnumItemsDirection
{ {
TopToBottom, TopToBottom,
BottomToTop, BottomToTop,
}; };
using TextState = HistoryView::TextState; using TextState = HistoryView::TextState;
using CursorState = HistoryView::CursorState; using CursorState = HistoryView::CursorState;
using PointState = HistoryView::PointState; using PointState = HistoryView::PointState;

View file

@ -4,40 +4,31 @@
// but be respectful and credit the original author. // but be respectful and credit the original author.
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include <ayu/database/entities.h>
#include "ayu/ui/sections/edited/edited_log_item.h" #include "ayu/ui/sections/edited/edited_log_item.h"
#include <ayu/database/entities.h>
#include "ayu/ui/sections/edited/edited_log_inner.h"
#include "history/view/history_view_element.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "history/history_location_manager.h"
#include "api/api_chat_participants.h" #include "api/api_chat_participants.h"
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "data/data_channel.h" #include "ayu/ui/sections/edited/edited_log_inner.h"
#include "data/data_file_origin.h"
#include "data/data_forum_topic.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "data/data_message_reaction_id.h"
#include "data/stickers/data_custom_emoji.h"
#include "lang/lang_keys.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/basic_click_handlers.h"
#include "boxes/sticker_set_box.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "data/data_channel.h"
#include "data/data_file_origin.h"
#include "data/data_forum_topic.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "history/view/history_view_element.h"
#include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/notifications_manager.h" #include "ui/basic_click_handlers.h"
#include "window/window_session_controller.h" #include "ui/text/text_utilities.h"
namespace EditedLog namespace EditedLog {
{ namespace {
namespace
{
const auto CollectChanges = []( const auto CollectChanges = [](
auto &phraseMap, auto &phraseMap,
@ -63,8 +54,7 @@ TextWithEntities GenerateAdminChangeText(
not_null<ChannelData *> channel, not_null<ChannelData *> channel,
const TextWithEntities &user, const TextWithEntities &user,
ChatAdminRightsInfo newRights, ChatAdminRightsInfo newRights,
ChatAdminRightsInfo prevRights) ChatAdminRightsInfo prevRights) {
{
using Flag = ChatAdminRight; using Flag = ChatAdminRight;
using Flags = ChatAdminRights; using Flags = ChatAdminRights;
@ -77,11 +67,11 @@ TextWithEntities GenerateAdminChangeText(
const auto useInviteLinkPhrase = channel->isMegagroup() const auto useInviteLinkPhrase = channel->isMegagroup()
&& channel->anyoneCanAddMembers(); && channel->anyoneCanAddMembers();
const auto invitePhrase = useInviteLinkPhrase const auto invitePhrase = useInviteLinkPhrase
? tr::lng_admin_log_admin_invite_link ? tr::lng_admin_log_admin_invite_link
: tr::lng_admin_log_admin_invite_users; : tr::lng_admin_log_admin_invite_users;
const auto callPhrase = channel->isBroadcast() const auto callPhrase = channel->isBroadcast()
? tr::lng_admin_log_admin_manage_calls_channel ? tr::lng_admin_log_admin_manage_calls_channel
: tr::lng_admin_log_admin_manage_calls; : tr::lng_admin_log_admin_manage_calls;
static auto phraseMap = std::map<Flags, tr::phrase<>>{ static auto phraseMap = std::map<Flags, tr::phrase<>>{
{Flag::ChangeInfo, tr::lng_admin_log_admin_change_info}, {Flag::ChangeInfo, tr::lng_admin_log_admin_change_info},
{Flag::PostMessages, tr::lng_admin_log_admin_post_messages}, {Flag::PostMessages, tr::lng_admin_log_admin_post_messages},
@ -117,8 +107,7 @@ TextWithEntities GenerateAdminChangeText(
QString GeneratePermissionsChangeText( QString GeneratePermissionsChangeText(
ChatRestrictionsInfo newRights, ChatRestrictionsInfo newRights,
ChatRestrictionsInfo prevRights) ChatRestrictionsInfo prevRights) {
{
using Flag = ChatRestriction; using Flag = ChatRestriction;
using Flags = ChatRestrictions; using Flags = ChatRestrictions;
@ -131,14 +120,19 @@ QString GeneratePermissionsChangeText(
{Flag::SendFiles, tr::lng_admin_log_banned_send_files}, {Flag::SendFiles, tr::lng_admin_log_banned_send_files},
{ {
Flag::SendVoiceMessages, Flag::SendVoiceMessages,
tr::lng_admin_log_banned_send_voice_messages}, tr::lng_admin_log_banned_send_voice_messages
},
{ {
Flag::SendVideoMessages, Flag::SendVideoMessages,
tr::lng_admin_log_banned_send_video_messages}, tr::lng_admin_log_banned_send_video_messages
{Flag::SendStickers },
| Flag::SendGifs {
| Flag::SendInline Flag::SendStickers
| Flag::SendGames, tr::lng_admin_log_banned_send_stickers}, | Flag::SendGifs
| Flag::SendInline
| Flag::SendGames,
tr::lng_admin_log_banned_send_stickers
},
{Flag::EmbedLinks, tr::lng_admin_log_banned_embed_links}, {Flag::EmbedLinks, tr::lng_admin_log_banned_embed_links},
{Flag::SendPolls, tr::lng_admin_log_banned_send_polls}, {Flag::SendPolls, tr::lng_admin_log_banned_send_polls},
{Flag::ChangeInfo, tr::lng_admin_log_admin_change_info}, {Flag::ChangeInfo, tr::lng_admin_log_admin_change_info},
@ -153,8 +147,7 @@ TextWithEntities GeneratePermissionsChangeText(
PeerId participantId, PeerId participantId,
const TextWithEntities &user, const TextWithEntities &user,
ChatRestrictionsInfo newRights, ChatRestrictionsInfo newRights,
ChatRestrictionsInfo prevRights) ChatRestrictionsInfo prevRights) {
{
using Flag = ChatRestriction; using Flag = ChatRestriction;
const auto newFlags = newRights.flags; const auto newFlags = newRights.flags;
@ -167,8 +160,7 @@ TextWithEntities GeneratePermissionsChangeText(
lt_user, lt_user,
user, user,
Ui::Text::WithEntities); Ui::Text::WithEntities);
} } else if (newFlags == 0
else if (newFlags == 0
&& (prevFlags & Flag::ViewMessages) && (prevFlags & Flag::ViewMessages)
&& !peerIsUser(participantId)) { && !peerIsUser(participantId)) {
return tr::lng_admin_log_unbanned( return tr::lng_admin_log_unbanned(
@ -178,11 +170,11 @@ TextWithEntities GeneratePermissionsChangeText(
Ui::Text::WithEntities); Ui::Text::WithEntities);
} }
const auto untilText = indefinitely const auto untilText = indefinitely
? tr::lng_admin_log_restricted_forever(tr::now) ? tr::lng_admin_log_restricted_forever(tr::now)
: tr::lng_admin_log_restricted_until( : tr::lng_admin_log_restricted_until(
tr::now, tr::now,
lt_date, lt_date,
langDateTime(base::unixtime::parse(newUntil))); langDateTime(base::unixtime::parse(newUntil)));
auto result = tr::lng_admin_log_restricted( auto result = tr::lng_admin_log_restricted(
tr::now, tr::now,
lt_user, lt_user,
@ -197,70 +189,68 @@ TextWithEntities GeneratePermissionsChangeText(
return result; return result;
} }
QString PublicJoinLink() QString PublicJoinLink() {
{
return u"(public_join_link)"_q; return u"(public_join_link)"_q;
} }
QString ExtractInviteLink(const MTPExportedChatInvite &data) QString ExtractInviteLink(const MTPExportedChatInvite &data) {
{
return data.match([&](const MTPDchatInviteExported &data) return data.match([&](const MTPDchatInviteExported &data)
{ {
return qs(data.vlink()); return qs(data.vlink());
}, [&](const MTPDchatInvitePublicJoinRequests &data) },
[&](const MTPDchatInvitePublicJoinRequests &data)
{ {
return PublicJoinLink(); return PublicJoinLink();
}); });
} }
QString ExtractInviteLinkLabel(const MTPExportedChatInvite &data) QString ExtractInviteLinkLabel(const MTPExportedChatInvite &data) {
{
return data.match([&](const MTPDchatInviteExported &data) return data.match([&](const MTPDchatInviteExported &data)
{ {
return qs(data.vtitle().value_or_empty()); return qs(data.vtitle().value_or_empty());
}, [&](const MTPDchatInvitePublicJoinRequests &data) },
[&](const MTPDchatInvitePublicJoinRequests &data)
{ {
return PublicJoinLink(); return PublicJoinLink();
}); });
} }
QString InternalInviteLinkUrl(const MTPExportedChatInvite &data) QString InternalInviteLinkUrl(const MTPExportedChatInvite &data) {
{
const auto base64 = ExtractInviteLink(data).toUtf8().toBase64(); const auto base64 = ExtractInviteLink(data).toUtf8().toBase64();
return "internal:show_invite_link/?link=" + QString::fromLatin1(base64); return "internal:show_invite_link/?link=" + QString::fromLatin1(base64);
} }
QString GenerateInviteLinkText(const MTPExportedChatInvite &data) QString GenerateInviteLinkText(const MTPExportedChatInvite &data) {
{
const auto label = ExtractInviteLinkLabel(data); const auto label = ExtractInviteLinkLabel(data);
return label.isEmpty() ? ExtractInviteLink(data).replace( return label.isEmpty()
u"https://"_q, ? ExtractInviteLink(data).replace(
QString() u"https://"_q,
).replace( QString()
u"t.me/joinchat/"_q, ).replace(
QString() u"t.me/joinchat/"_q,
) : label; QString()
)
: label;
} }
TextWithEntities GenerateInviteLinkLink(const MTPExportedChatInvite &data) TextWithEntities GenerateInviteLinkLink(const MTPExportedChatInvite &data) {
{
const auto text = GenerateInviteLinkText(data); const auto text = GenerateInviteLinkText(data);
return text.endsWith(Ui::kQEllipsis) return text.endsWith(Ui::kQEllipsis)
? TextWithEntities{.text = text} ? TextWithEntities{.text = text}
: Ui::Text::Link(text, InternalInviteLinkUrl(data)); : Ui::Text::Link(text, InternalInviteLinkUrl(data));
} }
TextWithEntities GenerateInviteLinkChangeText( TextWithEntities GenerateInviteLinkChangeText(
const MTPExportedChatInvite &newLink, const MTPExportedChatInvite &newLink,
const MTPExportedChatInvite &prevLink) const MTPExportedChatInvite &prevLink) {
{
auto link = TextWithEntities{GenerateInviteLinkText(newLink)}; auto link = TextWithEntities{GenerateInviteLinkText(newLink)};
if (!link.text.endsWith(Ui::kQEllipsis)) { if (!link.text.endsWith(Ui::kQEllipsis)) {
link.entities.push_back({ link.entities.push_back({
EntityType::CustomUrl, EntityType::CustomUrl,
0, 0,
int(link.text.size()), int(link.text.size()),
InternalInviteLinkUrl(newLink)}); InternalInviteLinkUrl(newLink)
});
} }
auto result = tr::lng_admin_log_edited_invite_link( auto result = tr::lng_admin_log_edited_invite_link(
tr::now, tr::now,
@ -274,7 +264,8 @@ TextWithEntities GenerateInviteLinkChangeText(
return link.match([](const MTPDchatInviteExported &data) return link.match([](const MTPDchatInviteExported &data)
{ {
return qs(data.vtitle().value_or_empty()); return qs(data.vtitle().value_or_empty());
}, [&](const MTPDchatInvitePublicJoinRequests &data) },
[&](const MTPDchatInvitePublicJoinRequests &data)
{ {
return PublicJoinLink(); return PublicJoinLink();
}); });
@ -284,7 +275,8 @@ TextWithEntities GenerateInviteLinkChangeText(
return link.match([](const MTPDchatInviteExported &data) return link.match([](const MTPDchatInviteExported &data)
{ {
return data.vexpire_date().value_or_empty(); return data.vexpire_date().value_or_empty();
}, [&](const MTPDchatInvitePublicJoinRequests &data) },
[&](const MTPDchatInvitePublicJoinRequests &data)
{ {
return TimeId(); return TimeId();
}); });
@ -294,7 +286,8 @@ TextWithEntities GenerateInviteLinkChangeText(
return link.match([](const MTPDchatInviteExported &data) return link.match([](const MTPDchatInviteExported &data)
{ {
return data.vusage_limit().value_or_empty(); return data.vusage_limit().value_or_empty();
}, [&](const MTPDchatInvitePublicJoinRequests &data) },
[&](const MTPDchatInvitePublicJoinRequests &data)
{ {
return 0; return 0;
}); });
@ -304,7 +297,8 @@ TextWithEntities GenerateInviteLinkChangeText(
return link.match([](const MTPDchatInviteExported &data) return link.match([](const MTPDchatInviteExported &data)
{ {
return data.is_request_needed(); return data.is_request_needed();
}, [&](const MTPDchatInvitePublicJoinRequests &data) },
[&](const MTPDchatInvitePublicJoinRequests &data)
{ {
return true; return true;
}); });
@ -312,14 +306,14 @@ TextWithEntities GenerateInviteLinkChangeText(
const auto wrapDate = [](TimeId date) const auto wrapDate = [](TimeId date)
{ {
return date return date
? langDateTime(base::unixtime::parse(date)) ? langDateTime(base::unixtime::parse(date))
: tr::lng_group_invite_expire_never(tr::now); : tr::lng_group_invite_expire_never(tr::now);
}; };
const auto wrapUsage = [](int count) const auto wrapUsage = [](int count)
{ {
return count return count
? QString::number(count) ? QString::number(count)
: tr::lng_group_invite_usage_any(tr::now); : tr::lng_group_invite_usage_any(tr::now);
}; };
const auto wasLabel = label(prevLink); const auto wasLabel = label(prevLink);
const auto nowLabel = label(newLink); const auto nowLabel = label(newLink);
@ -359,8 +353,8 @@ TextWithEntities GenerateInviteLinkChangeText(
if (wasRequestApproval != nowRequestApproval) { if (wasRequestApproval != nowRequestApproval) {
result.text.append('\n').append( result.text.append('\n').append(
nowRequestApproval nowRequestApproval
? tr::lng_admin_log_invite_link_request_needed(tr::now) ? tr::lng_admin_log_invite_link_request_needed(tr::now)
: tr::lng_admin_log_invite_link_request_not_needed(tr::now)); : tr::lng_admin_log_invite_link_request_not_needed(tr::now));
} }
result.entities.push_front( result.entities.push_front(
@ -370,23 +364,22 @@ TextWithEntities GenerateInviteLinkChangeText(
auto GenerateParticipantString( auto GenerateParticipantString(
not_null<Main::Session *> session, not_null<Main::Session *> session,
PeerId participantId) PeerId participantId) {
{
// User name in "User name (@username)" format with entities. // User name in "User name (@username)" format with entities.
const auto peer = session->data().peer(participantId); const auto peer = session->data().peer(participantId);
auto name = TextWithEntities{peer->name()}; auto name = TextWithEntities{peer->name()};
if (const auto user = peer->asUser()) { if (const auto user = peer->asUser()) {
const auto data = TextUtilities::MentionNameDataFromFields({ const auto data = TextUtilities::MentionNameDataFromFields({
.selfId = session->userId().bare, .selfId = session->userId().bare,
.userId = peerToUser(user->id).bare, .userId = peerToUser(user->id).bare,
.accessHash = user->accessHash(), .accessHash = user->accessHash(),
}); });
name.entities.push_back({ name.entities.push_back({
EntityType::MentionName, EntityType::MentionName,
0, 0,
int(name.text.size()), int(name.text.size()),
data, data,
}); });
} }
const auto username = peer->userName(); const auto username = peer->userName();
if (username.isEmpty()) { if (username.isEmpty()) {
@ -394,9 +387,10 @@ auto GenerateParticipantString(
} }
auto mention = TextWithEntities{'@' + username}; auto mention = TextWithEntities{'@' + username};
mention.entities.push_back({ mention.entities.push_back({
EntityType::Mention, EntityType::Mention,
0, 0,
int(mention.text.size())}); int(mention.text.size())
});
return tr::lng_admin_log_user_with_username( return tr::lng_admin_log_user_with_username(
tr::now, tr::now,
lt_name, lt_name,
@ -409,15 +403,14 @@ auto GenerateParticipantString(
auto GenerateParticipantChangeText( auto GenerateParticipantChangeText(
not_null<ChannelData *> channel, not_null<ChannelData *> channel,
const Api::ChatParticipant &participant, const Api::ChatParticipant &participant,
std::optional<Api::ChatParticipant> oldParticipant = std::nullopt) std::optional<Api::ChatParticipant> oldParticipant = std::nullopt) {
{
using Type = Api::ChatParticipant::Type; using Type = Api::ChatParticipant::Type;
const auto oldRights = oldParticipant const auto oldRights = oldParticipant
? oldParticipant->rights() ? oldParticipant->rights()
: ChatAdminRightsInfo(); : ChatAdminRightsInfo();
const auto oldRestrictions = oldParticipant const auto oldRestrictions = oldParticipant
? oldParticipant->restrictions() ? oldParticipant->restrictions()
: ChatRestrictionsInfo(); : ChatRestrictionsInfo();
const auto generateOther = [&](PeerId participantId) const auto generateOther = [&](PeerId participantId)
{ {
@ -430,15 +423,13 @@ auto GenerateParticipantChangeText(
user, user,
ChatAdminRightsInfo(), ChatAdminRightsInfo(),
oldRights); oldRights);
} } else if (oldParticipant && oldParticipant->type() == Type::Banned) {
else if (oldParticipant && oldParticipant->type() == Type::Banned) {
return GeneratePermissionsChangeText( return GeneratePermissionsChangeText(
participantId, participantId,
user, user,
ChatRestrictionsInfo(), ChatRestrictionsInfo(),
oldRestrictions); oldRestrictions);
} } else if (oldParticipant
else if (oldParticipant
&& oldParticipant->type() == Type::Restricted && oldParticipant->type() == Type::Restricted
&& (participant.type() == Type::Member && (participant.type() == Type::Member
|| participant.type() == Type::Left)) { || participant.type() == Type::Left)) {
@ -512,23 +503,21 @@ auto GenerateParticipantChangeText(
TextWithEntities GenerateParticipantChangeText( TextWithEntities GenerateParticipantChangeText(
not_null<ChannelData *> channel, not_null<ChannelData *> channel,
const MTPChannelParticipant &participant, const MTPChannelParticipant &participant,
std::optional<MTPChannelParticipant> oldParticipant = std::nullopt) std::optional<MTPChannelParticipant> oldParticipant = std::nullopt) {
{
return GenerateParticipantChangeText( return GenerateParticipantChangeText(
channel, channel,
Api::ChatParticipant(participant, channel), Api::ChatParticipant(participant, channel),
oldParticipant oldParticipant
? std::make_optional(Api::ChatParticipant( ? std::make_optional(Api::ChatParticipant(
*oldParticipant, *oldParticipant,
channel)) channel))
: std::nullopt); : std::nullopt);
} }
TextWithEntities GenerateDefaultBannedRightsChangeText( TextWithEntities GenerateDefaultBannedRightsChangeText(
not_null<ChannelData *> channel, not_null<ChannelData *> channel,
ChatRestrictionsInfo rights, ChatRestrictionsInfo rights,
ChatRestrictionsInfo oldRights) ChatRestrictionsInfo oldRights) {
{
auto result = TextWithEntities{ auto result = TextWithEntities{
tr::lng_admin_log_changed_default_permissions(tr::now) tr::lng_admin_log_changed_default_permissions(tr::now)
}; };
@ -541,23 +530,23 @@ TextWithEntities GenerateDefaultBannedRightsChangeText(
return result; return result;
} }
[[nodiscard]] bool IsTopicClosed(const MTPForumTopic &topic) [[nodiscard]] bool IsTopicClosed(const MTPForumTopic &topic) {
{
return topic.match([](const MTPDforumTopic &data) return topic.match([](const MTPDforumTopic &data)
{ {
return data.is_closed(); return data.is_closed();
}, [](const MTPDforumTopicDeleted &) },
[](const MTPDforumTopicDeleted &)
{ {
return false; return false;
}); });
} }
[[nodiscard]] bool IsTopicHidden(const MTPForumTopic &topic) [[nodiscard]] bool IsTopicHidden(const MTPForumTopic &topic) {
{
return topic.match([](const MTPDforumTopic &data) return topic.match([](const MTPDforumTopic &data)
{ {
return data.is_hidden(); return data.is_hidden();
}, [](const MTPDforumTopicDeleted &) },
[](const MTPDforumTopicDeleted &)
{ {
return false; return false;
}); });
@ -565,8 +554,7 @@ TextWithEntities GenerateDefaultBannedRightsChangeText(
[[nodiscard]] TextWithEntities GenerateTopicLink( [[nodiscard]] TextWithEntities GenerateTopicLink(
not_null<ChannelData *> channel, not_null<ChannelData *> channel,
const MTPForumTopic &topic) const MTPForumTopic &topic) {
{
return topic.match([&](const MTPDforumTopic &data) return topic.match([&](const MTPDforumTopic &data)
{ {
return Ui::Text::Link( return Ui::Text::Link(
@ -577,7 +565,8 @@ TextWithEntities GenerateDefaultBannedRightsChangeText(
u"internal:url:https://t.me/c/%1/%2"_q.arg( u"internal:url:https://t.me/c/%1/%2"_q.arg(
peerToChannel(channel->id).bare).arg( peerToChannel(channel->id).bare).arg(
data.vid().v)); data.vid().v));
}, [](const MTPDforumTopicDeleted &) },
[](const MTPDforumTopicDeleted &)
{ {
return TextWithEntities{u"Deleted"_q}; return TextWithEntities{u"Deleted"_q};
}); });
@ -585,31 +574,26 @@ TextWithEntities GenerateDefaultBannedRightsChangeText(
} // namespace } // namespace
OwnedItem::OwnedItem(std::nullptr_t) OwnedItem::OwnedItem(std::nullptr_t) {
{
} }
OwnedItem::OwnedItem( OwnedItem::OwnedItem(
not_null<HistoryView::ElementDelegate *> delegate, not_null<HistoryView::ElementDelegate *> delegate,
not_null<HistoryItem *> data) not_null<HistoryItem *> data)
: _data(data), _view(_data->createView(delegate)) : _data(data), _view(_data->createView(delegate)) {
{
} }
OwnedItem::OwnedItem(OwnedItem &&other) OwnedItem::OwnedItem(OwnedItem &&other)
: _data(base::take(other._data)), _view(base::take(other._view)) : _data(base::take(other._data)), _view(base::take(other._view)) {
{
} }
OwnedItem &OwnedItem::operator=(OwnedItem &&other) OwnedItem &OwnedItem::operator=(OwnedItem &&other) {
{
_data = base::take(other._data); _data = base::take(other._data);
_view = base::take(other._view); _view = base::take(other._view);
return *this; return *this;
} }
OwnedItem::~OwnedItem() OwnedItem::~OwnedItem() {
{
clearView(); clearView();
if (_data) { if (_data) {
_data->destroy(); _data->destroy();
@ -617,13 +601,11 @@ OwnedItem::~OwnedItem()
} }
void OwnedItem::refreshView( void OwnedItem::refreshView(
not_null<HistoryView::ElementDelegate *> delegate) not_null<HistoryView::ElementDelegate *> delegate) {
{
_view = _data->createView(delegate); _view = _data->createView(delegate);
} }
void OwnedItem::clearView() void OwnedItem::clearView() {
{
_view = nullptr; _view = nullptr;
} }
@ -631,11 +613,10 @@ void GenerateItems(
not_null<HistoryView::ElementDelegate *> delegate, not_null<HistoryView::ElementDelegate *> delegate,
not_null<History *> history, not_null<History *> history,
EditedMessage message, EditedMessage message,
Fn<void(OwnedItem item, TimeId sentDate, MsgId)> callback) Fn<void(OwnedItem item, TimeId sentDate, MsgId)> callback) {
{
const auto session = &history->session(); const auto session = &history->session();
const auto id = message.fakeId; const auto id = message.fakeId;
PeerData* from = history->owner().userLoaded(message.fromId); PeerData *from = history->owner().userLoaded(message.fromId);
if (!from) { if (!from) {
from = history->owner().channelLoaded(message.fromId); from = history->owner().channelLoaded(message.fromId);
} }

View file

@ -10,14 +10,12 @@
class History; class History;
namespace HistoryView namespace HistoryView {
{
class ElementDelegate; class ElementDelegate;
class Element; class Element;
} // namespace HistoryView } // namespace HistoryView
namespace EditedLog namespace EditedLog {
{
class OwnedItem; class OwnedItem;
@ -41,16 +39,15 @@ public:
OwnedItem &operator=(OwnedItem &&other); OwnedItem &operator=(OwnedItem &&other);
~OwnedItem(); ~OwnedItem();
[[nodiscard]] HistoryView::Element *get() const [[nodiscard]] HistoryView::Element *get() const {
{
return _view.get(); return _view.get();
} }
[[nodiscard]] HistoryView::Element *operator->() const
{ [[nodiscard]] HistoryView::Element *operator->() const {
return get(); return get();
} }
[[nodiscard]] operator HistoryView::Element *() const
{ [[nodiscard]] operator HistoryView::Element *() const {
return get(); return get();
} }

View file

@ -6,32 +6,26 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ayu/ui/sections/edited/edited_log_section.h" #include "ayu/ui/sections/edited/edited_log_section.h"
#include "ayu/ui/sections/edited/edited_log_inner.h"
#include "profile/profile_back_button.h"
#include "core/shortcuts.h"
#include "ui/effects/animations.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/shadow.h"
#include "ui/widgets/buttons.h"
#include "ui/ui_utility.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "window/themes/window_theme.h" #include "ayu/ui/sections/edited/edited_log_inner.h"
#include "window/window_adaptive.h"
#include "window/window_session_controller.h"
#include "ui/boxes/confirm_box.h"
#include "base/timer.h" #include "base/timer.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "profile/profile_back_button.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
#include "styles/style_window.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "ui/ui_utility.h"
#include "ui/boxes/confirm_box.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/shadow.h"
#include "window/window_adaptive.h"
#include "window/window_session_controller.h"
#include "window/themes/window_theme.h"
namespace EditedLog namespace EditedLog {
{
class FixedBar final : public TWidget class FixedBar final : public TWidget
{ {
@ -65,8 +59,7 @@ object_ptr<Window::SectionWidget> SectionMemento::createWidget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController *> controller, not_null<Window::SessionController *> controller,
Window::Column column, Window::Column column,
const QRect &geometry) const QRect &geometry) {
{
if (column == Window::Column::Third) { if (column == Window::Column::Third) {
return nullptr; return nullptr;
} }
@ -80,25 +73,24 @@ FixedBar::FixedBar(
not_null<Window::SessionController *> controller, not_null<Window::SessionController *> controller,
not_null<PeerData *> peer) not_null<PeerData *> peer)
: TWidget(parent), _controller(controller), _peer(peer), _backButton( : TWidget(parent), _controller(controller), _peer(peer), _backButton(
this, this,
&controller->session(), &controller->session(),
tr::lng_terms_back(tr::now), tr::lng_terms_back(tr::now),
controller->adaptive().oneColumnValue()), _cancel(this, st::historyAdminLogCancelSearch) controller->adaptive().oneColumnValue()), _cancel(this, st::historyAdminLogCancelSearch) {
{
_backButton->moveToLeft(0, 0); _backButton->moveToLeft(0, 0);
_backButton->setClickedCallback([=] _backButton->setClickedCallback([=]
{ goBack(); }); {
goBack();
});
_cancel->hide(anim::type::instant); _cancel->hide(anim::type::instant);
} }
void FixedBar::goBack() void FixedBar::goBack() {
{
_controller->showBackFromStack(); _controller->showBackFromStack();
} }
int FixedBar::resizeGetHeight(int newWidth) int FixedBar::resizeGetHeight(int newWidth) {
{
auto filterLeft = newWidth; auto filterLeft = newWidth;
auto cancelLeft = filterLeft - _cancel->width(); auto cancelLeft = filterLeft - _cancel->width();
@ -115,16 +107,14 @@ int FixedBar::resizeGetHeight(int newWidth)
return newHeight; return newHeight;
} }
void FixedBar::setAnimatingMode(bool enabled) void FixedBar::setAnimatingMode(bool enabled) {
{
if (_animatingMode != enabled) { if (_animatingMode != enabled) {
_animatingMode = enabled; _animatingMode = enabled;
setCursor(_animatingMode ? style::cur_pointer : style::cur_default); setCursor(_animatingMode ? style::cur_pointer : style::cur_default);
if (_animatingMode) { if (_animatingMode) {
setAttribute(Qt::WA_OpaquePaintEvent, false); setAttribute(Qt::WA_OpaquePaintEvent, false);
hideChildren(); hideChildren();
} } else {
else {
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
showChildren(); showChildren();
_cancel->setVisible(false); _cancel->setVisible(false);
@ -133,20 +123,17 @@ void FixedBar::setAnimatingMode(bool enabled)
} }
} }
void FixedBar::paintEvent(QPaintEvent *e) void FixedBar::paintEvent(QPaintEvent *e) {
{
if (!_animatingMode) { if (!_animatingMode) {
auto p = QPainter(this); auto p = QPainter(this);
p.fillRect(e->rect(), st::topBarBg); p.fillRect(e->rect(), st::topBarBg);
} }
} }
void FixedBar::mousePressEvent(QMouseEvent *e) void FixedBar::mousePressEvent(QMouseEvent *e) {
{
if (e->button() == Qt::LeftButton) { if (e->button() == Qt::LeftButton) {
goBack(); goBack();
} } else {
else {
TWidget::mousePressEvent(e); TWidget::mousePressEvent(e);
} }
} }
@ -160,8 +147,7 @@ Widget::Widget(
_scroll(this, st::historyScroll, false), _scroll(this, st::historyScroll, false),
_fixedBar(this, controller, peer), _fixedBar(this, controller, peer),
_fixedBarShadow(this), _fixedBarShadow(this),
_item(item) _item(item) {
{
_fixedBar->move(0, 0); _fixedBar->move(0, 0);
_fixedBar->resizeToWidth(width()); _fixedBar->resizeToWidth(width());
_fixedBar->show(); _fixedBar->show();
@ -172,14 +158,16 @@ Widget::Widget(
) | rpl::start_with_next([=] ) | rpl::start_with_next([=]
{ {
updateAdaptiveLayout(); updateAdaptiveLayout();
}, lifetime()); },
lifetime());
_inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(this, controller, peer, item)); _inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(this, controller, peer, item));
_inner->scrollToSignal( _inner->scrollToSignal(
) | rpl::start_with_next([=](int top) ) | rpl::start_with_next([=](int top)
{ {
_scroll->scrollToY(top); _scroll->scrollToY(top);
}, lifetime()); },
lifetime());
_scroll->move(0, _fixedBar->height()); _scroll->move(0, _fixedBar->height());
_scroll->show(); _scroll->show();
@ -187,50 +175,45 @@ Widget::Widget(
) | rpl::start_with_next([=] ) | rpl::start_with_next([=]
{ {
onScroll(); onScroll();
}, lifetime()); },
lifetime());
setupShortcuts(); setupShortcuts();
} }
void Widget::updateAdaptiveLayout() void Widget::updateAdaptiveLayout() {
{
_fixedBarShadow->moveToLeft( _fixedBarShadow->moveToLeft(
controller()->adaptive().isOneColumn() controller()->adaptive().isOneColumn()
? 0 ? 0
: st::lineWidth, : st::lineWidth,
_fixedBar->height()); _fixedBar->height());
} }
not_null<PeerData *> Widget::channel() const not_null<PeerData *> Widget::channel() const {
{
return _inner->channel(); return _inner->channel();
} }
Dialogs::RowDescriptor Widget::activeChat() const Dialogs::RowDescriptor Widget::activeChat() const {
{
return { return {
channel()->owner().history(channel()), channel()->owner().history(channel()),
FullMsgId(channel()->id, ShowAtUnreadMsgId) FullMsgId(channel()->id, ShowAtUnreadMsgId)
}; };
} }
QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams &params) QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams &params) {
{
if (params.withTopBarShadow) _fixedBarShadow->hide(); if (params.withTopBarShadow) _fixedBarShadow->hide();
auto result = Ui::GrabWidget(this); auto result = Ui::GrabWidget(this);
if (params.withTopBarShadow) _fixedBarShadow->show(); if (params.withTopBarShadow) _fixedBarShadow->show();
return result; return result;
} }
void Widget::doSetInnerFocus() void Widget::doSetInnerFocus() {
{
_inner->setFocus(); _inner->setFocus();
} }
bool Widget::showInternal( bool Widget::showInternal(
not_null<Window::SectionMemento *> memento, not_null<Window::SectionMemento *> memento,
const Window::SectionShow &params) const Window::SectionShow &params) {
{
if (auto logMemento = dynamic_cast<SectionMemento *>(memento.get())) { if (auto logMemento = dynamic_cast<SectionMemento *>(memento.get())) {
if (logMemento->getPeer() == channel()) { if (logMemento->getPeer() == channel()) {
restoreState(logMemento); restoreState(logMemento);
@ -240,41 +223,35 @@ bool Widget::showInternal(
return false; return false;
} }
void Widget::setInternalState(const QRect &geometry, not_null<SectionMemento *> memento) void Widget::setInternalState(const QRect &geometry, not_null<SectionMemento *> memento) {
{
setGeometry(geometry); setGeometry(geometry);
Ui::SendPendingMoveResizeEvents(this); Ui::SendPendingMoveResizeEvents(this);
restoreState(memento); restoreState(memento);
} }
void Widget::setupShortcuts() void Widget::setupShortcuts() {
{
// todo: smth // todo: smth
} }
std::shared_ptr<Window::SectionMemento> Widget::createMemento() std::shared_ptr<Window::SectionMemento> Widget::createMemento() {
{
auto result = std::make_shared<SectionMemento>(channel(), _item); auto result = std::make_shared<SectionMemento>(channel(), _item);
saveState(result.get()); saveState(result.get());
return result; return result;
} }
void Widget::saveState(not_null<SectionMemento *> memento) void Widget::saveState(not_null<SectionMemento *> memento) {
{
memento->setScrollTop(_scroll->scrollTop()); memento->setScrollTop(_scroll->scrollTop());
_inner->saveState(memento); _inner->saveState(memento);
} }
void Widget::restoreState(not_null<SectionMemento *> memento) void Widget::restoreState(not_null<SectionMemento *> memento) {
{
_inner->restoreState(memento); _inner->restoreState(memento);
auto scrollTop = memento->getScrollTop(); auto scrollTop = memento->getScrollTop();
_scroll->scrollToY(scrollTop); _scroll->scrollToY(scrollTop);
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
} }
void Widget::resizeEvent(QResizeEvent *e) void Widget::resizeEvent(QResizeEvent *e) {
{
if (!width() || !height()) { if (!width() || !height()) {
return; return;
} }
@ -303,13 +280,11 @@ void Widget::resizeEvent(QResizeEvent *e)
} }
} }
void Widget::paintEvent(QPaintEvent *e) void Widget::paintEvent(QPaintEvent *e) {
{
if (animatingShow()) { if (animatingShow()) {
SectionWidget::paintEvent(e); SectionWidget::paintEvent(e);
return; return;
} } else if (controller()->contentOverlapped(this, e)) {
else if (controller()->contentOverlapped(this, e)) {
return; return;
} }
//if (hasPendingResizedItems()) { //if (hasPendingResizedItems()) {
@ -323,33 +298,27 @@ void Widget::paintEvent(QPaintEvent *e)
SectionWidget::PaintBackground(controller(), _inner->theme(), this, clip); SectionWidget::PaintBackground(controller(), _inner->theme(), this, clip);
} }
void Widget::onScroll() void Widget::onScroll() {
{
int scrollTop = _scroll->scrollTop(); int scrollTop = _scroll->scrollTop();
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
} }
void Widget::showAnimatedHook( void Widget::showAnimatedHook(
const Window::SectionSlideParams &params) const Window::SectionSlideParams &params) {
{
_fixedBar->setAnimatingMode(true); _fixedBar->setAnimatingMode(true);
if (params.withTopBarShadow) _fixedBarShadow->show(); if (params.withTopBarShadow) _fixedBarShadow->show();
} }
void Widget::showFinishedHook() void Widget::showFinishedHook() {
{
_fixedBar->setAnimatingMode(false); _fixedBar->setAnimatingMode(false);
} }
bool Widget::floatPlayerHandleWheelEvent(QEvent *e) bool Widget::floatPlayerHandleWheelEvent(QEvent *e) {
{
return _scroll->viewportEvent(e); return _scroll->viewportEvent(e);
} }
QRect Widget::floatPlayerAvailableRect() QRect Widget::floatPlayerAvailableRect() {
{
return mapToGlobal(_scroll->geometry()); return mapToGlobal(_scroll->geometry());
} }
} // namespace EditedLog } // namespace EditedLog

View file

@ -10,21 +10,19 @@
#include "window/section_memento.h" #include "window/section_memento.h"
#include "ayu/ui/sections/edited/edited_log_item.h" #include "ayu/ui/sections/edited/edited_log_item.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
// don't reformat includes above
namespace Ui namespace Ui {
{
class ScrollArea; class ScrollArea;
class PlainShadow; class PlainShadow;
class FlatButton; class FlatButton;
} // namespace Ui } // namespace Ui
namespace Profile namespace Profile {
{
class BackButton; class BackButton;
} // namespace Profile } // namespace Profile
namespace EditedLog namespace EditedLog {
{
class FixedBar; class FixedBar;
class InnerWidget; class InnerWidget;
@ -42,8 +40,7 @@ public:
not_null<PeerData *> channel() const; not_null<PeerData *> channel() const;
Dialogs::RowDescriptor activeChat() const override; Dialogs::RowDescriptor activeChat() const override;
bool hasTopBarShadow() const override bool hasTopBarShadow() const override {
{
return true; return true;
} }
@ -91,8 +88,7 @@ public:
SectionMemento(not_null<PeerData *> peer, not_null<HistoryItem *> item) SectionMemento(not_null<PeerData *> peer, not_null<HistoryItem *> item)
: _peer(peer), : _peer(peer),
_item(item) _item(item) {
{
} }
object_ptr<Window::SectionWidget> createWidget( object_ptr<Window::SectionWidget> createWidget(
@ -101,16 +97,15 @@ public:
Window::Column column, Window::Column column,
const QRect &geometry) override; const QRect &geometry) override;
not_null<PeerData *> getPeer() const not_null<PeerData *> getPeer() const {
{
return _peer; return _peer;
} }
void setScrollTop(int scrollTop)
{ void setScrollTop(int scrollTop) {
_scrollTop = scrollTop; _scrollTop = scrollTop;
} }
int getScrollTop() const
{ int getScrollTop() const {
return _scrollTop; return _scrollTop;
} }
@ -118,27 +113,26 @@ public:
std::vector<OwnedItem> &&items, std::vector<OwnedItem> &&items,
std::set<uint64> &&eventIds, std::set<uint64> &&eventIds,
bool upLoaded, bool upLoaded,
bool downLoaded) bool downLoaded) {
{
_items = std::move(items); _items = std::move(items);
_eventIds = std::move(eventIds); _eventIds = std::move(eventIds);
_upLoaded = upLoaded; _upLoaded = upLoaded;
_downLoaded = downLoaded; _downLoaded = downLoaded;
} }
std::vector<OwnedItem> takeItems()
{ std::vector<OwnedItem> takeItems() {
return std::move(_items); return std::move(_items);
} }
std::set<uint64> takeEventIds()
{ std::set<uint64> takeEventIds() {
return std::move(_eventIds); return std::move(_eventIds);
} }
bool upLoaded() const
{ bool upLoaded() const {
return _upLoaded; return _upLoaded;
} }
bool downLoaded() const
{ bool downLoaded() const {
return _downLoaded; return _downLoaded;
} }

View file

@ -5,10 +5,10 @@
// //
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "icon_picker.h" #include "icon_picker.h"
#include "tray.h"
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
#include "core/application.h" #include "core/application.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "tray.h"
#include "ayu/ui/ayu_assets.h" #include "ayu/ui/ayu_assets.h"
#include "main/main_domain.h" #include "main/main_domain.h"
@ -20,7 +20,7 @@
#include "ayu/utils/windows_utils.h" #include "ayu/utils/windows_utils.h"
#endif #endif
const QVector<QString> icons{ const QVector icons{
AyuAssets::DEFAULT_ICON, AyuAssets::DEFAULT_ICON,
AyuAssets::ALT_ICON, AyuAssets::ALT_ICON,
AyuAssets::DISCORD_ICON, AyuAssets::DISCORD_ICON,
@ -33,8 +33,7 @@ const QVector<QString> icons{
const auto rows = static_cast<int>(icons.size()) / 4 + std::min(1, static_cast<int>(icons.size()) % 4); const auto rows = static_cast<int>(icons.size()) / 4 + std::min(1, static_cast<int>(icons.size()) % 4);
void drawIcon(QPainter &p, const QImage &icon, int xOffset, int yOffset, bool selected) void drawIcon(QPainter &p, const QImage &icon, int xOffset, int yOffset, bool selected) {
{
xOffset += st::cpPadding; xOffset += st::cpPadding;
if (selected) { if (selected) {
@ -51,8 +50,7 @@ void drawIcon(QPainter &p, const QImage &icon, int xOffset, int yOffset, bool se
p.drawImage(rect, icon); p.drawImage(rect, icon);
} }
void applyIcon() void applyIcon() {
{
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
AyuAssets::loadAppIco(); AyuAssets::loadAppIco();
reloadAppIconFromTaskBar(); reloadAppIconFromTaskBar();
@ -65,13 +63,11 @@ void applyIcon()
} }
IconPicker::IconPicker(QWidget *parent) IconPicker::IconPicker(QWidget *parent)
: RpWidget(parent) : RpWidget(parent) {
{
setMinimumSize(st::boxWidth, (st::cpIconSize + st::cpPadding) * rows); setMinimumSize(st::boxWidth, (st::cpIconSize + st::cpPadding) * rows);
} }
void IconPicker::paintEvent(QPaintEvent *e) void IconPicker::paintEvent(QPaintEvent *e) {
{
Painter p(this); Painter p(this);
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
@ -94,8 +90,7 @@ void IconPicker::paintEvent(QPaintEvent *e)
} }
} }
void IconPicker::mousePressEvent(QMouseEvent *e) void IconPicker::mousePressEvent(QMouseEvent *e) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
auto changed = false; auto changed = false;

View file

@ -6,35 +6,29 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "settings_ayu.h" #include "settings_ayu.h"
#include "ayu/ayu_settings.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_deleted_mark.h"
#include "ayu/ui/boxes/edit_edited_mark.h" #include "ayu/ui/boxes/edit_edited_mark.h"
#include "ayu/ui/boxes/font_selector.h" #include "ayu/ui/boxes/font_selector.h"
#include "apiwrap.h"
#include "lang_auto.h" #include "lang_auto.h"
#include "mainwindow.h"
#include "api/api_blocked_peers.h"
#include "boxes/connection_box.h" #include "boxes/connection_box.h"
#include "core/application.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "lang/lang_instance.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "media/system_media_controls_manager.h"
#include "platform/platform_specific.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "styles/style_ayu_styles.h"
#include "styles/style_basic.h" #include "styles/style_basic.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
#include "styles/style_ayu_styles.h"
#include "icon_picker.h" #include "icon_picker.h"
#include "styles/style_ayu_icons.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/vertical_list.h"
#include "ui/boxes/single_choice_box.h" #include "ui/boxes/single_choice_box.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
@ -44,9 +38,6 @@
#include "ui/wrap/slide_wrap.h" #include "ui/wrap/slide_wrap.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_ayu_icons.h"
#include "ui/vertical_list.h"
class PainterHighQualityEnabler; class PainterHighQualityEnabler;
@ -55,8 +46,7 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
std::vector<not_null<Ui::AbstractCheckView *>> innerCheckViews, std::vector<not_null<Ui::AbstractCheckView *>> innerCheckViews,
not_null<Ui::SlideWrap<> *> wrap, not_null<Ui::SlideWrap<> *> wrap,
rpl::producer<QString> buttonLabel, rpl::producer<QString> buttonLabel,
bool toggledWhenAll) bool toggledWhenAll) {
{
const auto button = container->add(object_ptr<Ui::SettingsButton>( const auto button = container->add(object_ptr<Ui::SettingsButton>(
container, container,
nullptr, nullptr,
@ -70,8 +60,7 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
struct State final struct State final
{ {
State(const style::Toggle &st, Fn<void()> c) State(const style::Toggle &st, Fn<void()> c)
: checkView(st, false, c) : checkView(st, false, c) {
{
} }
Ui::ToggleView checkView; Ui::ToggleView checkView;
@ -82,14 +71,18 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
const auto state = button->lifetime().make_state<State>( const auto state = button->lifetime().make_state<State>(
st.toggle, st.toggle,
[=] [=]
{ toggleButton->update(); }); {
toggleButton->update();
});
state->innerChecks = std::move(innerCheckViews); state->innerChecks = std::move(innerCheckViews);
const auto countChecked = [=] const auto countChecked = [=]
{ {
return ranges::count_if( return ranges::count_if(
state->innerChecks, state->innerChecks,
[](const auto &v) [](const auto &v)
{ return v->checked(); }); {
return v->checked();
});
}; };
for (const auto &innerCheck : state->innerChecks) { for (const auto &innerCheck : state->innerChecks) {
innerCheck->checkedChanges( innerCheck->checkedChanges(
@ -105,7 +98,8 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
{ {
auto p = QPainter(separator); auto p = QPainter(separator);
p.fillRect(separator->rect(), bg); p.fillRect(separator->rect(), bg);
}, separator->lifetime()); },
separator->lifetime());
const auto separatorHeight = 2 * st.toggle.border const auto separatorHeight = 2 * st.toggle.border
+ st.toggle.diameter; + st.toggle.diameter;
button->geometryValue( button->geometryValue(
@ -123,7 +117,8 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
r.y() + (r.height() - separatorHeight) / 2, r.y() + (r.height() - separatorHeight) / 2,
kLineWidth, kLineWidth,
separatorHeight); separatorHeight);
}, toggleButton->lifetime()); },
toggleButton->lifetime());
const auto checkWidget = Ui::CreateChild<Ui::RpWidget>(toggleButton); const auto checkWidget = Ui::CreateChild<Ui::RpWidget>(toggleButton);
checkWidget->resize(checkView->getSize()); checkWidget->resize(checkView->getSize());
@ -132,14 +127,16 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
{ {
auto p = QPainter(checkWidget); auto p = QPainter(checkWidget);
checkView->paint(p, 0, 0, checkWidget->width()); checkView->paint(p, 0, 0, checkWidget->width());
}, checkWidget->lifetime()); },
checkWidget->lifetime());
toggleButton->sizeValue( toggleButton->sizeValue(
) | start_with_next([=](const QSize &s) ) | start_with_next([=](const QSize &s)
{ {
checkWidget->moveToRight( checkWidget->moveToRight(
st.toggleSkip, st.toggleSkip,
(s.height() - checkWidget->height()) / 2); (s.height() - checkWidget->height()) / 2);
}, toggleButton->lifetime()); },
toggleButton->lifetime());
} }
const auto totalInnerChecks = state->innerChecks.size(); const auto totalInnerChecks = state->innerChecks.size();
@ -151,12 +148,12 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
if (toggledWhenAll) { if (toggledWhenAll) {
checkView->setChecked(count == totalInnerChecks, checkView->setChecked(count == totalInnerChecks,
anim::type::normal); anim::type::normal);
} } else {
else {
checkView->setChecked(count != 0, checkView->setChecked(count != 0,
anim::type::normal); anim::type::normal);
} }
}, toggleButton->lifetime()); },
toggleButton->lifetime());
checkView->setLocked(false); checkView->setLocked(false);
checkView->finishAnimating(); checkView->finishAnimating();
@ -168,13 +165,13 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
rpl::empty_value() rpl::empty_value()
) | rpl::map(countChecked) ) | rpl::map(countChecked)
) | rpl::map([=](const QString &t, int checked) ) | rpl::map([=](const QString &t, int checked)
{ {
auto count = Ui::Text::Bold(" " auto count = Ui::Text::Bold(" "
+ QString::number(checked) + QString::number(checked)
+ '/' + '/'
+ QString::number(totalInnerChecks)); + QString::number(totalInnerChecks));
return TextWithEntities::Simple(t).append(std::move(count)); return TextWithEntities::Simple(t).append(std::move(count));
})); }));
label->setAttribute(Qt::WA_TransparentForMouseEvents); label->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto arrow = Ui::CreateChild<Ui::RpWidget>(button); const auto arrow = Ui::CreateChild<Ui::RpWidget>(button);
{ {
@ -197,7 +194,8 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
p.translate(-center); p.translate(-center);
} }
icon.paint(p, 0, 0, arrow->width()); icon.paint(p, 0, 0, arrow->width());
}, arrow->lifetime()); },
arrow->lifetime());
} }
button->sizeValue( button->sizeValue(
) | start_with_next([=, &st](const QSize &s) ) | start_with_next([=, &st](const QSize &s)
@ -214,25 +212,30 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
labelLeft + label->naturalWidth(), labelLeft + label->naturalWidth(),
labelRight - arrow->width()), labelRight - arrow->width()),
(s.height() - arrow->height()) / 2); (s.height() - arrow->height()) / 2);
}, button->lifetime()); },
button->lifetime());
wrap->toggledValue( wrap->toggledValue(
) | rpl::skip(1) | start_with_next([=](bool toggled) ) | rpl::skip(1) | start_with_next([=](bool toggled)
{ {
state->animation.start( state->animation.start(
[=] [=]
{ arrow->update(); }, {
arrow->update();
},
toggled ? 0. : 1., toggled ? 0. : 1.,
toggled ? 1. : 0., toggled ? 1. : 0.,
st::slideWrapDuration, st::slideWrapDuration,
anim::easeOutCubic); anim::easeOutCubic);
}, button->lifetime()); },
button->lifetime());
wrap->ease = anim::easeOutCubic; wrap->ease = anim::easeOutCubic;
button->clicks( button->clicks(
) | start_with_next([=] ) | start_with_next([=]
{ {
wrap->toggle(!wrap->toggled(), anim::type::normal); wrap->toggle(!wrap->toggled(), anim::type::normal);
}, button->lifetime()); },
button->lifetime());
toggleButton->clicks( toggleButton->clicks(
) | start_with_next([=] ) | start_with_next([=]
@ -241,7 +244,8 @@ not_null<Ui::RpWidget *> AddInnerToggle(not_null<Ui::VerticalLayout *> container
for (const auto &innerCheck : state->innerChecks) { for (const auto &innerCheck : state->innerChecks) {
innerCheck->setChecked(checked, anim::type::normal); innerCheck->setChecked(checked, anim::type::normal);
} }
}, toggleButton->lifetime()); },
toggleButton->lifetime());
return button; return button;
} }
@ -256,8 +260,7 @@ struct NestedEntry
void AddCollapsibleToggle(not_null<Ui::VerticalLayout *> container, void AddCollapsibleToggle(not_null<Ui::VerticalLayout *> container,
rpl::producer<QString> title, rpl::producer<QString> title,
std::vector<NestedEntry> checkboxes, std::vector<NestedEntry> checkboxes,
bool toggledWhenAll) bool toggledWhenAll) {
{
const auto addCheckbox = [&]( const auto addCheckbox = [&](
not_null<Ui::VerticalLayout *> verticalLayout, not_null<Ui::VerticalLayout *> verticalLayout,
const QString &label, const QString &label,
@ -282,22 +285,24 @@ void AddCollapsibleToggle(not_null<Ui::VerticalLayout *> container,
) | start_with_next([=](int w, const QRect &r) ) | start_with_next([=](int w, const QRect &r)
{ {
button->setGeometry(0, r.y(), w, r.height()); button->setGeometry(0, r.y(), w, r.height());
}, button->lifetime()); },
button->lifetime());
checkbox->setAttribute(Qt::WA_TransparentForMouseEvents); checkbox->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto checkView = checkbox->checkView(); const auto checkView = checkbox->checkView();
button->setClickedCallback([=] button->setClickedCallback([=]
{ {
checkView->setChecked( checkView->setChecked(
!checkView->checked(), !checkView->checked(),
anim::type::normal); anim::type::normal);
}); });
return checkView; return checkView;
}(); }();
checkView->checkedChanges( checkView->checkedChanges(
) | start_with_next([=](bool checked) ) | start_with_next([=](bool checked)
{ {
}, verticalLayout->lifetime()); },
verticalLayout->lifetime());
return checkView; return checkView;
}; };
@ -313,7 +318,8 @@ void AddCollapsibleToggle(not_null<Ui::VerticalLayout *> container,
) | start_with_next([=](bool enabled) ) | start_with_next([=](bool enabled)
{ {
entry.callback(enabled); entry.callback(enabled);
}, container->lifetime()); },
container->lifetime());
innerChecks.push_back(c); innerChecks.push_back(c);
} }
@ -331,7 +337,8 @@ void AddCollapsibleToggle(not_null<Ui::VerticalLayout *> container,
) | start_with_next([=](int w) ) | start_with_next([=](int w)
{ {
raw->resizeToWidth(w); raw->resizeToWidth(w);
}, raw->lifetime()); },
raw->lifetime());
} }
void AddChooseButtonWithIconAndRightText(not_null<Ui::VerticalLayout *> container, void AddChooseButtonWithIconAndRightText(not_null<Ui::VerticalLayout *> container,
@ -341,8 +348,7 @@ void AddChooseButtonWithIconAndRightText(not_null<Ui::VerticalLayout *> containe
rpl::producer<QString> text, rpl::producer<QString> text,
rpl::producer<QString> boxTitle, rpl::producer<QString> boxTitle,
const style::icon &icon, const style::icon &icon,
const Fn<void(int)> &setter) const Fn<void(int)> &setter) {
{
auto reactiveVal = container->lifetime().make_state<rpl::variable<int>>(initialState); auto reactiveVal = container->lifetime().make_state<rpl::variable<int>>(initialState);
rpl::producer<QString> rightTextReactive = reactiveVal->value() | rpl::map( rpl::producer<QString> rightTextReactive = reactiveVal->value() | rpl::map(
@ -368,34 +374,31 @@ void AddChooseButtonWithIconAndRightText(not_null<Ui::VerticalLayout *> containe
reactiveVal->force_assign(index); reactiveVal->force_assign(index);
}; };
SingleChoiceBox(box, { SingleChoiceBox(box,
.title = boxTitle, {
.options = options, .title = boxTitle,
.initialSelection = reactiveVal->current(), .options = options,
.callback = save, .initialSelection = reactiveVal->current(),
}); .callback = save,
});
})); }));
}); });
} }
namespace Settings namespace Settings {
{
rpl::producer<QString> Ayu::title() rpl::producer<QString> Ayu::title() {
{
return tr::ayu_AyuPreferences(); return tr::ayu_AyuPreferences();
} }
Ayu::Ayu( Ayu::Ayu(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller)
: Section(parent) : Section(parent) {
{
setupContent(controller); setupContent(controller);
} }
void SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container) void SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader()); AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader());
@ -441,8 +444,7 @@ void SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container)
AddCollapsibleToggle(container, tr::ayu_GhostEssentialsHeader(), checkboxes, true); AddCollapsibleToggle(container, tr::ayu_GhostEssentialsHeader(), checkboxes, true);
} }
void SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container) void SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
std::vector checkboxes{ std::vector checkboxes{
@ -472,8 +474,7 @@ void SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container)
AddCollapsibleToggle(container, tr::ayu_MarkReadAfterAction(), checkboxes, false); AddCollapsibleToggle(container, tr::ayu_MarkReadAfterAction(), checkboxes, false);
} }
void SetupGhostEssentials(not_null<Ui::VerticalLayout *> container) void SetupGhostEssentials(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
SetupGhostModeToggle(container); SetupGhostModeToggle(container);
@ -499,11 +500,11 @@ void SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_useScheduledMessages(enabled); settings->set_useScheduledMessages(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
} }
void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container) void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_SpyEssentialsHeader()); AddSubsectionTitle(container, tr::ayu_SpyEssentialsHeader());
@ -528,7 +529,8 @@ void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_saveDeletedMessages(enabled); settings->set_saveDeletedMessages(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -546,11 +548,11 @@ void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_saveMessagesHistory(enabled); settings->set_saveMessagesHistory(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
} }
void SetupQoLToggles(not_null<Ui::VerticalLayout *> container) void SetupQoLToggles(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_QoLTogglesHeader()); AddSubsectionTitle(container, tr::ayu_QoLTogglesHeader());
@ -571,7 +573,8 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_disableAds(enabled); settings->set_disableAds(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -589,7 +592,8 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_disableStories(enabled); settings->set_disableStories(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -607,7 +611,8 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_simpleQuotesAndReplies(enabled); settings->set_simpleQuotesAndReplies(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
std::vector checkboxes = { std::vector checkboxes = {
NestedEntry{ NestedEntry{
@ -648,7 +653,8 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_uploadSpeedBoost(enabled); settings->set_uploadSpeedBoost(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddSkip(container); AddSkip(container);
AddDivider(container); AddDivider(container);
@ -670,7 +676,8 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_disableNotificationsDelay(enabled); settings->set_disableNotificationsDelay(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -688,7 +695,8 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_localPremium(enabled); settings->set_localPremium(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -706,19 +714,18 @@ void SetupQoLToggles(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_copyUsernameAsLink(enabled); settings->set_copyUsernameAsLink(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
} }
void SetupAppIcon(not_null<Ui::VerticalLayout *> container) void SetupAppIcon(not_null<Ui::VerticalLayout *> container) {
{
container->add( container->add(
object_ptr<IconPicker>(container), object_ptr<IconPicker>(container),
st::settingsCheckboxPadding); st::settingsCheckboxPadding);
} }
void SetupContextMenuElements(not_null<Ui::VerticalLayout *> container, void SetupContextMenuElements(not_null<Ui::VerticalLayout *> container,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSkip(container); AddSkip(container);
@ -801,8 +808,7 @@ void SetupContextMenuElements(not_null<Ui::VerticalLayout *> container,
AddDividerText(container, tr::ayu_SettingsContextMenuDescription()); AddDividerText(container, tr::ayu_SettingsContextMenuDescription());
} }
void SetupDrawerElements(not_null<Ui::VerticalLayout *> container) void SetupDrawerElements(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSkip(container); AddSkip(container);
@ -825,7 +831,8 @@ void SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_showLReadToggleInDrawer(enabled); settings->set_showLReadToggleInDrawer(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -844,7 +851,8 @@ void SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_showSReadToggleInDrawer(enabled); settings->set_showSReadToggleInDrawer(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -863,7 +871,8 @@ void SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_showGhostToggleInDrawer(enabled); settings->set_showGhostToggleInDrawer(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
#ifdef WIN32 #ifdef WIN32
AddButtonWithIcon( AddButtonWithIcon(
@ -883,12 +892,12 @@ void SetupDrawerElements(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_showStreamerToggleInDrawer(enabled); settings->set_showStreamerToggleInDrawer(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
#endif #endif
} }
void SetupTrayElements(not_null<Ui::VerticalLayout *> container) void SetupTrayElements(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSkip(container); AddSkip(container);
@ -910,7 +919,8 @@ void SetupTrayElements(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_showGhostToggleInTray(enabled); settings->set_showGhostToggleInTray(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
#ifdef WIN32 #ifdef WIN32
AddButtonWithIcon( AddButtonWithIcon(
@ -929,13 +939,13 @@ void SetupTrayElements(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_showStreamerToggleInTray(enabled); settings->set_showStreamerToggleInTray(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
#endif #endif
} }
void SetupShowPeerId(not_null<Ui::VerticalLayout *> container, void SetupShowPeerId(not_null<Ui::VerticalLayout *> container,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
const auto options = std::vector{ const auto options = std::vector{
@ -966,18 +976,18 @@ void SetupShowPeerId(not_null<Ui::VerticalLayout *> container,
settings->set_showPeerId(index); settings->set_showPeerId(index);
AyuSettings::save(); AyuSettings::save();
}; };
SingleChoiceBox(box, { SingleChoiceBox(box,
.title = tr::ayu_SettingsShowID(), {
.options = options, .title = tr::ayu_SettingsShowID(),
.initialSelection = settings->showPeerId, .options = options,
.callback = save, .initialSelection = settings->showPeerId,
}); .callback = save,
});
})); }));
}); });
} }
void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container) void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
container->add( container->add(
@ -1003,12 +1013,17 @@ void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container)
updateLabel(settings->recentStickersCount); updateLabel(settings->recentStickersCount);
slider->setPseudoDiscrete( slider->setPseudoDiscrete(
100 + 1, // thx tg 100 + 1,
// thx tg
[=](int amount) [=](int amount)
{ return amount; }, {
return amount;
},
settings->recentStickersCount, settings->recentStickersCount,
[=](int amount) [=](int amount)
{ updateLabel(amount); }, {
updateLabel(amount);
},
[=](int amount) [=](int amount)
{ {
updateLabel(amount); updateLabel(amount);
@ -1018,8 +1033,7 @@ void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container)
}); });
} }
void SetupFonts(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller) void SetupFonts(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller) {
{
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
const auto commonButton = AddButtonWithLabel( const auto commonButton = AddButtonWithLabel(
@ -1034,13 +1048,14 @@ void SetupFonts(not_null<Ui::VerticalLayout *> container, not_null<Window::Sessi
commonButton->addClickHandler( commonButton->addClickHandler(
[=] [=]
{ {
*commonGuard = AyuUi::FontSelectorBox::Show(controller, [=](QString font) *commonGuard = AyuUi::FontSelectorBox::Show(controller,
{ [=](QString font)
auto ayuSettings = &AyuSettings::getInstance(); {
auto ayuSettings = &AyuSettings::getInstance();
ayuSettings->set_mainFont(std::move(font)); ayuSettings->set_mainFont(std::move(font));
AyuSettings::save(); AyuSettings::save();
}); });
}); });
const auto monoButton = AddButtonWithLabel( const auto monoButton = AddButtonWithLabel(
@ -1055,37 +1070,18 @@ void SetupFonts(not_null<Ui::VerticalLayout *> container, not_null<Window::Sessi
monoButton->addClickHandler( monoButton->addClickHandler(
[=] [=]
{ {
*monoGuard = AyuUi::FontSelectorBox::Show(controller, [=](QString font) *monoGuard = AyuUi::FontSelectorBox::Show(controller,
{ [=](QString font)
auto ayuSettings = &AyuSettings::getInstance(); {
auto ayuSettings = &AyuSettings::getInstance();
ayuSettings->set_monoFont(std::move(font)); ayuSettings->set_monoFont(std::move(font));
AyuSettings::save(); AyuSettings::save();
}); });
});
}
void SetupAyuSync(not_null<Ui::VerticalLayout *> container)
{
AddSubsectionTitle(container, tr::ayu_AyuSyncHeader());
auto text = AyuSync::isAgentDownloaded() ? tr::ayu_AyuSyncOpenPreferences() : tr::ayu_AyuSyncDownloadAgent();
AddButtonWithIcon(
container,
text,
st::settingsButtonNoIcon
)->addClickHandler(
[=]
{
auto controller = &AyuSync::getInstance();
controller->initializeAgent();
}); });
} }
void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container) void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container) {
{
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_ConfirmationsTitle()); AddSubsectionTitle(container, tr::ayu_ConfirmationsTitle());
@ -1106,7 +1102,8 @@ void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_stickerConfirmation(enabled); settings->set_stickerConfirmation(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -1124,7 +1121,8 @@ void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_gifConfirmation(enabled); settings->set_gifConfirmation(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -1142,7 +1140,8 @@ void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container)
{ {
settings->set_voiceConfirmation(enabled); settings->set_voiceConfirmation(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
} }
void SetupMarks(not_null<Ui::VerticalLayout *> container) { void SetupMarks(not_null<Ui::VerticalLayout *> container) {
@ -1192,7 +1191,8 @@ void SetupFolderSettings(not_null<Ui::VerticalLayout *> container) {
{ {
settings->set_hideNotificationCounters(enabled); settings->set_hideNotificationCounters(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -1210,7 +1210,8 @@ void SetupFolderSettings(not_null<Ui::VerticalLayout *> container) {
{ {
settings->set_hideAllChatsFolder(enabled); settings->set_hideAllChatsFolder(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
} }
void SetupNerdSettings(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller) { void SetupNerdSettings(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller) {
@ -1234,7 +1235,8 @@ void SetupNerdSettings(not_null<Ui::VerticalLayout *> container, not_null<Window
{ {
settings->set_showMessageSeconds(enabled); settings->set_showMessageSeconds(enabled);
AyuSettings::save(); AyuSettings::save();
}, container->lifetime()); },
container->lifetime());
AddButtonWithIcon( AddButtonWithIcon(
container, container,
@ -1257,8 +1259,7 @@ void SetupNerdSettings(not_null<Ui::VerticalLayout *> container, not_null<Window
} }
void SetupCustomization(not_null<Ui::VerticalLayout *> container, void SetupCustomization(not_null<Ui::VerticalLayout *> container,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller) {
{
AddSubsectionTitle(container, tr::ayu_CustomizationHeader()); AddSubsectionTitle(container, tr::ayu_CustomizationHeader());
SetupAppIcon(container); SetupAppIcon(container);
@ -1299,8 +1300,7 @@ void SetupCustomization(not_null<Ui::VerticalLayout *> container,
} }
void SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container, void SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container,
not_null<Window::SessionController *> controller) not_null<Window::SessionController *> controller) {
{
AddSkip(container); AddSkip(container);
SetupGhostEssentials(container); SetupGhostEssentials(container);
AddSkip(container); AddSkip(container);
@ -1324,15 +1324,6 @@ void SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container,
AddSkip(container); AddSkip(container);
AddDividerText(container, tr::ayu_SettingsCustomizationHint()); AddDividerText(container, tr::ayu_SettingsCustomizationHint());
// todo: compilation flag
if constexpr (false) {
AddSkip(container);
SetupAyuSync(container);
AddSkip(container);
AddDivider(container);
}
AddSkip(container); AddSkip(container);
SetupSendConfirmations(container); SetupSendConfirmations(container);
AddSkip(container); AddSkip(container);
@ -1341,8 +1332,7 @@ void SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container,
AddDividerText(container, tr::ayu_SettingsWatermark()); AddDividerText(container, tr::ayu_SettingsWatermark());
} }
void Ayu::setupContent(not_null<Window::SessionController *> controller) void Ayu::setupContent(not_null<Window::SessionController *> controller) {
{
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this); const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
SetupAyuGramSettings(content, controller); SetupAyuGramSettings(content, controller);

View file

@ -6,20 +6,17 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "base/options.h"
#include "settings/settings_common_session.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "settings/settings_common_session.h"
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> class Ayu : public Section<Ayu>
{ {

View file

@ -10,19 +10,16 @@
#include "data/data_peer.h" #include "data/data_peer.h"
#include "ui/text/text_utilities.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(getBareID(peer)); auto resultId = QString::number(getBareID(peer));
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->showPeerId == 2) { if (settings->showPeerId == 2) {
if (peer->isChannel()) { if (peer->isChannel()) {
resultId = QString::number(peerToChannel(peer->id).bare - kMaxChannelId).prepend("-"); resultId = QString::number(peerToChannel(peer->id).bare - kMaxChannelId).prepend("-");
} } else if (peer->isChat()) {
else if (peer->isChat()) {
resultId = resultId.prepend("-"); resultId = resultId.prepend("-");
} }
} }
@ -30,19 +27,16 @@ QString IDString(not_null<PeerData *> peer)
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 topicRootId) rpl::producer<TextWithEntities> IDValue(MsgId topicRootId) {
{
return rpl::single(IDString(topicRootId)) | Ui::Text::ToWithEntities(); return rpl::single(IDString(topicRootId)) | Ui::Text::ToWithEntities();
} }

View file

@ -6,7 +6,6 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#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);

View file

@ -6,21 +6,18 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#include "ayu_mapper.h" #include "ayu_mapper.h"
#include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/history.h"
namespace AyuMapper {
namespace AyuMapper int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item) {
{
int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item)
{
int flags = 0; int flags = 0;
const auto thread = item->topic() const auto thread = item->topic()
? (Data::Thread *)item->topic() ? (Data::Thread *)item->topic()
: item->history(); : item->history();
const auto unseen = item->unread(thread); const auto unseen = item->unread(thread);
if (unseen) { if (unseen) {
flags |= 1; flags |= 1;
@ -59,9 +56,9 @@ int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item)
} }
// todo: legacy // todo: legacy
// if (item->isLegacy()) { // if (item->isLegacy()) {
// flags |= 524288; // flags |= 524288;
// } // }
if (item->hideEditedBadge()) { if (item->hideEditedBadge()) {
flags |= 2097152; flags |= 2097152;

View file

@ -6,8 +6,7 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
namespace AyuMapper namespace AyuMapper {
{
int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item); int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item);

View file

@ -8,31 +8,29 @@
#include <functional> #include <functional>
#include <QTimer> #include <QTimer>
#include "apiwrap.h"
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "lang_auto.h"
#include "ayu/ayu_worker.h"
#include "ayu/database/entities.h"
#include "core/mime_type.h" #include "core/mime_type.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_document_media.h"
#include "data/data_photo.h"
#include "data/data_photo_media.h"
#include "inline_bots/inline_bot_result.h"
#include "lang_auto.h"
#include "apiwrap.h"
#include "ayu/ayu_worker.h"
#include "data/data_forum.h" #include "data/data_forum.h"
#include "data/data_user.h"
#include "data/data_forum_topic.h" #include "data/data_forum_topic.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_peer_id.h" #include "data/data_peer_id.h"
#include "data/data_photo.h"
#include "data/data_user.h"
#include "inline_bots/inline_bot_result.h"
#include "ayu/sync/models.h"
#include "data/data_session.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_session.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "history/history_unread_things.h" #include "history/history_unread_things.h"
#include "data/data_histories.h" #include "main/main_account.h"
#include "main/main_session.h"
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
// https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java // https://github.com/AyuGram/AyuGram4AX/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/AyuConstants.java
@ -82,8 +80,7 @@ std::unordered_set<ID> extera_devs = {
139303278 139303278
}; };
Main::Session *getSession(ID userId) Main::Session *getSession(ID userId) {
{
for (const auto &[index, account] : Core::App().domain().accounts()) { for (const auto &[index, account] : Core::App().domain().accounts()) {
if (const auto session = account->maybeSession()) { if (const auto session = account->maybeSession()) {
if (session->userId().bare == userId) { if (session->userId().bare == userId) {
@ -95,26 +92,25 @@ Main::Session *getSession(ID userId)
return nullptr; return nullptr;
} }
bool accountExists(ID userId) bool accountExists(ID userId) {
{
return userId == 0 || getSession(userId) != nullptr; return userId == 0 || getSession(userId) != nullptr;
} }
void dispatchToMainThread(std::function<void()> callback, int delay) void dispatchToMainThread(std::function<void()> callback, int delay) {
{
auto timer = new QTimer(); auto timer = new QTimer();
timer->moveToThread(qApp->thread()); timer->moveToThread(qApp->thread());
timer->setSingleShot(true); timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() QObject::connect(timer,
{ &QTimer::timeout,
callback(); [=]()
timer->deleteLater(); {
}); callback();
timer->deleteLater();
});
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, delay)); QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, delay));
} }
not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session) not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session) {
{
if (dialogId > 0) { if (dialogId > 0) {
return session->data().history(peerFromUser(dialogId)); return session->data().history(peerFromUser(dialogId));
} }
@ -127,15 +123,14 @@ not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session)
return session->data().history(peerFromChat(abs(dialogId))); return session->data().history(peerFromChat(abs(dialogId)));
} }
ID getDialogIdFromPeer(not_null<PeerData *> peer) ID getDialogIdFromPeer(not_null<PeerData *> peer) {
{
auto peerId = peerIsUser(peer->id) auto peerId = peerIsUser(peer->id)
? peerToUser(peer->id).bare ? peerToUser(peer->id).bare
: peerIsChat(peer->id) : peerIsChat(peer->id)
? peerToChat(peer->id).bare ? peerToChat(peer->id).bare
: peerIsChannel(peer->id) : peerIsChannel(peer->id)
? peerToChannel(peer->id).bare ? peerToChannel(peer->id).bare
: peer->id.value; : peer->id.value;
if (peer->isChannel() || peer->isChat()) { if (peer->isChannel() || peer->isChat()) {
peerId = -peerId; peerId = -peerId;
@ -144,15 +139,15 @@ ID getDialogIdFromPeer(not_null<PeerData *> peer)
return peerId; return peerId;
} }
std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem *> item) std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem *> item) {
{
if (item->emptyText()) { if (item->emptyText()) {
return std::make_pair("", ""); return std::make_pair("", "");
} }
auto textWithEntities = item->originalText(); auto textWithEntities = item->originalText();
auto text = textWithEntities.text.toStdString(); auto text = textWithEntities.text.toStdString();
auto entities = EntitiesToMTP(&item->history()->owner().session(), textWithEntities.entities, auto entities = EntitiesToMTP(&item->history()->owner().session(),
textWithEntities.entities,
Api::ConvertOption::SkipLocal); Api::ConvertOption::SkipLocal);
if (entities.v.isEmpty()) { if (entities.v.isEmpty()) {
@ -167,29 +162,25 @@ std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryIt
return std::make_pair(text, std::string(reinterpret_cast<char *>(buff.data()), buff.size())); return std::make_pair(text, std::string(reinterpret_cast<char *>(buff.data()), buff.size()));
} }
ID getBareID(not_null<PeerData *> peer) ID getBareID(not_null<PeerData *> peer) {
{
return peerIsUser(peer->id) return peerIsUser(peer->id)
? peerToUser(peer->id).bare ? peerToUser(peer->id).bare
: peerIsChat(peer->id) : peerIsChat(peer->id)
? peerToChat(peer->id).bare ? peerToChat(peer->id).bare
: peerIsChannel(peer->id) : peerIsChannel(peer->id)
? peerToChannel(peer->id).bare ? peerToChannel(peer->id).bare
: peer->id.value; : peer->id.value;
} }
bool isAyuGramRelated(ID peerId) bool isAyuGramRelated(ID peerId) {
{
return ayugram_devs.contains(peerId) || ayugram_channels.contains(peerId); return ayugram_devs.contains(peerId) || ayugram_channels.contains(peerId);
} }
bool isExteraRelated(ID peerId) bool isExteraRelated(ID peerId) {
{
return extera_devs.contains(peerId) || extera_channels.contains(peerId); return extera_devs.contains(peerId) || extera_channels.contains(peerId);
} }
void MarkAsReadChatList(not_null<Dialogs::MainList *> list) void MarkAsReadChatList(not_null<Dialogs::MainList *> list) {
{
auto mark = std::vector<not_null<History *>>(); auto mark = std::vector<not_null<History *>>();
for (const auto &row : list->indexed()->all()) { for (const auto &row : list->indexed()->all()) {
if (const auto history = row->history()) { if (const auto history = row->history()) {
@ -199,8 +190,7 @@ void MarkAsReadChatList(not_null<Dialogs::MainList *> list)
ranges::for_each(mark, MarkAsReadThread); ranges::for_each(mark, MarkAsReadThread);
} }
void readMentions(base::weak_ptr<Data::Thread> weakThread) void readMentions(base::weak_ptr<Data::Thread> weakThread) {
{
const auto thread = weakThread.get(); const auto thread = weakThread.get();
if (!thread) { if (!thread) {
return; return;
@ -214,21 +204,19 @@ void readMentions(base::weak_ptr<Data::Thread> weakThread)
peer->input, peer->input,
MTP_int(rootId) MTP_int(rootId)
)).done([=](const MTPmessages_AffectedHistory &result) )).done([=](const MTPmessages_AffectedHistory &result)
{ {
const auto offset = peer->session().api().applyAffectedHistory( const auto offset = peer->session().api().applyAffectedHistory(
peer, peer,
result); result);
if (offset > 0) { if (offset > 0) {
readMentions(weakThread); readMentions(weakThread);
} } else {
else { peer->owner().history(peer)->clearUnreadMentionsFor(rootId);
peer->owner().history(peer)->clearUnreadMentionsFor(rootId); }
} }).send();
}).send();
} }
void readReactions(base::weak_ptr<Data::Thread> weakThread) void readReactions(base::weak_ptr<Data::Thread> weakThread) {
{
const auto thread = weakThread.get(); const auto thread = weakThread.get();
if (!thread) { if (!thread) {
return; return;
@ -242,21 +230,19 @@ void readReactions(base::weak_ptr<Data::Thread> weakThread)
peer->input, peer->input,
MTP_int(rootId) MTP_int(rootId)
)).done([=](const MTPmessages_AffectedHistory &result) )).done([=](const MTPmessages_AffectedHistory &result)
{ {
const auto offset = peer->session().api().applyAffectedHistory( const auto offset = peer->session().api().applyAffectedHistory(
peer, peer,
result); result);
if (offset > 0) { if (offset > 0) {
readReactions(weakThread); readReactions(weakThread);
} } else {
else { peer->owner().history(peer)->clearUnreadReactionsFor(rootId);
peer->owner().history(peer)->clearUnreadReactionsFor(rootId); }
} }).send();
}).send();
} }
void MarkAsReadThread(not_null<Data::Thread *> thread) void MarkAsReadThread(not_null<Data::Thread *> thread) {
{
const auto readHistory = [&](not_null<History *> history) const auto readHistory = [&](not_null<History *> history)
{ {
history->owner().histories().readInbox(history); history->owner().histories().readInbox(history);
@ -276,17 +262,15 @@ void MarkAsReadThread(not_null<Data::Thread *> thread)
if (const auto forum = thread->asForum()) { if (const auto forum = thread->asForum()) {
forum->enumerateTopics([]( forum->enumerateTopics([](
not_null<Data::ForumTopic *> topic) not_null<Data::ForumTopic *> topic)
{ {
MarkAsReadThread(topic); MarkAsReadThread(topic);
}); });
} } else if (const auto history = thread->asHistory()) {
else if (const auto history = thread->asHistory()) {
readHistory(history); readHistory(history);
if (const auto migrated = history->migrateSibling()) { if (const auto migrated = history->migrateSibling()) {
readHistory(migrated); readHistory(migrated);
} }
} } else if (const auto topic = thread->asTopic()) {
else if (const auto topic = thread->asTopic()) {
topic->readTillEnd(); topic->readTillEnd();
} }
} }
@ -302,32 +286,33 @@ void MarkAsReadThread(not_null<Data::Thread *> thread)
AyuWorker::markAsOnline(&thread->session()); AyuWorker::markAsOnline(&thread->session());
} }
void readHistory(not_null<HistoryItem *> message) void readHistory(not_null<HistoryItem *> message) {
{
const auto history = message->history(); const auto history = message->history();
const auto tillId = message->id; const auto tillId = message->id;
history->session().data().histories() history->session().data().histories()
.sendRequest(history, Data::Histories::RequestType::ReadInbox, [=](Fn<void()> finish) .sendRequest(history,
{ Data::Histories::RequestType::ReadInbox,
if (const auto channel = history->peer->asChannel()) { [=](Fn<void()> finish)
return history->session().api().request(MTPchannels_ReadHistory( {
channel->inputChannel, if (const auto channel = history->peer->asChannel()) {
MTP_int(tillId) return history->session().api().request(MTPchannels_ReadHistory(
)).done([=] { AyuWorker::markAsOnline(&history->session()); }).send(); channel->inputChannel,
} MTP_int(tillId)
)).done([=] { AyuWorker::markAsOnline(&history->session()); }).send();
}
return history->session().api().request(MTPmessages_ReadHistory( return history->session().api().request(MTPmessages_ReadHistory(
history->peer->input, history->peer->input,
MTP_int(tillId) MTP_int(tillId)
)).done([=](const MTPmessages_AffectedMessages &result) )).done([=](const MTPmessages_AffectedMessages &result)
{ {
history->session().api().applyAffectedMessages(history->peer, result); history->session().api().applyAffectedMessages(history->peer, result);
AyuWorker::markAsOnline(&history->session()); AyuWorker::markAsOnline(&history->session());
}).fail([=] }).fail([=]
{ {
}).send(); }).send();
}); });
if (history->unreadMentions().has()) { if (history->unreadMentions().has()) {
readMentions(history->asThread()); readMentions(history->asThread());
@ -338,8 +323,7 @@ void readHistory(not_null<HistoryItem *> message)
} }
} }
QString formatTTL(int time) QString formatTTL(int time) {
{
if (time == 0x7FFFFFFF) { if (time == 0x7FFFFFFF) {
return QString("👀 %1").arg(tr::ayu_OneViewTTL(tr::now)); return QString("👀 %1").arg(tr::ayu_OneViewTTL(tr::now));
} }
@ -347,8 +331,7 @@ QString formatTTL(int time)
return QString("🕓 %1s").arg(time); return QString("🕓 %1s").arg(time);
} }
QString getDCName(int dc) QString getDCName(int dc) {
{
const auto getName = [=](int dc) const auto getName = [=](int dc)
{ {
switch (dc) { switch (dc) {
@ -368,8 +351,7 @@ QString getDCName(int dc)
return QString("DC%1, %2").arg(dc).arg(getName(dc)); return QString("DC%1, %2").arg(dc).arg(getName(dc));
} }
QString getLocalizedAt() QString getLocalizedAt() {
{
static const auto val = tr::lng_mediaview_date_time( static const auto val = tr::lng_mediaview_date_time(
tr::now, tr::now,
lt_date, lt_date,
@ -379,8 +361,7 @@ QString getLocalizedAt()
return val; return val;
} }
QString formatDateTime(const QDateTime &date) QString formatDateTime(const QDateTime &date) {
{
const auto locale = QLocale::system(); const auto locale = QLocale::system();
const auto datePart = locale.toString(date.date(), QLocale::ShortFormat); const auto datePart = locale.toString(date.date(), QLocale::ShortFormat);
const auto timePart = locale.toString(date, "HH:mm:ss"); const auto timePart = locale.toString(date, "HH:mm:ss");
@ -388,8 +369,7 @@ QString formatDateTime(const QDateTime &date)
return datePart + getLocalizedAt() + timePart; return datePart + getLocalizedAt() + timePart;
} }
QString getMediaSize(not_null<HistoryItem *> message) QString getMediaSize(not_null<HistoryItem *> message) {
{
if (!message->media()) { if (!message->media()) {
return {}; return {};
} }
@ -400,10 +380,11 @@ QString getMediaSize(not_null<HistoryItem *> message)
const auto photo = media->photo(); const auto photo = media->photo();
int64 size = -1; int64 size = -1;
if (document) { // any file if (document) {
// any file
size = document->size; size = document->size;
} } else if (photo && photo->hasVideo()) {
else if (photo && photo->hasVideo()) { // video // video
size = photo->videoByteSize(Data::PhotoSize::Large); size = photo->videoByteSize(Data::PhotoSize::Large);
if (size == 0) { if (size == 0) {
size = photo->videoByteSize(Data::PhotoSize::Small); size = photo->videoByteSize(Data::PhotoSize::Small);
@ -411,8 +392,8 @@ QString getMediaSize(not_null<HistoryItem *> message)
if (size == 0) { if (size == 0) {
size = photo->videoByteSize(Data::PhotoSize::Thumbnail); size = photo->videoByteSize(Data::PhotoSize::Thumbnail);
} }
} } else if (photo && !photo->hasVideo()) {
else if (photo && !photo->hasVideo()) { // photo // photo
size = photo->imageByteSize(Data::PhotoSize::Large); size = photo->imageByteSize(Data::PhotoSize::Large);
if (size == 0) { if (size == 0) {
size = photo->imageByteSize(Data::PhotoSize::Small); size = photo->imageByteSize(Data::PhotoSize::Small);
@ -429,8 +410,7 @@ QString getMediaSize(not_null<HistoryItem *> message)
return Ui::FormatSizeText(size); return Ui::FormatSizeText(size);
} }
QString getMediaMime(not_null<HistoryItem *> message) QString getMediaMime(not_null<HistoryItem *> message) {
{
if (!message->media()) { if (!message->media()) {
return {}; return {};
} }
@ -440,21 +420,21 @@ QString getMediaMime(not_null<HistoryItem *> message)
const auto document = media->document(); const auto document = media->document();
const auto photo = media->photo(); const auto photo = media->photo();
if (document) { // any file if (document) {
// any file
return document->mimeString(); return document->mimeString();
} } else if (photo && photo->hasVideo()) {
else if (photo && photo->hasVideo()) { // video // video
return "video/mp4"; return "video/mp4";
} } else if (photo && !photo->hasVideo()) {
else if (photo && !photo->hasVideo()) { // photo // photo
return "image/jpeg"; return "image/jpeg";
} }
return {}; return {};
} }
QString getMediaName(not_null<HistoryItem *> message) QString getMediaName(not_null<HistoryItem *> message) {
{
if (!message->media()) { if (!message->media()) {
return {}; return {};
} }
@ -470,8 +450,7 @@ QString getMediaName(not_null<HistoryItem *> message)
return {}; return {};
} }
QString getMediaResolution(not_null<HistoryItem *> message) QString getMediaResolution(not_null<HistoryItem *> message) {
{
if (!message->media()) { if (!message->media()) {
return {}; return {};
} }
@ -492,8 +471,7 @@ QString getMediaResolution(not_null<HistoryItem *> message)
if (document) { if (document) {
return formatQSize(document->dimensions); return formatQSize(document->dimensions);
} } else if (photo) {
else if (photo) {
auto result = photo->size(Data::PhotoSize::Large); auto result = photo->size(Data::PhotoSize::Large);
if (!result.has_value()) { if (!result.has_value()) {
result = photo->size(Data::PhotoSize::Small); result = photo->size(Data::PhotoSize::Small);
@ -507,8 +485,7 @@ QString getMediaResolution(not_null<HistoryItem *> message)
return {}; return {};
} }
QString getMediaDC(not_null<HistoryItem *> message) QString getMediaDC(not_null<HistoryItem *> message) {
{
if (!message->media()) { if (!message->media()) {
return {}; return {};
} }
@ -520,16 +497,14 @@ QString getMediaDC(not_null<HistoryItem *> message)
if (document) { if (document) {
return getDCName(document->getDC()); return getDCName(document->getDC());
} } else if (photo) {
else if (photo) {
return getDCName(photo->getDC()); return getDCName(photo->getDC());
} }
return {}; return {};
} }
void resolveUser(ID userId, const QString &username, Main::Session *session, const Callback &callback) void resolveUser(ID userId, const QString &username, Main::Session *session, const Callback &callback) {
{
auto normalized = username.trimmed().toLower(); auto normalized = username.trimmed().toLower();
if (normalized.isEmpty()) { if (normalized.isEmpty()) {
callback(QString(), nullptr); callback(QString(), nullptr);
@ -545,30 +520,29 @@ void resolveUser(ID userId, const QString &username, Main::Session *session, con
session->api().request(MTPcontacts_ResolveUsername( session->api().request(MTPcontacts_ResolveUsername(
MTP_string(normalized) MTP_string(normalized)
)).done([=](const MTPcontacts_ResolvedPeer &result) )).done([=](const MTPcontacts_ResolvedPeer &result)
{ {
Expects(result.type() == mtpc_contacts_resolvedPeer); Expects(result.type() == mtpc_contacts_resolvedPeer);
auto &data = result.c_contacts_resolvedPeer(); auto &data = result.c_contacts_resolvedPeer();
session->data().processUsers(data.vusers()); session->data().processUsers(data.vusers());
session->data().processChats(data.vchats()); session->data().processChats(data.vchats());
const auto peer = session->data().peerLoaded( const auto peer = session->data().peerLoaded(
peerFromMTP(data.vpeer())); peerFromMTP(data.vpeer()));
if (const auto user = peer ? peer->asUser() : nullptr) { if (const auto user = peer ? peer->asUser() : nullptr) {
if (user->id.value == userId) { if (user->id.value == userId) {
callback(normalized, user); callback(normalized, user);
return; return;
} }
} }
callback(normalized, nullptr); callback(normalized, nullptr);
}).fail([=] }).fail([=]
{ {
callback(QString(), nullptr); callback(QString(), nullptr);
}).send(); }).send();
} }
void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cache, const Callback &callback) void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cache, const Callback &callback) {
{
if (!session) { if (!session) {
callback(QString(), nullptr); callback(QString(), nullptr);
return; return;
@ -579,12 +553,14 @@ void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cac
if (!bot) { if (!bot) {
if (searchUserFlag) { if (searchUserFlag) {
resolveUser(botId, "tgdb_bot", session, [=](const QString &title, UserData *data) resolveUser(botId,
{ "tgdb_bot",
searchUser(userId, session, false, false, callback); session,
}); [=](const QString &title, UserData *data)
} {
else { searchUser(userId, session, false, false, callback);
});
} else {
callback(QString(), nullptr); callback(QString(), nullptr);
} }
return; return;
@ -598,107 +574,113 @@ void searchUser(ID userId, Main::Session *session, bool searchUserFlag, bool cac
MTP_string(QString::number(userId)), MTP_string(QString::number(userId)),
MTP_string("") MTP_string("")
)).done([=](const MTPmessages_BotResults &result) )).done([=](const MTPmessages_BotResults &result)
{ {
if (result.type() != mtpc_messages_botResults) { if (result.type() != mtpc_messages_botResults) {
callback(QString(), nullptr); callback(QString(), nullptr);
return; return;
}
auto &d = result.c_messages_botResults();
session->data().processUsers(d.vusers());
auto &v = d.vresults().v;
auto queryId = d.vquery_id().v;
auto added = 0;
for (const auto &res : v) {
const auto message = res.match(
[&](const MTPDbotInlineResult &data)
{
return &data.vsend_message();
},
[&](const MTPDbotInlineMediaResult &data)
{
return &data.vsend_message();
});
const auto text = message->match(
[&](const MTPDbotInlineMessageMediaAuto &data)
{
return QString();
},
[&](const MTPDbotInlineMessageText &data)
{
return qs(data.vmessage());
},
[&](const MTPDbotInlineMessageMediaGeo &data)
{
return QString();
},
[&](const MTPDbotInlineMessageMediaVenue &data)
{
return QString();
},
[&](const MTPDbotInlineMessageMediaContact &data)
{
return QString();
},
[&](const MTPDbotInlineMessageMediaInvoice &data)
{
return QString();
},
[&](const MTPDbotInlineMessageMediaWebPage &data)
{
return QString();
});
if (text.isEmpty()) {
continue;
}
ID id = 0; // 🆔
QString title; // 🏷
QString username; // 📧
for (const auto &line : text.split('\n')) {
if (line.startsWith("🆔")) {
id = line.mid(line.indexOf(':') + 1).toLongLong();
} else if (line.startsWith("🏷")) {
title = line.mid(line.indexOf(':') + 1);
} else if (line.startsWith("📧")) {
username = line.mid(line.indexOf(':') + 1);
} }
auto &d = result.c_messages_botResults(); }
session->data().processUsers(d.vusers());
auto &v = d.vresults().v; if (id == 0) {
auto queryId = d.vquery_id().v; continue;
}
auto added = 0; if (id != userId) {
for (const auto &res : v) { continue;
const auto message = res.match( }
[&](const MTPDbotInlineResult &data)
{
return &data.vsend_message();
}, [&](const MTPDbotInlineMediaResult &data)
{
return &data.vsend_message();
});
const auto text = message->match( if (!username.isEmpty()) {
[&](const MTPDbotInlineMessageMediaAuto &data) resolveUser(id,
{ username,
return QString(); session,
}, [&](const MTPDbotInlineMessageText &data) [=](const QString &titleInner, UserData *data)
{ {
return qs(data.vmessage()); if (data) {
}, [&](const MTPDbotInlineMessageMediaGeo &data) callback(titleInner, data);
{ } else {
return QString(); callback(title, nullptr);
}, [&](const MTPDbotInlineMessageMediaVenue &data) }
{ });
return QString(); return;
}, [&](const MTPDbotInlineMessageMediaContact &data) }
{
return QString();
}, [&](const MTPDbotInlineMessageMediaInvoice &data)
{
return QString();
}, [&](const MTPDbotInlineMessageMediaWebPage &data)
{
return QString();
});
if (text.isEmpty()) { if (!title.isEmpty()) {
continue; callback(title, nullptr);
} }
}
ID id = 0; // 🆔 callback(QString(), nullptr);
QString title; // 🏷 }).fail([=]
QString username; // 📧 {
callback(QString(), nullptr);
for (const auto &line : text.split('\n')) { }).handleAllErrors().send();
if (line.startsWith("🆔")) {
id = line.mid(line.indexOf(':') + 1).toLongLong();
}
else if (line.startsWith("🏷")) {
title = line.mid(line.indexOf(':') + 1);
}
else if (line.startsWith("📧")) {
username = line.mid(line.indexOf(':') + 1);
}
}
if (id == 0) {
continue;
}
if (id != userId) {
continue;
}
if (!username.isEmpty()) {
resolveUser(id, username, session, [=](const QString &titleInner, UserData *data)
{
if (data) {
callback(titleInner, data);
}
else {
callback(title, nullptr);
}
});
return;
}
if (!title.isEmpty()) {
callback(title, nullptr);
}
}
callback(QString(), nullptr);
}).fail([=]
{
callback(QString(), nullptr);
}).handleAllErrors().send();
} }
void searchById(ID userId, Main::Session *session, bool retry, const Callback &callback) void searchById(ID userId, Main::Session *session, bool retry, const Callback &callback) {
{
if (userId == 0 || !session) { if (userId == 0 || !session) {
callback(QString(), nullptr); callback(QString(), nullptr);
return; return;
@ -710,23 +692,24 @@ void searchById(ID userId, Main::Session *session, bool retry, const Callback &c
return; return;
} }
searchUser(userId, session, true, true, [=](const QString &title, UserData *data) searchUser(userId,
{ session,
if (data && data->accessHash()) { true,
callback(title, data); true,
} [=](const QString &title, UserData *data)
else { {
if (retry) { if (data && data->accessHash()) {
searchById(0x100000000 + userId, session, false, callback); callback(title, data);
} } else {
else { if (retry) {
callback(QString(), nullptr); searchById(0x100000000 + userId, session, false, callback);
} } else {
} callback(QString(), nullptr);
}); }
}
});
} }
void searchById(ID userId, Main::Session *session, const Callback &callback) void searchById(ID userId, Main::Session *session, const Callback &callback) {
{
searchById(userId, session, true, callback); searchById(userId, session, true, callback);
} }

View file

@ -6,15 +6,13 @@
// Copyright @Radolyn, 2023 // Copyright @Radolyn, 2023
#pragma once #pragma once
#include "ayu/sync/models.h" #include "ayu/database/entities.h"
#include "core/application.h" #include "core/application.h"
#include "main/main_account.h"
#include "main/main_domain.h"
#include "main/main_session.h"
#include "dialogs/dialogs_main_list.h" #include "dialogs/dialogs_main_list.h"
#include "main/main_domain.h"
using Callback = Fn<void(const QString&, UserData *)>; using Callback = Fn<void(const QString &, UserData *)>;
Main::Session *getSession(ID userId); Main::Session *getSession(ID userId);
bool accountExists(ID userId); bool accountExists(ID userId);
@ -45,4 +43,4 @@ QString getMediaResolution(not_null<HistoryItem *> message);
QString getMediaDC(not_null<HistoryItem *> message); QString getMediaDC(not_null<HistoryItem *> message);
void searchById(ID userId, Main::Session *session, bool retry, const Callback &callback); void searchById(ID userId, Main::Session *session, bool retry, const Callback &callback);
void searchById(ID userId, Main::Session *session, const Callback& callback); void searchById(ID userId, Main::Session *session, const Callback &callback);

View file

@ -10,8 +10,7 @@
#include <ShlObj_core.h> #include <ShlObj_core.h>
void reloadAppIconFromTaskBar() void reloadAppIconFromTaskBar() {
{
QString appdata = QDir::fromNativeSeparators(qgetenv("APPDATA")); QString appdata = QDir::fromNativeSeparators(qgetenv("APPDATA"));
QString ayugramIconPath = appdata + "/AyuGram.ico"; QString ayugramIconPath = appdata + "/AyuGram.ico";
@ -24,7 +23,10 @@ void reloadAppIconFromTaskBar()
IShellLink *pShellLink = NULL; IShellLink *pShellLink = NULL;
IPersistFile *pPersistFile = NULL; IPersistFile *pPersistFile = NULL;
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, HRESULT hr = CoCreateInstance(CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLink,
(void **)&pShellLink); (void **)&pShellLink);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile); hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
@ -48,4 +50,4 @@ void reloadAppIconFromTaskBar()
} }
} }
#endif #endif

View file

@ -645,8 +645,8 @@ void SendFilesBox::addMenuButton() {
targetImage.loadFromData(targetArray, "WEBP"); targetImage.loadFromData(targetArray, "WEBP");
addFiles(Storage::PrepareMediaFromImage(std::move(targetImage), addFiles(Storage::PrepareMediaFromImage(std::move(targetImage),
std::move(targetArray), std::move(targetArray),
st::sendMediaPreviewSize)); st::sendMediaPreviewSize));
_list.overrideSendImagesAsPhotos = false; _list.overrideSendImagesAsPhotos = false;
initSendWay(); initSendWay();
@ -1427,8 +1427,7 @@ void SendFilesBox::send(
bool ctrlShiftEnter) { bool ctrlShiftEnter) {
// AyuGram useScheduledMessages // AyuGram useScheduledMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->useScheduledMessages && !options.scheduled) if (settings->useScheduledMessages && !options.scheduled) {
{
DEBUG_LOG(("[AyuGram] Scheduling files")); DEBUG_LOG(("[AyuGram] Scheduling files"));
auto current = base::unixtime::now(); auto current = base::unixtime::now();
options.scheduled = current + 60; // well, files can be huge... options.scheduled = current + 60; // well, files can be huge...

View file

@ -542,33 +542,40 @@ void StickerSetBox::updateButtons() {
? tr::lng_stickers_copied_emoji(tr::now) ? tr::lng_stickers_copied_emoji(tr::now)
: tr::lng_stickers_copied(tr::now)); : tr::lng_stickers_copied(tr::now));
}; };
const auto addAuthorPack = [=](const std::shared_ptr<base::unique_qptr<Ui::PopupMenu>>& menu) { const auto addAuthorPack = [=](const std::shared_ptr<base::unique_qptr<Ui::PopupMenu>> &menu)
{
if (type == Data::StickersType::Stickers) { if (type == Data::StickersType::Stickers) {
const auto pointer = Ui::MakeWeak(this); const auto pointer = Ui::MakeWeak(this);
(*menu)->addAction(tr::ayu_MessageDetailsPackOwnerPC(tr::now), [=] (*menu)->addAction(
{ tr::ayu_MessageDetailsPackOwnerPC(tr::now),
if (!pointer) { [=]
return;
}
searchById(_inner->setId() >> 32, _session, [=](const QString &username, UserData *user)
{ {
if (!pointer) { if (!pointer) {
return; return;
} }
if (!user) { searchById(
showToast(tr::ayu_UserNotFoundMessage(tr::now)); _inner->setId() >> 32,
return; _session,
} [=](const QString &username, UserData *user)
{
if (!pointer) {
return;
}
if (const auto window = _session->tryResolveWindow()) { if (!user) {
if (const auto mainWidget = window->widget()->sessionController()) { showToast(tr::ayu_UserNotFoundMessage(tr::now));
mainWidget->showPeer(user); return;
} }
}
}); if (const auto window = _session->tryResolveWindow()) {
}, &st::menuIconProfile); if (const auto mainWidget = window->widget()->sessionController()) {
mainWidget->showPeer(user);
}
}
});
},
&st::menuIconProfile);
} }
}; };
if (_inner->notInstalled()) { if (_inner->notInstalled()) {

View file

@ -493,23 +493,24 @@ void GifsListWidget::selectInlineResult(
if (forceSend || (media && preview.loaded())) { if (forceSend || (media && preview.loaded())) {
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
auto from = messageSendingFrom(); auto from = messageSendingFrom();
auto sendGIFCallback = crl::guard(this, [=] auto sendGIFCallback = crl::guard(
{ this,
_fileChosen.fire({ [=]
.document = document, {
.options = options, _fileChosen.fire({
.messageSendingFrom = from, .document = document,
}); .options = options,
}); .messageSendingFrom = from,
});
});
if (settings->gifConfirmation) { if (settings->gifConfirmation) {
Ui::show(Ui::MakeConfirmBox({ Ui::show(Ui::MakeConfirmBox({
.text = tr::ayu_ConfirmationGIF(), .text = tr::ayu_ConfirmationGIF(),
.confirmed = sendGIFCallback, .confirmed = sendGIFCallback,
.confirmText = tr::lng_send_button() .confirmText = tr::lng_send_button()
})); }));
} } else {
else {
sendGIFCallback(); sendGIFCallback();
} }
} else if (!preview.usingThumbnail()) { } else if (!preview.usingThumbnail()) {

View file

@ -1756,23 +1756,25 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
auto from = messageSentAnimationInfo( auto from = messageSentAnimationInfo(
sticker->section, sticker->section,
sticker->index, sticker->index,
document); document
auto sendStickerCallback = crl::guard(this, [=, this] );
{ auto sendStickerCallback = crl::guard(
_chosen.fire({ this,
.document = document, [=, this]
.messageSendingFrom = from, {
}); _chosen.fire({
}); .document = document,
.messageSendingFrom = from,
});
});
if (settings->stickerConfirmation) { if (settings->stickerConfirmation) {
Ui::show(Ui::MakeConfirmBox({ Ui::show(Ui::MakeConfirmBox({
.text = tr::ayu_ConfirmationSticker(), .text = tr::ayu_ConfirmationSticker(),
.confirmed = sendStickerCallback, .confirmed = sendStickerCallback,
.confirmText = tr::lng_send_button() .confirmText = tr::lng_send_button()
})); }));
} } else {
else {
sendStickerCallback(); sendStickerCallback();
} }
} }

View file

@ -354,11 +354,9 @@ bool Manager::readCustomFile() {
void Manager::fillDefaults() { void Manager::fillDefaults() {
const auto ctrl = Platform::IsMac() ? u"meta"_q : u"ctrl"_q; const auto ctrl = Platform::IsMac() ? u"meta"_q : u"ctrl"_q;
// set(u"ctrl+w"_q, Command::Close);
set(u"ctrl+f4"_q, Command::Close); set(u"ctrl+f4"_q, Command::Close);
set(u"ctrl+l"_q, Command::Lock); set(u"ctrl+l"_q, Command::Lock);
set(u"ctrl+m"_q, Command::Minimize); set(u"ctrl+m"_q, Command::Minimize);
// set(u"ctrl+q"_q, Command::Quit);
set(u"media play"_q, Command::MediaPlay); set(u"media play"_q, Command::MediaPlay);
set(u"media pause"_q, Command::MediaPause); set(u"media pause"_q, Command::MediaPause);

View file

@ -1250,15 +1250,6 @@ void Updater::start(bool forceWait) {
startImplementation( startImplementation(
&_httpImplementation, &_httpImplementation,
std::make_unique<HttpChecker>(_testing)); std::make_unique<HttpChecker>(_testing));
// AyuGram: removed
if (false)
{
startImplementation(
&_mtpImplementation,
std::make_unique<MtpChecker>(_session, _testing));
}
_checking.fire({}); _checking.fire({});
} else { } else {
_timer.callOnce((updateInSecs + 5) * crl::time(1000)); _timer.callOnce((updateInSecs + 5) * crl::time(1000));

View file

@ -286,8 +286,7 @@ public:
std::unique_ptr<Data::UploadState> uploadingData; std::unique_ptr<Data::UploadState> uploadingData;
int32 getDC() const int32 getDC() const {
{
return _dc; return _dc;
} }

View file

@ -29,8 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
// AyuGram includes // AyuGram includes
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
#include "ayu/ayu_state.h"
#include "ayu/sync/ayu_sync_controller.h"
namespace Data { namespace Data {
@ -247,8 +245,6 @@ void Histories::readInboxTill(
Core::App().notifications().clearIncomingFromHistory(history); Core::App().notifications().clearIncomingFromHistory(history);
AyuSync::getInstance().syncRead(history, tillId);
const auto needsRequest = history->readInboxTillNeedsRequest(tillId); const auto needsRequest = history->readInboxTillNeedsRequest(tillId);
if (!needsRequest && !force) { if (!needsRequest && !force) {
DEBUG_LOG(("Reading: readInboxTill finish 1.")); DEBUG_LOG(("Reading: readInboxTill finish 1."));
@ -579,8 +575,7 @@ void Histories::sendReadRequests() {
// AyuGram sendReadMessages // AyuGram sendReadMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages) if (!settings->sendReadMessages) {
{
DEBUG_LOG(("[AyuGram] Don't read messages")); DEBUG_LOG(("[AyuGram] Don't read messages"));
_states.clear(); _states.clear();
return; return;
@ -624,7 +619,6 @@ void Histories::sendReadRequest(not_null<History*> history, State &state) {
).arg(tillId.bare)); ).arg(tillId.bare));
const auto finished = [=] { const auto finished = [=] {
auto state = lookup(history); auto state = lookup(history);
// Assert(state != nullptr);
if (state == nullptr) { if (state == nullptr) {
// dont care + didnt ask + cry about it + who asked + stay mad + get real + L + bleed + mald seethe cope harder + dilate + incorrect + hoes mad + pound sand + basic skill issue + typo + ratio + ur dad left + you fell off + no u + the audacity + triggered + repelled + ur a minor + k. + any askers + get a life + ok and? + cringe + copium + go outside + touch grass + kick rocks + quote tweet + think again + not based + not funny didnt laugh + social credits -999, 999, 999, 999 + get good + reported + ad hominem + ok boomer + small pp + ur allergic to sunlight + GG! + get rekt + trolled + your loss + muted + banned + kicked + permaban + useless + i slept with ur mom + yo momma + yo momma so fat + redpilled + no bitches allowed + i said it better + tiktok fan + get a life + unsubscribed + plundered + go tell reddit + donowalled + simp + get sticked bug LOL + talk nonsense + trump supporter + yourre a full time discord mod + youre* + grammar issue + nerd + get clapped + kys + lorem ipsum dolor sit amet + go outside + bleach + lol + gay + retard + autistic + reported + ask deez + ez clap + straight cash + idgaf + ratio again + stay mad + read FAQ + youre lost + you “re” + stay pressed + reverse double take back + pedophile + cancelled + done for + don't give a damn + get a job + sus + baka + sussy baka + get blocked + mad free + freer than air + furry + rip bozo + you're a (insert stereotype) + slight_smile + aired + cringe again + Super Idol的笑容 + mad cuz bad + my pronouns are xe, xem & xyr + irrelevant + deal with it + screencapped your bio + karen/kyle + jealous + you're deaf + balls + i'll be right back + go ahead whine about it + not straight + eat paper + you lose + count to three + your problem + no one cares + log off + don't care even more + sex offender + sex defender + get religion + not okay + glhf + NFT owner + you make bad memes + problematic + fall in line + dog water + you look like a wall + you dont know 2 + 2 with yo head ass + you are going to my cringe compilation + you cant count to five + try again + you failed kindergarten + rickrolled + no lifer + guten freunden schickt man einen deutschen panzer + you have a anime profile picture + an* + fatherless + motherless + sisterless + brotherless + orphan + you can't catch this ratio + catch some bitches + I don't care about your opinion + genshin player + you dress like garbage + 日本語がお上手ですね + get fucked + you cant understand what the word intelligence means with your dumb ass + you have hair + queued + put some thought into what you're going to do with that + stfu + go to bed + yes, i'm taller than you + i think your joke is funny + i rejected your mother's advances + marooned + you cant read + I win + final ratio // dont care + didnt ask + cry about it + who asked + stay mad + get real + L + bleed + mald seethe cope harder + dilate + incorrect + hoes mad + pound sand + basic skill issue + typo + ratio + ur dad left + you fell off + no u + the audacity + triggered + repelled + ur a minor + k. + any askers + get a life + ok and? + cringe + copium + go outside + touch grass + kick rocks + quote tweet + think again + not based + not funny didnt laugh + social credits -999, 999, 999, 999 + get good + reported + ad hominem + ok boomer + small pp + ur allergic to sunlight + GG! + get rekt + trolled + your loss + muted + banned + kicked + permaban + useless + i slept with ur mom + yo momma + yo momma so fat + redpilled + no bitches allowed + i said it better + tiktok fan + get a life + unsubscribed + plundered + go tell reddit + donowalled + simp + get sticked bug LOL + talk nonsense + trump supporter + yourre a full time discord mod + youre* + grammar issue + nerd + get clapped + kys + lorem ipsum dolor sit amet + go outside + bleach + lol + gay + retard + autistic + reported + ask deez + ez clap + straight cash + idgaf + ratio again + stay mad + read FAQ + youre lost + you “re” + stay pressed + reverse double take back + pedophile + cancelled + done for + don't give a damn + get a job + sus + baka + sussy baka + get blocked + mad free + freer than air + furry + rip bozo + you're a (insert stereotype) + slight_smile + aired + cringe again + Super Idol的笑容 + mad cuz bad + my pronouns are xe, xem & xyr + irrelevant + deal with it + screencapped your bio + karen/kyle + jealous + you're deaf + balls + i'll be right back + go ahead whine about it + not straight + eat paper + you lose + count to three + your problem + no one cares + log off + don't care even more + sex offender + sex defender + get religion + not okay + glhf + NFT owner + you make bad memes + problematic + fall in line + dog water + you look like a wall + you dont know 2 + 2 with yo head ass + you are going to my cringe compilation + you cant count to five + try again + you failed kindergarten + rickrolled + no lifer + guten freunden schickt man einen deutschen panzer + you have a anime profile picture + an* + fatherless + motherless + sisterless + brotherless + orphan + you can't catch this ratio + catch some bitches + I don't care about your opinion + genshin player + you dress like garbage + 日本語がお上手ですね + get fucked + you cant understand what the word intelligence means with your dumb ass + you have hair + queued + put some thought into what you're going to do with that + stfu + go to bed + yes, i'm taller than you + i think your joke is funny + i rejected your mother's advances + marooned + you cant read + I win + final ratio
state = &_states[history]; state = &_states[history];

View file

@ -1166,8 +1166,7 @@ void Reactions::send(not_null<HistoryItem*> item, bool addToRecent) {
_owner->session().api().applyUpdates(result); _owner->session().api().applyUpdates(result);
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadMessages && settings->markReadAfterReaction && item) if (!settings->sendReadMessages && settings->markReadAfterReaction && item) {
{
readHistory(item); readHistory(item);
} }
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {

View file

@ -159,8 +159,7 @@ public:
std::unique_ptr<Data::UploadState> uploadingData; std::unique_ptr<Data::UploadState> uploadingData;
int32 getDC() const int32 getDC() const {
{
return _dc; return _dc;
} }

View file

@ -334,8 +334,7 @@ Session::Session(not_null<Main::Session*> session)
// AyuGram disableStories // AyuGram disableStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->disableStories) if (!settings->disableStories) {
{
_stories->loadMore(Data::StorySourcesList::NotHidden); _stories->loadMore(Data::StorySourcesList::NotHidden);
} }
}); });
@ -2312,17 +2311,14 @@ void Session::updateEditedMessage(const MTPMessage &data) {
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
HistoryMessageEdition edit; HistoryMessageEdition edit;
if (data.type() != mtpc_message) if (data.type() != mtpc_message) {
{
goto proceed; goto proceed;
} }
edit = HistoryMessageEdition(_session, data.c_message()); edit = HistoryMessageEdition(_session, data.c_message());
if (settings->saveMessagesHistory && !existing->isLocal() && !existing->author()->isSelf() && !edit.isEditHide) if (settings->saveMessagesHistory && !existing->isLocal() && !existing->author()->isSelf() && !edit.isEditHide) {
{
const auto msg = existing->originalText(); const auto msg = existing->originalText();
if (edit.textWithEntities == msg || msg.empty()) if (edit.textWithEntities == msg || msg.empty()) {
{
goto proceed; goto proceed;
} }
@ -2475,8 +2471,7 @@ void Session::checkTTLs() {
while (!_ttlMessages.empty() && _ttlMessages.begin()->first <= now) { while (!_ttlMessages.empty() && _ttlMessages.begin()->first <= now) {
if (!settings->saveDeletedMessages) { if (!settings->saveDeletedMessages) {
_ttlMessages.begin()->second.front()->destroy(); _ttlMessages.begin()->second.front()->destroy();
} } else {
else {
_ttlMessages.begin()->second.front()->setAyuHint(settings->deletedMark); _ttlMessages.begin()->second.front()->setAyuHint(settings->deletedMark);
} }
} }
@ -2501,8 +2496,7 @@ void Session::processMessagesDeleted(
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->saveDeletedMessages) { if (!settings->saveDeletedMessages) {
i->second->destroy(); i->second->destroy();
} } else {
else {
i->second->setAyuHint(settings->deletedMark); i->second->setAyuHint(settings->deletedMark);
} }
@ -2527,8 +2521,7 @@ void Session::processNonChannelMessagesDeleted(const QVector<MTPint> &data) {
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->saveDeletedMessages) { if (!settings->saveDeletedMessages) {
item->destroy(); item->destroy();
} } else {
else {
item->setAyuHint(settings->deletedMark); item->setAyuHint(settings->deletedMark);
} }

View file

@ -1106,8 +1106,7 @@ void Stories::markAsRead(FullStoryId id, bool viewed) {
// AyuGram sendReadStories // AyuGram sendReadStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadStories) if (!settings->sendReadStories) {
{
_markReadRequests.clear(); _markReadRequests.clear();
_markReadPending.clear(); _markReadPending.clear();
@ -1265,8 +1264,7 @@ void Stories::sendMarkAsReadRequest(
// AyuGram sendReadStories // AyuGram sendReadStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadStories) if (!settings->sendReadStories) {
{
_markReadRequests.clear(); _markReadRequests.clear();
_markReadPending.clear(); _markReadPending.clear();
@ -1326,8 +1324,7 @@ void Stories::sendIncrementViewsRequests() {
// AyuGram sendReadStories // AyuGram sendReadStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (!settings->sendReadStories) if (!settings->sendReadStories) {
{
_incrementViewsPending.clear(); _incrementViewsPending.clear();
_incrementViewsRequests.clear(); _incrementViewsRequests.clear();
return; return;
@ -1847,8 +1844,7 @@ bool Stories::isQuitPrevent() {
// AyuGram sendReadStories // AyuGram sendReadStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->sendReadStories) if (settings->sendReadStories) {
{
sendMarkAsReadRequests(); sendMarkAsReadRequests();
} }
} }

View file

@ -366,16 +366,13 @@ bool UserData::isFake() const {
bool UserData::isPremium() const { bool UserData::isPremium() const {
if (id) { if (id) {
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
if (settings->localPremium) if (settings->localPremium) {
{ if (getSession(id.value)) {
if (getSession(id.value))
{
return true; return true;
} }
} }
} }
return flags() & UserDataFlag::Premium; return flags() & UserDataFlag::Premium;
} }

View file

@ -831,8 +831,7 @@ void Widget::setupMainMenuToggle() {
void Widget::setupStories() { void Widget::setupStories() {
// AyuGram disableStories // AyuGram disableStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->disableStories) if (settings->disableStories) {
{
return; return;
} }

View file

@ -384,20 +384,38 @@ HistoryItem::HistoryItem(
if (media) { if (media) {
setMedia(*media); setMedia(*media);
if (checked == MediaCheckResult::HasUnsupportedTimeToLive) { if (checked == MediaCheckResult::HasUnsupportedTimeToLive) {
media->match([&](const MTPDmessageMediaPhoto &media) { media->match(
auto time = media.vttl_seconds()->v; [&](const MTPDmessageMediaPhoto &media)
setAyuHint(formatTTL(time)); {
}, [&](const MTPDmessageMediaDocument &media) { auto time = media.vttl_seconds()->v;
auto time = media.vttl_seconds()->v; setAyuHint(formatTTL(time));
setAyuHint(formatTTL(time)); },
}, [&](const MTPDmessageMediaWebPage &media) { [&](const MTPDmessageMediaDocument &media)
}, [&](const MTPDmessageMediaGame &media) { {
}, [&](const MTPDmessageMediaInvoice &media) { auto time = media.vttl_seconds()->v;
}, [&](const MTPDmessageMediaPoll &media) { setAyuHint(formatTTL(time));
}, [&](const MTPDmessageMediaDice &media) { },
}, [&](const MTPDmessageMediaStory &media) { [&](const MTPDmessageMediaWebPage &media)
}, [&](const auto &) { {
}); },
[&](const MTPDmessageMediaGame &media)
{
},
[&](const MTPDmessageMediaInvoice &media)
{
},
[&](const MTPDmessageMediaPoll &media)
{
},
[&](const MTPDmessageMediaDice &media)
{
},
[&](const MTPDmessageMediaStory &media)
{
},
[&](const auto &)
{
});
} }
} }
auto textWithEntities = TextWithEntities{ auto textWithEntities = TextWithEntities{
@ -1212,8 +1230,9 @@ void HistoryItem::setServiceText(PreparedServiceText &&prepared) {
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
const auto timeString = QString(" (%1)").arg(QLocale().toString( const auto timeString = QString(" (%1)").arg(QLocale().toString(
base::unixtime::parse(_date), base::unixtime::parse(_date),
settings->showMessageSeconds ? QLocale::system().timeFormat(QLocale::LongFormat).remove(" t") settings->showMessageSeconds
: QLocale::system().timeFormat(QLocale::ShortFormat) ? QLocale::system().timeFormat(QLocale::LongFormat).remove(" t")
: QLocale::system().timeFormat(QLocale::ShortFormat)
)); ));
if (!text.text.isEmpty() && !text.text.contains(timeString)) { if (!text.text.isEmpty() && !text.text.contains(timeString)) {
text = text.append(timeString); text = text.append(timeString);
@ -2744,13 +2763,11 @@ void HistoryItem::setPostAuthor(const QString &postAuthor) {
msgsigned->postAuthor = postAuthor; msgsigned->postAuthor = postAuthor;
msgsigned->isAnonymousRank = !isDiscussionPost() msgsigned->isAnonymousRank = !isDiscussionPost()
&& this->author()->isMegagroup(); && this->author()->isMegagroup();
history()->owner().requestItemResize(this); history()->owner().requestItemResize(this);
} }
void HistoryItem::setAyuHint(const QString &hint) { void HistoryItem::setAyuHint(const QString &hint) {
try { try {
const auto settings = &AyuSettings::getInstance();
if (!(_flags & MessageFlag::HasPostAuthor)) { if (!(_flags & MessageFlag::HasPostAuthor)) {
_flags |= MessageFlag::HasPostAuthor; _flags |= MessageFlag::HasPostAuthor;
} }
@ -2769,15 +2786,13 @@ void HistoryItem::setAyuHint(const QString &hint) {
if (!msgsigned) { if (!msgsigned) {
AddComponents(HistoryMessageSigned::Bit()); AddComponents(HistoryMessageSigned::Bit());
msgsigned = Get<HistoryMessageSigned>(); msgsigned = Get<HistoryMessageSigned>();
} } else if (msgsigned->postAuthor == hint) {
else if (msgsigned->postAuthor == hint) {
return; return;
} }
msgsigned->postAuthor = hint; msgsigned->postAuthor = hint;
msgsigned->isAnonymousRank = !isDiscussionPost() msgsigned->isAnonymousRank = !isDiscussionPost()
&& this->author()->isMegagroup(); && this->author()->isMegagroup();
} } else {
else {
const auto data = Get<HistoryServiceData>(); const auto data = Get<HistoryServiceData>();
auto prepared = PreparedServiceText{ auto prepared = PreparedServiceText{
.text = _text.append(QString(" (%1)").arg(hint)), .text = _text.append(QString(" (%1)").arg(hint)),

View file

@ -4010,16 +4010,14 @@ Api::SendAction HistoryWidget::prepareSendAction(
void HistoryWidget::send(Api::SendOptions options) { void HistoryWidget::send(Api::SendOptions options) {
// AyuGram useScheduledMessages // AyuGram useScheduledMessages
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->useScheduledMessages && !options.scheduled) if (settings->useScheduledMessages && !options.scheduled) {
{
DEBUG_LOG(("[AyuGram] Scheduling message")); DEBUG_LOG(("[AyuGram] Scheduling message"));
auto current = base::unixtime::now(); auto current = base::unixtime::now();
options.scheduled = current + 12; options.scheduled = current + 12;
} }
auto lastMessage = _history->lastMessage(); auto lastMessage = _history->lastMessage();
if (!settings->sendReadMessages && settings->markReadAfterSend && lastMessage) if (!settings->sendReadMessages && settings->markReadAfterSend && lastMessage) {
{
readHistory(lastMessage); readHistory(lastMessage);
} }
@ -7818,7 +7816,8 @@ void HistoryWidget::messageShotSelected() {
} }
const auto messages = ranges::views::all(items) const auto messages = ranges::views::all(items)
| ranges::views::transform([this](const auto fullId) { | ranges::views::transform([this](const auto fullId)
{
return gsl::not_null(session().data().message(fullId)); return gsl::not_null(session().data().message(fullId));
}) })
| ranges::to_vector; | ranges::to_vector;

View file

@ -44,7 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
// AyuGram includes // AyuGram includes
#include "ayu/ayu_settings.h" #include "ayu/ayu_settings.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "window/window_controller.h"
namespace HistoryView::Controls { namespace HistoryView::Controls {
namespace { namespace {
@ -1805,16 +1805,18 @@ void VoiceRecordBar::stopRecording(StopType type, bool ttlBeforeHide) {
}; };
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
auto sendVoiceCallback = crl::guard(this, [=, this](Fn<void()> &&close) auto sendVoiceCallback = crl::guard(
{ this,
_sendVoiceRequests.fire({ [=, this](Fn<void()> &&close)
_data.bytes, {
_data.waveform, _sendVoiceRequests.fire({
Duration(_data.samples), _data.bytes,
options, _data.waveform,
Duration(_data.samples),
options,
});
close();
}); });
close();
});
if (settings->voiceConfirmation) { if (settings->voiceConfirmation) {
_show->showBox(Ui::MakeConfirmBox( _show->showBox(Ui::MakeConfirmBox(
@ -1823,9 +1825,10 @@ void VoiceRecordBar::stopRecording(StopType type, bool ttlBeforeHide) {
.confirmed = std::move(sendVoiceCallback), .confirmed = std::move(sendVoiceCallback),
.confirmText = tr::lng_send_button() .confirmText = tr::lng_send_button()
})); }));
} } else {
else { sendVoiceCallback([]
sendVoiceCallback([]{}); {
});
} }
})); }));
} }
@ -1890,16 +1893,18 @@ void VoiceRecordBar::requestToSendWithOptions(Api::SendOptions options) {
} }
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
auto sendVoiceCallback = crl::guard(this, [=, this](Fn<void()> &&close) auto sendVoiceCallback = crl::guard(
{ this,
_sendVoiceRequests.fire({ [=, this](Fn<void()> &&close)
_data.bytes, {
_data.waveform, _sendVoiceRequests.fire({
Duration(_data.samples), _data.bytes,
options, _data.waveform,
Duration(_data.samples),
options,
});
close();
}); });
close();
});
if (settings->voiceConfirmation) { if (settings->voiceConfirmation) {
_show->showBox(Ui::MakeConfirmBox( _show->showBox(Ui::MakeConfirmBox(
@ -1908,9 +1913,10 @@ void VoiceRecordBar::requestToSendWithOptions(Api::SendOptions options) {
.confirmed = std::move(sendVoiceCallback), .confirmed = std::move(sendVoiceCallback),
.confirmText = tr::lng_send_button() .confirmText = tr::lng_send_button()
})); }));
} } else {
else { sendVoiceCallback([]
sendVoiceCallback([]{}); {
});
} }
} }
} }

View file

@ -472,15 +472,16 @@ void BottomInfo::layoutDateText() {
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
const auto edited = (_data.flags & Data::Flag::Edited) const auto edited = (_data.flags & Data::Flag::Edited)
? (settings->editedMark + ' ') ? (settings->editedMark + ' ')
: QString(); : QString();
const auto author = _data.author; const auto author = _data.author;
const auto prefix = !author.isEmpty() ? (author == settings->deletedMark ? u" "_q : u", "_q) : QString(); const auto prefix = !author.isEmpty() ? (author == settings->deletedMark ? u" "_q : u", "_q) : QString();
const auto date = edited + QLocale().toString( const auto date = edited + QLocale().toString(
_data.date.time(), _data.date.time(),
settings->showMessageSeconds ? QLocale::system().timeFormat(QLocale::LongFormat).remove(" t") settings->showMessageSeconds
: QLocale::system().timeFormat(QLocale::ShortFormat) ? QLocale::system().timeFormat(QLocale::LongFormat).remove(" t")
); : QLocale::system().timeFormat(QLocale::ShortFormat)
);
const auto afterAuthor = prefix + date; const auto afterAuthor = prefix + date;
const auto afterAuthorWidth = st::msgDateFont->width(afterAuthor); const auto afterAuthorWidth = st::msgDateFont->width(afterAuthor);
const auto authorWidth = st::msgDateFont->width(author); const auto authorWidth = st::msgDateFont->width(author);

View file

@ -289,7 +289,7 @@ QString DateTooltipText(not_null<Element*> view) {
if (item->isScheduled() && item->isSilent()) { if (item->isScheduled() && item->isSilent()) {
dateText += '\n' + QChar(0xD83D) + QChar(0xDD15); dateText += '\n' + QChar(0xD83D) + QChar(0xDD15);
} }
if (!item->isLocal()) { // local messages have strange ID if (!item->isLocal()) {
dateText += '\n'; dateText += '\n';
dateText += "ID: "; dateText += "ID: ";
dateText += QString::number(item->id.bare); dateText += QString::number(item->id.bare);

View file

@ -745,15 +745,6 @@ void Selector::finishExpand() {
void Selector::paintBubble(QPainter &p, int innerWidth) { void Selector::paintBubble(QPainter &p, int innerWidth) {
// AyuGram: removed // AyuGram: removed
// const auto &bubble = _st.icons.stripBubble;
// const auto bubbleRight = std::min(
// st::reactStripBubbleRight,
// (innerWidth - bubble.width()) / 2);
// bubble.paint(
// p,
// _inner.x() + innerWidth - bubbleRight - bubble.width(),
// _inner.y() + _inner.height() - _outer.y(),
// width());
} }
void Selector::paintEvent(QPaintEvent *e) { void Selector::paintEvent(QPaintEvent *e) {

View file

@ -500,8 +500,7 @@ void TopBar::updateControlsVisibility(anim::type animated) {
void TopBar::setStories(rpl::producer<Dialogs::Stories::Content> content) { void TopBar::setStories(rpl::producer<Dialogs::Stories::Content> content) {
// AyuGram disableStories // AyuGram disableStories
const auto settings = &AyuSettings::getInstance(); const auto settings = &AyuSettings::getInstance();
if (settings->disableStories) if (settings->disableStories) {
{
return; return;
} }

View file

@ -119,21 +119,15 @@ base::options::toggle ShowPeerIdBelowAbout({
const QString &addToLink) { const QString &addToLink) {
return [=](QString link) { return [=](QString link) {
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
if (!settings->copyUsernameAsLink) if (!settings->copyUsernameAsLink) {
{
link = '@' + link.mid(13); link = '@' + link.mid(13);
} } else {
else if (!link.startsWith(u"https://"_q)) {
{
if (!link.startsWith(u"https://"_q))
{
link = peer->session().createInternalLinkFull(peer->userName()) link = peer->session().createInternalLinkFull(peer->userName())
+ addToLink; + addToLink;
} }
} }
if (!link.isEmpty()) {
if (!link.isEmpty())
{
QGuiApplication::clipboard()->setText(link); QGuiApplication::clipboard()->setText(link);
show->showToast(tr::lng_username_copied(tr::now)); show->showToast(tr::lng_username_copied(tr::now));
} }
@ -583,11 +577,10 @@ 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);
}); });
@ -597,11 +590,10 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
tr::ayu_ContextCopyID(tr::now) tr::ayu_ContextCopyID(tr::now)
); );
idInfo.text->setClickHandlerFilter([=](auto&&...) idInfo.text->setClickHandlerFilter([=](auto &&...)
{ {
const auto idText = IDString(user); const auto idText = IDString(user);
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);
@ -671,11 +663,10 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
addTranslateToMenu(about.text, AboutWithIdValue(_peer)); addTranslateToMenu(about.text, AboutWithIdValue(_peer));
} }
if (settings->showPeerId != 0 && !_topic) if (settings->showPeerId != 0 && !_topic) {
{
auto idDrawableText = IDValue( auto idDrawableText = IDValue(
_peer _peer
) | rpl::map([](TextWithEntities&& text) ) | rpl::map([](TextWithEntities &&text)
{ {
return Ui::Text::Code(text.text); return Ui::Text::Code(text.text);
}); });
@ -685,11 +676,10 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
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);
@ -698,12 +688,10 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
}); });
} }
if (settings->showPeerId != 0 && _topic) if (settings->showPeerId != 0 && _topic) {
{
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);
}); });
@ -713,11 +701,10 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
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);

View file

@ -310,15 +310,18 @@ Cover::Cover(
Window::GifPauseReason::Layer); Window::GifPauseReason::Layer);
})) }))
, _devBadge( , _devBadge(
std::make_unique<Badge>( std::make_unique<Badge>(
this, this,
st::infoPeerBadge, st::infoPeerBadge,
peer, peer,
_emojiStatusPanel.get(), _emojiStatusPanel.get(),
[=] { [=]
return controller->isGifPausedAtLeastFor( {
Window::GifPauseReason::Layer); return controller->isGifPausedAtLeastFor(
}, 0, BadgeType::None | BadgeType::AyuGram | BadgeType::Extera)) Window::GifPauseReason::Layer);
},
0,
BadgeType::None | BadgeType::AyuGram | BadgeType::Extera))
, _userpic(topic , _userpic(topic
? nullptr ? nullptr
: object_ptr<Ui::UserpicButton>( : object_ptr<Ui::UserpicButton>(
@ -366,17 +369,18 @@ Cover::Cover(
if (isAyuGramRelated(getBareID(_peer))) { if (isAyuGramRelated(getBareID(_peer))) {
_devBadge->setContent(Info::Profile::Badge::Content{BadgeType::AyuGram}); _devBadge->setContent(Info::Profile::Badge::Content{BadgeType::AyuGram});
} } else if (isExteraRelated(getBareID(_peer))) {
else if (isExteraRelated(getBareID(_peer))) {
_devBadge->setContent(Info::Profile::Badge::Content{BadgeType::Extera}); _devBadge->setContent(Info::Profile::Badge::Content{BadgeType::Extera});
} } else {
else {
_devBadge->setContent(Info::Profile::Badge::Content{BadgeType::None}); _devBadge->setContent(Info::Profile::Badge::Content{BadgeType::None});
} }
_devBadge->updated() | rpl::start_with_next([=] { _devBadge->updated() | rpl::start_with_next(
refreshNameGeometry(width()); [=]
}, _name->lifetime()); {
refreshNameGeometry(width());
},
_name->lifetime());
initViewers(std::move(title)); initViewers(std::move(title));
setupChildGeometry(); setupChildGeometry();

View file

@ -30,8 +30,8 @@ public:
std::unique_ptr<Account> account; std::unique_ptr<Account> account;
}; };
static constexpr auto kMaxAccounts = 666; static constexpr auto kMaxAccounts = 100;
static constexpr auto kPremiumMaxAccounts = 1338; static constexpr auto kPremiumMaxAccounts = 200;
explicit Domain(const QString &dataName); explicit Domain(const QString &dataName);
~Domain(); ~Domain();

View file

@ -1038,9 +1038,6 @@ bool OverlayWidget::hasCopyMediaRestriction(bool skipPremiumCheck) const {
if (const auto story = _stories ? _stories->story() : nullptr) { if (const auto story = _stories ? _stories->story() : nullptr) {
// AyuGram: removed; allow downloading any stories // AyuGram: removed; allow downloading any stories
return false; return false;
// return skipPremiumCheck
// ? !story->canDownloadIfPremium()
// : !story->canDownloadChecked();
} }
return (_history && !_history->peer->allowsForwarding()) return (_history && !_history->peer->allowsForwarding())
|| (_message && _message->forbidsSaving()); || (_message && _message->forbidsSaving());
@ -1072,6 +1069,7 @@ QSize OverlayWidget::videoSize() const {
bool OverlayWidget::streamingRequiresControls() const { bool OverlayWidget::streamingRequiresControls() const {
return !_stories return !_stories
&& _document; && _document;
// AyuGram: allow vieo messages seeking
// && (!_document->isAnimation() || _document->isVideoMessage()); // && (!_document->isAnimation() || _document->isVideoMessage());
} }
@ -3286,8 +3284,7 @@ void OverlayWidget::activate() {
QApplication::setActiveWindow(_window); QApplication::setActiveWindow(_window);
setFocus(); setFocus();
if (AyuFeatures::StreamerMode::isEnabled()) if (AyuFeatures::StreamerMode::isEnabled()) {
{
AyuFeatures::StreamerMode::hideWidgetWindow(_window); AyuFeatures::StreamerMode::hideWidgetWindow(_window);
} else { } else {
AyuFeatures::StreamerMode::showWidgetWindow(_window); AyuFeatures::StreamerMode::showWidgetWindow(_window);

View file

@ -961,8 +961,7 @@ void Pip::setupPanel() {
_panel.setPosition(Deserialize(_delegate->pipLoadGeometry())); _panel.setPosition(Deserialize(_delegate->pipLoadGeometry()));
_panel.widget()->show(); _panel.widget()->show();
if (AyuFeatures::StreamerMode::isEnabled()) if (AyuFeatures::StreamerMode::isEnabled()) {
{
AyuFeatures::StreamerMode::hideWidgetWindow(_panel.widget()); AyuFeatures::StreamerMode::hideWidgetWindow(_panel.widget());
} else { } else {
AyuFeatures::StreamerMode::showWidgetWindow(_panel.widget()); AyuFeatures::StreamerMode::showWidgetWindow(_panel.widget());

View file

@ -131,6 +131,7 @@ bool DarkTasbarValueValid/* = false*/;
static auto ScaledLogoNoMargin = base::flat_map<int, QImage>(); static auto ScaledLogoNoMargin = base::flat_map<int, QImage>();
static auto ScaledLogoDark = base::flat_map<int, QImage>(); static auto ScaledLogoDark = base::flat_map<int, QImage>();
static auto ScaledLogoLight = base::flat_map<int, QImage>(); static auto ScaledLogoLight = base::flat_map<int, QImage>();
static auto lastUsedIcon = AyuAssets::currentAppLogoName(); static auto lastUsedIcon = AyuAssets::currentAppLogoName();
if (lastUsedIcon != AyuAssets::currentAppLogoName()) { if (lastUsedIcon != AyuAssets::currentAppLogoName()) {

View file

@ -1414,20 +1414,20 @@ void SetupDefaultThemes(
} }
}; };
group->setChangedCallback([=](Type type) { group->setChangedCallback([=](Type type) {
if (AyuFeatures::MessageShot::isChoosingTheme()) { if (AyuFeatures::MessageShot::isChoosingTheme()) {
palette->show(type); palette->show(type);
refreshColorizer(type); refreshColorizer(type);
group->setValue(type); group->setValue(type);
AyuFeatures::MessageShot::setDefaultSelected(type); AyuFeatures::MessageShot::setDefaultSelected(type);
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type); const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
if (scheme == end(kSchemesList)) { if (scheme == end(kSchemesList)) {
return; return;
} }
updateMessageShotPalette(scheme->path); updateMessageShotPalette(scheme->path);
return; return;
} }
group->setValue(chosen()); group->setValue(chosen());
}); });
@ -1480,23 +1480,28 @@ void SetupDefaultThemes(
}, block->lifetime()); }, block->lifetime());
if (AyuFeatures::MessageShot::isChoosingTheme()) { if (AyuFeatures::MessageShot::isChoosingTheme()) {
palette->selected() | rpl::start_with_next([=](QColor color) { palette->selected() | rpl::start_with_next(
AyuFeatures::MessageShot::setDefaultSelectedColor(color); [=](QColor color)
refreshColorizer(AyuFeatures::MessageShot::getSelectedFromDefault()); {
AyuFeatures::MessageShot::setDefaultSelectedColor(color);
refreshColorizer(AyuFeatures::MessageShot::getSelectedFromDefault());
const auto type = chosen(); const auto type = chosen();
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type); const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
if (scheme == end(kSchemesList)) { if (scheme == end(kSchemesList)) {
return; return;
} }
updateMessageShotPalette(scheme->path); updateMessageShotPalette(scheme->path);
}, container->lifetime()); },
container->lifetime());
AyuFeatures::MessageShot::resetDefaultSelectedEvents() | rpl::start_with_next([=] { AyuFeatures::MessageShot::resetDefaultSelectedEvents() | rpl::start_with_next([=]
refreshColorizer(AyuFeatures::MessageShot::getSelectedFromDefault()); // hide colorizer {
group->setValue(Type(-1)); refreshColorizer(AyuFeatures::MessageShot::getSelectedFromDefault()); // hide colorizer
}, container->lifetime()); group->setValue(Type(-1));
},
container->lifetime());
} }
palette->selected( palette->selected(

View file

@ -350,9 +350,6 @@ void NotificationsCount::paintEvent(QPaintEvent *e) {
} }
// support for top center notifications // support for top center notifications
auto screenCorner = static_cast<ScreenCorner>(4);
auto isLeft = Core::Settings::IsLeftCorner(screenCorner);
auto isTop = true;
auto sampleLeft = screenRect.x() + screenRect.width() / 2 - st::notificationSampleSize.width() / 2; auto sampleLeft = screenRect.x() + screenRect.width() / 2 - st::notificationSampleSize.width() / 2;
auto sampleTop = screenRect.y() + st::notificationsSampleTopSkip; auto sampleTop = screenRect.y() + st::notificationsSampleTopSkip;
if (static_cast<int>(_chosenCorner) == 4) { if (static_cast<int>(_chosenCorner) == 4) {
@ -361,7 +358,7 @@ void NotificationsCount::paintEvent(QPaintEvent *e) {
auto opacity = _sampleOpacities[i].value((i < count) ? 1. : 0.); auto opacity = _sampleOpacities[i].value((i < count) ? 1. : 0.);
p.setOpacity(opacity); p.setOpacity(opacity);
p.drawPixmapLeft(sampleLeft, sampleTop, width(), _notificationSampleSmall); p.drawPixmapLeft(sampleLeft, sampleTop, width(), _notificationSampleSmall);
sampleTop += (isTop ? 1 : -1) * (st::notificationSampleSize.height() + st::notificationsSampleMargin); sampleTop += st::notificationSampleSize.height() + st::notificationsSampleMargin;
} }
p.setOpacity(1.); p.setOpacity(1.);
} else { } else {
@ -530,7 +527,7 @@ void NotificationsCount::mouseMoveEvent(QMouseEvent *e) {
setOverCorner(ScreenCorner::BottomLeft); setOverCorner(ScreenCorner::BottomLeft);
} else if (topCenter.contains(e->pos())) { } else if (topCenter.contains(e->pos())) {
setOverCorner(ScreenCorner::TopCenter); setOverCorner(ScreenCorner::TopCenter);
} else{ } else {
clearOverCorner(); clearOverCorner();
} }
} }

View file

@ -999,8 +999,7 @@ QPointer<Ui::RpWidget> Premium::createPinnedToTop(
} }
auto settings = &AyuSettings::getInstance(); auto settings = &AyuSettings::getInstance();
if (settings->localPremium) if (settings->localPremium) {
{
return tr::ayu_LocalPremiumNotice(Ui::Text::RichLangValue); return tr::ayu_LocalPremiumNotice(Ui::Text::RichLangValue);
} }

Some files were not shown because too many files have changed in this diff Show more