mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-11 11:47:09 +02:00
chore: reformat & refactor & remove as not planned for now
This commit is contained in:
parent
4a6ae07409
commit
adb5abf4fb
105 changed files with 2169 additions and 5531 deletions
57
.clang-format
Normal file
57
.clang-format
Normal 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
|
||||||
|
...
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace AyuInfra
|
namespace AyuInfra {
|
||||||
{
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
|
|
||||||
}
|
|
|
@ -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)
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 ¶ms)
|
QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) {
|
||||||
{
|
|
||||||
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 ¶ms)
|
const Window::SectionShow ¶ms) {
|
||||||
{
|
|
||||||
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 ¶ms)
|
const Window::SectionSlideParams ¶ms) {
|
||||||
{
|
|
||||||
_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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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...
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
// don’t care + didn’t 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 didn’t 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 + your’re a full time discord mod + you’re* + 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 don’t know 2 + 2 with yo head ass + you are going to my cringe compilation + you can’t 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 can’t 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 can’t read + I win + final ratio
|
// don’t care + didn’t 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 didn’t 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 + your’re a full time discord mod + you’re* + 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 don’t know 2 + 2 with yo head ass + you are going to my cringe compilation + you can’t 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 can’t 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 can’t read + I win + final ratio
|
||||||
state = &_states[history];
|
state = &_states[history];
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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([]{});
|
{
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue