mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
feat: new message history viewer initial
fix: use Qt formatting kanged from `admin_log` and cleaned up a bit
This commit is contained in:
parent
ba93a50062
commit
e1babcf69a
56 changed files with 6953 additions and 2561 deletions
|
@ -102,6 +102,8 @@ PRIVATE
|
||||||
ayu/ayu_lang.cpp
|
ayu/ayu_lang.cpp
|
||||||
ayu/ayu_lang.h
|
ayu/ayu_lang.h
|
||||||
ayu/ayu_constants.h
|
ayu/ayu_constants.h
|
||||||
|
ayu/utils/ayu_mapper.cpp
|
||||||
|
ayu/utils/ayu_mapper.h
|
||||||
ayu/utils/telegram_helpers.cpp
|
ayu/utils/telegram_helpers.cpp
|
||||||
ayu/utils/telegram_helpers.h
|
ayu/utils/telegram_helpers.h
|
||||||
ayu/utils/windows_utils.cpp
|
ayu/utils/windows_utils.cpp
|
||||||
|
@ -118,6 +120,12 @@ PRIVATE
|
||||||
ayu/ui/settings/settings_ayu.h
|
ayu/ui/settings/settings_ayu.h
|
||||||
ayu/ui/context_menu/context_menu.cpp
|
ayu/ui/context_menu/context_menu.cpp
|
||||||
ayu/ui/context_menu/context_menu.h
|
ayu/ui/context_menu/context_menu.h
|
||||||
|
ayu/ui/sections/edited/edited_log_inner.cpp
|
||||||
|
ayu/ui/sections/edited/edited_log_inner.h
|
||||||
|
ayu/ui/sections/edited/edited_log_item.cpp
|
||||||
|
ayu/ui/sections/edited/edited_log_item.h
|
||||||
|
ayu/ui/sections/edited/edited_log_section.cpp
|
||||||
|
ayu/ui/sections/edited/edited_log_section.h
|
||||||
ayu/ui/boxes/voice_confirmation_box.cpp
|
ayu/ui/boxes/voice_confirmation_box.cpp
|
||||||
ayu/ui/boxes/voice_confirmation_box.h
|
ayu/ui/boxes/voice_confirmation_box.h
|
||||||
ayu/ui/boxes/message_history_box.cpp
|
ayu/ui/boxes/message_history_box.cpp
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// https://github.com/AyuGram/AyuGram4A/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;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "core/core_settings.h"
|
#include "core/core_settings.h"
|
||||||
#include "lang/lang_instance.h"
|
#include "lang/lang_instance.h"
|
||||||
|
|
||||||
CustomLangPack* CustomLangPack::instance = nullptr;
|
CustomLangPack *CustomLangPack::instance = nullptr;
|
||||||
|
|
||||||
CustomLangPack::CustomLangPack() = default;
|
CustomLangPack::CustomLangPack() = default;
|
||||||
|
|
||||||
|
@ -22,39 +22,35 @@ void CustomLangPack::initInstance()
|
||||||
instance = new CustomLangPack;
|
instance = new CustomLangPack;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomLangPack* CustomLangPack::currentInstance()
|
CustomLangPack *CustomLangPack::currentInstance()
|
||||||
{
|
{
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomLangPack::fetchCustomLangPack(const QString& langPackId, const QString& langPackBaseId)
|
void CustomLangPack::fetchCustomLangPack(const QString &langPackId, const QString &langPackBaseId)
|
||||||
{
|
{
|
||||||
LOG(("Current Language pack ID: %1, Base ID: %2").arg(langPackId, langPackBaseId));
|
LOG(("Current Language pack ID: %1, Base ID: %2").arg(langPackId, langPackBaseId));
|
||||||
|
|
||||||
auto finalLangPackId = langPackId;
|
auto finalLangPackId = langPackId;
|
||||||
if (finalLangPackId == qsl("pt-br"))
|
if (finalLangPackId == qsl("pt-br")) {
|
||||||
{
|
|
||||||
// meh
|
// meh
|
||||||
finalLangPackId = qsl("pt");
|
finalLangPackId = qsl("pt");
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url;
|
QUrl url;
|
||||||
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
|
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
|
||||||
{
|
|
||||||
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
|
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
|
||||||
finalLangPackId));
|
finalLangPackId));
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
|
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
|
||||||
needFallback ? langPackBaseId : finalLangPackId));
|
needFallback ? langPackBaseId : finalLangPackId));
|
||||||
}
|
}
|
||||||
|
@ -73,24 +69,20 @@ void CustomLangPack::fetchFinished()
|
||||||
QString langPackId = Lang::GetInstance().id();
|
QString langPackId = Lang::GetInstance().id();
|
||||||
auto statusCode = _chkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
auto statusCode = _chkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
if (statusCode == 404 && !langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
|
if (statusCode == 404 && !langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
|
||||||
{
|
|
||||||
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
|
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
@ -103,20 +95,17 @@ void CustomLangPack::fetchError(QNetworkReply::NetworkError e)
|
||||||
{
|
{
|
||||||
LOG(("Network error: %1").arg(e));
|
LOG(("Network error: %1").arg(e));
|
||||||
|
|
||||||
if (e == QNetworkReply::NetworkError::ContentNotFoundError)
|
if (e == QNetworkReply::NetworkError::ContentNotFoundError) {
|
||||||
{
|
|
||||||
QString langPackBaseId = Lang::GetInstance().baseId();
|
QString langPackBaseId = Lang::GetInstance().baseId();
|
||||||
QString langPackId = Lang::GetInstance().id();
|
QString langPackId = Lang::GetInstance().id();
|
||||||
|
|
||||||
if (!langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
|
if (!langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
|
||||||
{
|
|
||||||
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
|
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
|
||||||
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;
|
||||||
|
@ -127,12 +116,10 @@ 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());
|
||||||
QJsonObject json = str.object();
|
QJsonObject json = str.object();
|
||||||
for (const QString& key : json.keys())
|
for (const QString &key : json.keys()) {
|
||||||
{
|
|
||||||
Lang::GetInstance().applyValue(key.toUtf8(), json.value(key).toString().toUtf8());
|
Lang::GetInstance().applyValue(key.toUtf8(), json.value(key).toString().toUtf8());
|
||||||
}
|
}
|
||||||
Lang::GetInstance().updatePluralRules();
|
Lang::GetInstance().updatePluralRules();
|
||||||
|
@ -143,15 +130,13 @@ 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;
|
||||||
auto val = json.value(brokenKey).toString().replace(qsl("&"), qsl("&")).toUtf8();
|
auto val = json.value(brokenKey).toString().replace(qsl("&"), qsl("&")).toUtf8();
|
||||||
|
|
||||||
Lang::GetInstance().resetValue(key.toUtf8());
|
Lang::GetInstance().resetValue(key.toUtf8());
|
||||||
Lang::GetInstance().applyValue(key.toUtf8(), val);
|
Lang::GetInstance().applyValue(key.toUtf8(), val);
|
||||||
if (key.contains("#other"))
|
if (key.contains("#other")) {
|
||||||
{
|
|
||||||
Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few"));
|
Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few"));
|
||||||
Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few"));
|
Lang::GetInstance().resetValue(key.toUtf8().replace("#other", "#few"));
|
||||||
Lang::GetInstance().applyValue(key.toUtf8().replace("#other", "#few"), val);
|
Lang::GetInstance().applyValue(key.toUtf8().replace("#other", "#few"), val);
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
@ -12,18 +11,18 @@
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
|
@ -40,6 +39,6 @@ private:
|
||||||
~CustomLangPack() override = default;
|
~CustomLangPack() override = default;
|
||||||
|
|
||||||
QNetworkAccessManager networkManager;
|
QNetworkAccessManager networkManager;
|
||||||
QNetworkReply* _chkReply = nullptr;
|
QNetworkReply *_chkReply = nullptr;
|
||||||
bool needFallback = false;
|
bool needFallback = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,301 +14,315 @@ using json = nlohmann::json;
|
||||||
|
|
||||||
namespace AyuSettings
|
namespace AyuSettings
|
||||||
{
|
{
|
||||||
const QString filename = "tdata/ayu_settings.json";
|
|
||||||
std::optional<AyuGramSettings> settings = std::nullopt;
|
|
||||||
|
|
||||||
rpl::variable<bool> sendReadMessagesReactive;
|
const QString filename = "tdata/ayu_settings.json";
|
||||||
rpl::variable<bool> sendReadStoriesReactive;
|
|
||||||
rpl::variable<bool> sendOnlinePacketsReactive;
|
|
||||||
rpl::variable<bool> sendUploadProgressReactive;
|
|
||||||
rpl::variable<bool> sendOfflinePacketAfterOnlineReactive;
|
|
||||||
|
|
||||||
rpl::variable<QString> deletedMarkReactive;
|
std::optional<AyuGramSettings> settings = std::nullopt;
|
||||||
rpl::variable<QString> editedMarkReactive;
|
|
||||||
rpl::variable<int> showPeerIdReactive;
|
|
||||||
|
|
||||||
rpl::variable<bool> ghostModeEnabled;
|
rpl::variable<bool> sendReadMessagesReactive;
|
||||||
|
|
||||||
rpl::lifetime lifetime = rpl::lifetime();
|
rpl::variable<bool> sendReadStoriesReactive;
|
||||||
|
|
||||||
bool ghostModeEnabled_util(AyuGramSettings& settingsUtil)
|
rpl::variable<bool> sendOnlinePacketsReactive;
|
||||||
{
|
|
||||||
return
|
rpl::variable<bool> sendUploadProgressReactive;
|
||||||
!settingsUtil.sendReadMessages
|
|
||||||
|
rpl::variable<bool> sendOfflinePacketAfterOnlineReactive;
|
||||||
|
|
||||||
|
rpl::variable<QString> deletedMarkReactive;
|
||||||
|
|
||||||
|
rpl::variable<QString> editedMarkReactive;
|
||||||
|
|
||||||
|
rpl::variable<int> showPeerIdReactive;
|
||||||
|
|
||||||
|
rpl::variable<bool> ghostModeEnabled;
|
||||||
|
|
||||||
|
rpl::lifetime lifetime = rpl::lifetime();
|
||||||
|
|
||||||
|
bool ghostModeEnabled_util(AyuGramSettings &settingsUtil)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
!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;
|
}
|
||||||
}
|
|
||||||
|
settings = AyuGramSettings();
|
||||||
settings = AyuGramSettings();
|
|
||||||
|
sendReadMessagesReactive.value() | rpl::filter([=](bool val)
|
||||||
sendReadMessagesReactive.value() | rpl::filter([=](bool val)
|
{
|
||||||
{
|
return (val != settings->sendReadMessages);
|
||||||
return (val != settings->sendReadMessages);
|
}) | start_with_next([=](bool val)
|
||||||
}) | start_with_next([=](bool val)
|
{
|
||||||
{
|
ghostModeEnabled =
|
||||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
ghostModeEnabled_util(settings.value());
|
||||||
}, lifetime);
|
}, lifetime);
|
||||||
// ..
|
// ..
|
||||||
sendReadStoriesReactive.value() | rpl::filter([=](bool val)
|
sendReadStoriesReactive.value() | rpl::filter([=](bool val)
|
||||||
{
|
{
|
||||||
return (val != settings->sendReadStories);
|
return (val != settings->sendReadStories);
|
||||||
}) | start_with_next([=](bool val)
|
}) | start_with_next([=](bool val)
|
||||||
{
|
{
|
||||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
ghostModeEnabled =
|
||||||
}, lifetime);
|
ghostModeEnabled_util(settings.value());
|
||||||
// ..
|
}, lifetime);
|
||||||
sendOnlinePacketsReactive.value() | rpl::filter([=](bool val)
|
// ..
|
||||||
{
|
sendOnlinePacketsReactive.value() | rpl::filter([=](bool val)
|
||||||
return (val != settings->sendOnlinePackets);
|
{
|
||||||
}) | start_with_next([=](bool val)
|
return (val != settings->sendOnlinePackets);
|
||||||
{
|
}) | start_with_next([=](bool val)
|
||||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
{
|
||||||
}, lifetime);
|
ghostModeEnabled =
|
||||||
// ..
|
ghostModeEnabled_util(settings
|
||||||
sendUploadProgressReactive.value() | rpl::filter([=](bool val)
|
.value());
|
||||||
{
|
}, lifetime);
|
||||||
return (val != settings->sendUploadProgress);
|
// ..
|
||||||
}) | start_with_next([=](bool val)
|
sendUploadProgressReactive.value() | rpl::filter([=](bool val)
|
||||||
{
|
{
|
||||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
return (val != settings->sendUploadProgress);
|
||||||
}, lifetime);
|
}) | start_with_next([=](bool val)
|
||||||
// ..
|
{
|
||||||
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val)
|
ghostModeEnabled =
|
||||||
{
|
ghostModeEnabled_util(settings
|
||||||
return (val != settings->sendOfflinePacketAfterOnline);
|
.value());
|
||||||
}) | start_with_next([=](bool val)
|
}, lifetime);
|
||||||
{
|
// ..
|
||||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val)
|
||||||
}, lifetime);
|
{
|
||||||
}
|
return (val
|
||||||
|
!= settings->sendOfflinePacketAfterOnline);
|
||||||
void postinitialize()
|
}) | start_with_next([=](bool val)
|
||||||
{
|
{
|
||||||
sendReadMessagesReactive = settings->sendReadMessages;
|
ghostModeEnabled =
|
||||||
sendReadStoriesReactive = settings->sendReadStories;
|
ghostModeEnabled_util(
|
||||||
sendUploadProgressReactive = settings->sendUploadProgress;
|
settings.value());
|
||||||
sendOfflinePacketAfterOnlineReactive = settings->sendOfflinePacketAfterOnline;
|
}, lifetime);
|
||||||
sendOnlinePacketsReactive = settings->sendOnlinePackets;
|
}
|
||||||
|
|
||||||
deletedMarkReactive = settings->deletedMark;
|
void postinitialize()
|
||||||
editedMarkReactive = settings->editedMark;
|
{
|
||||||
showPeerIdReactive = settings->showPeerId;
|
sendReadMessagesReactive = settings->sendReadMessages;
|
||||||
|
sendReadStoriesReactive = settings->sendReadStories;
|
||||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
sendUploadProgressReactive = settings->sendUploadProgress;
|
||||||
}
|
sendOfflinePacketAfterOnlineReactive = settings->sendOfflinePacketAfterOnline;
|
||||||
|
sendOnlinePacketsReactive = settings->sendOnlinePackets;
|
||||||
AyuGramSettings& getInstance()
|
|
||||||
{
|
deletedMarkReactive = settings->deletedMark;
|
||||||
initialize();
|
editedMarkReactive = settings->editedMark;
|
||||||
return settings.value();
|
showPeerIdReactive = settings->showPeerId;
|
||||||
}
|
|
||||||
|
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||||
void load()
|
}
|
||||||
{
|
|
||||||
QFile file(filename);
|
AyuGramSettings &getInstance()
|
||||||
if (!file.exists())
|
{
|
||||||
{
|
initialize();
|
||||||
return;
|
return settings.value();
|
||||||
}
|
}
|
||||||
file.open(QIODevice::ReadOnly);
|
|
||||||
QByteArray data = file.readAll();
|
void load()
|
||||||
file.close();
|
{
|
||||||
|
QFile file(filename);
|
||||||
initialize();
|
if (!file.exists()) {
|
||||||
json p = json::parse(data);
|
return;
|
||||||
try
|
}
|
||||||
{
|
file.open(QIODevice::ReadOnly);
|
||||||
settings = p.get<AyuGramSettings>();
|
QByteArray data = file.readAll();
|
||||||
}
|
file.close();
|
||||||
catch (...)
|
|
||||||
{
|
initialize();
|
||||||
LOG(("AyuGramSettings: failed to parse settings file"));
|
json p = json::parse(data);
|
||||||
}
|
try {
|
||||||
postinitialize();
|
settings = p.get<AyuGramSettings>();
|
||||||
}
|
}
|
||||||
|
catch (...) {
|
||||||
void save()
|
LOG(("AyuGramSettings: failed to parse settings file"));
|
||||||
{
|
}
|
||||||
initialize();
|
postinitialize();
|
||||||
|
}
|
||||||
json p = settings.value();
|
|
||||||
|
void save()
|
||||||
QFile file(filename);
|
{
|
||||||
file.open(QIODevice::WriteOnly);
|
initialize();
|
||||||
file.write(p.dump().c_str());
|
|
||||||
file.close();
|
json p = settings.value();
|
||||||
|
|
||||||
postinitialize();
|
QFile file(filename);
|
||||||
}
|
file.open(QIODevice::WriteOnly);
|
||||||
|
file.write(p.dump().c_str());
|
||||||
void AyuGramSettings::set_sendReadMessages(bool val)
|
file.close();
|
||||||
{
|
|
||||||
sendReadMessages = val;
|
postinitialize();
|
||||||
sendReadMessagesReactive = val;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_sendReadMessages(bool val)
|
||||||
void AyuGramSettings::set_sendReadStories(bool val)
|
{
|
||||||
{
|
sendReadMessages = val;
|
||||||
sendReadStories = val;
|
sendReadMessagesReactive = val;
|
||||||
sendReadStoriesReactive = val;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_sendReadStories(bool val)
|
||||||
void AyuGramSettings::set_sendOnlinePackets(bool val)
|
{
|
||||||
{
|
sendReadStories = val;
|
||||||
sendOnlinePackets = val;
|
sendReadStoriesReactive = val;
|
||||||
sendOnlinePacketsReactive = val;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_sendOnlinePackets(bool val)
|
||||||
void AyuGramSettings::set_sendUploadProgress(bool val)
|
{
|
||||||
{
|
sendOnlinePackets = val;
|
||||||
sendUploadProgress = val;
|
sendOnlinePacketsReactive = val;
|
||||||
sendUploadProgressReactive = val;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_sendUploadProgress(bool val)
|
||||||
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val)
|
{
|
||||||
{
|
sendUploadProgress = val;
|
||||||
sendOfflinePacketAfterOnline = val;
|
sendUploadProgressReactive = val;
|
||||||
sendOfflinePacketAfterOnlineReactive = val;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val)
|
||||||
void AyuGramSettings::set_ghostModeEnabled(bool val)
|
{
|
||||||
{
|
sendOfflinePacketAfterOnline = val;
|
||||||
set_sendReadMessages(!val);
|
sendOfflinePacketAfterOnlineReactive = val;
|
||||||
set_sendReadStories(!val);
|
}
|
||||||
set_sendOnlinePackets(!val);
|
|
||||||
set_sendUploadProgress(!val);
|
void AyuGramSettings::set_ghostModeEnabled(bool val)
|
||||||
set_sendOfflinePacketAfterOnline(val);
|
{
|
||||||
}
|
set_sendReadMessages(!val);
|
||||||
|
set_sendReadStories(!val);
|
||||||
void AyuGramSettings::set_markReadAfterSend(bool val)
|
set_sendOnlinePackets(!val);
|
||||||
{
|
set_sendUploadProgress(!val);
|
||||||
markReadAfterSend = val;
|
set_sendOfflinePacketAfterOnline(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_useScheduledMessages(bool val)
|
void AyuGramSettings::set_markReadAfterSend(bool val)
|
||||||
{
|
{
|
||||||
useScheduledMessages = val;
|
markReadAfterSend = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_keepDeletedMessages(bool val)
|
void AyuGramSettings::set_useScheduledMessages(bool val)
|
||||||
{
|
{
|
||||||
saveDeletedMessages = val;
|
useScheduledMessages = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_keepMessagesHistory(bool val)
|
void AyuGramSettings::set_keepDeletedMessages(bool val)
|
||||||
{
|
{
|
||||||
saveMessagesHistory = val;
|
saveDeletedMessages = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_disableAds(bool val)
|
void AyuGramSettings::set_keepMessagesHistory(bool val)
|
||||||
{
|
{
|
||||||
disableAds = val;
|
saveMessagesHistory = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_disableStories(bool val)
|
void AyuGramSettings::set_disableAds(bool val)
|
||||||
{
|
{
|
||||||
disableStories = val;
|
disableAds = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_localPremium(bool val)
|
void AyuGramSettings::set_disableStories(bool val)
|
||||||
{
|
{
|
||||||
localPremium = val;
|
disableStories = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_copyUsernameAsLink(bool val)
|
void AyuGramSettings::set_localPremium(bool val)
|
||||||
{
|
{
|
||||||
copyUsernameAsLink = val;
|
localPremium = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_appIcon(QString val)
|
void AyuGramSettings::set_copyUsernameAsLink(bool val)
|
||||||
{
|
{
|
||||||
appIcon = std::move(val);
|
copyUsernameAsLink = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_deletedMark(QString val)
|
void AyuGramSettings::set_appIcon(QString val)
|
||||||
{
|
{
|
||||||
deletedMark = std::move(val);
|
appIcon = std::move(val);
|
||||||
deletedMarkReactive = deletedMark;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_deletedMark(QString val)
|
||||||
void AyuGramSettings::set_editedMark(QString val)
|
{
|
||||||
{
|
deletedMark = std::move(val);
|
||||||
editedMark = std::move(val);
|
deletedMarkReactive = deletedMark;
|
||||||
editedMarkReactive = editedMark;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_editedMark(QString val)
|
||||||
void AyuGramSettings::set_recentStickersCount(int val)
|
{
|
||||||
{
|
editedMark = std::move(val);
|
||||||
recentStickersCount = val;
|
editedMarkReactive = editedMark;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_showGhostToggleInDrawer(bool val)
|
void AyuGramSettings::set_recentStickersCount(int val)
|
||||||
{
|
{
|
||||||
showGhostToggleInDrawer = val;
|
recentStickersCount = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_showPeerId(int val)
|
void AyuGramSettings::set_showGhostToggleInDrawer(bool val)
|
||||||
{
|
{
|
||||||
showPeerId = val;
|
showGhostToggleInDrawer = val;
|
||||||
showPeerIdReactive = val;
|
}
|
||||||
}
|
|
||||||
|
void AyuGramSettings::set_showPeerId(int val)
|
||||||
void AyuGramSettings::set_showMessageSeconds(bool val)
|
{
|
||||||
{
|
showPeerId = val;
|
||||||
showMessageSeconds = val;
|
showPeerIdReactive = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_hideAllChatsFolder(bool val)
|
void AyuGramSettings::set_showMessageSeconds(bool val)
|
||||||
{
|
{
|
||||||
hideAllChatsFolder = val;
|
showMessageSeconds = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_stickerConfirmation(bool val)
|
void AyuGramSettings::set_hideAllChatsFolder(bool val)
|
||||||
{
|
{
|
||||||
stickerConfirmation = val;
|
hideAllChatsFolder = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_gifConfirmation(bool val)
|
void AyuGramSettings::set_stickerConfirmation(bool val)
|
||||||
{
|
{
|
||||||
gifConfirmation = val;
|
stickerConfirmation = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuGramSettings::set_voiceConfirmation(bool val)
|
void AyuGramSettings::set_gifConfirmation(bool val)
|
||||||
{
|
{
|
||||||
voiceConfirmation = val;
|
gifConfirmation = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_ghostModeEnabled()
|
void AyuGramSettings::set_voiceConfirmation(bool val)
|
||||||
{
|
{
|
||||||
return ghostModeEnabled.current();
|
voiceConfirmation = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QString> get_deletedMarkReactive()
|
bool get_ghostModeEnabled()
|
||||||
{
|
{
|
||||||
return deletedMarkReactive.value();
|
return ghostModeEnabled.current();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QString> get_editedMarkReactive()
|
rpl::producer<QString> get_deletedMarkReactive()
|
||||||
{
|
{
|
||||||
return editedMarkReactive.value();
|
return deletedMarkReactive.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> get_showPeerIdReactive()
|
rpl::producer<QString> get_editedMarkReactive()
|
||||||
{
|
{
|
||||||
return showPeerIdReactive.value();
|
return editedMarkReactive.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<bool> get_ghostModeEnabledReactive()
|
rpl::producer<int> get_showPeerIdReactive()
|
||||||
{
|
{
|
||||||
return ghostModeEnabled.value();
|
return showPeerIdReactive.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> get_ghostModeEnabledReactive()
|
||||||
|
{
|
||||||
|
return ghostModeEnabled.value();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "lang_auto.h"
|
#include "lang_auto.h"
|
||||||
|
@ -14,176 +13,180 @@
|
||||||
|
|
||||||
namespace AyuSettings
|
namespace AyuSettings
|
||||||
{
|
{
|
||||||
const auto DEFAULT_ICON = QString("default");
|
|
||||||
const auto ALT_ICON = QString("alt");
|
|
||||||
const auto NOTHING_ICON = QString("nothing");
|
|
||||||
|
|
||||||
class AyuGramSettings
|
const auto DEFAULT_ICON = QString("default");
|
||||||
|
|
||||||
|
const auto ALT_ICON = QString("alt");
|
||||||
|
|
||||||
|
const auto NOTHING_ICON = QString("nothing");
|
||||||
|
|
||||||
|
class AyuGramSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AyuGramSettings()
|
||||||
{
|
{
|
||||||
public:
|
// ~ Ghost essentials
|
||||||
AyuGramSettings()
|
sendReadMessages = true;
|
||||||
{
|
sendReadStories = true;
|
||||||
// ~ Ghost essentials
|
sendOnlinePackets = true;
|
||||||
sendReadMessages = true;
|
sendUploadProgress = true;
|
||||||
sendReadStories = true;
|
sendOfflinePacketAfterOnline = false;
|
||||||
sendOnlinePackets = true;
|
|
||||||
sendUploadProgress = true;
|
|
||||||
sendOfflinePacketAfterOnline = false;
|
|
||||||
|
|
||||||
markReadAfterSend = true;
|
markReadAfterSend = true;
|
||||||
useScheduledMessages = false;
|
useScheduledMessages = false;
|
||||||
|
|
||||||
// ~ Message edits & deletion history
|
// ~ Message edits & deletion history
|
||||||
saveDeletedMessages = true;
|
saveDeletedMessages = true;
|
||||||
saveMessagesHistory = true;
|
saveMessagesHistory = true;
|
||||||
|
|
||||||
// ~ QoL toggles
|
// ~ QoL toggles
|
||||||
disableAds = true;
|
disableAds = true;
|
||||||
disableStories = false;
|
disableStories = false;
|
||||||
localPremium = false;
|
localPremium = false;
|
||||||
copyUsernameAsLink = true;
|
copyUsernameAsLink = true;
|
||||||
|
|
||||||
// ~ Customization
|
// ~ Customization
|
||||||
appIcon = DEFAULT_ICON;
|
appIcon = DEFAULT_ICON;
|
||||||
deletedMark = "🧹";
|
deletedMark = "🧹";
|
||||||
editedMark = tr::lng_edited(tr::now);
|
editedMark = tr::lng_edited(tr::now);
|
||||||
recentStickersCount = 20;
|
recentStickersCount = 20;
|
||||||
showGhostToggleInDrawer = true;
|
showGhostToggleInDrawer = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* showPeerId = 0 means no ID shown
|
* showPeerId = 0 means no ID shown
|
||||||
* showPeerId = 1 means ID shown as for Telegram API devs
|
* showPeerId = 1 means ID shown as for Telegram API devs
|
||||||
* showPeerId = 2 means ID shown as for Bot API devs (-100)
|
* showPeerId = 2 means ID shown as for Bot API devs (-100)
|
||||||
*/
|
*/
|
||||||
showPeerId = 2;
|
showPeerId = 2;
|
||||||
|
|
||||||
hideAllChatsFolder = false;
|
hideAllChatsFolder = false;
|
||||||
showMessageSeconds = false;
|
showMessageSeconds = false;
|
||||||
|
|
||||||
// ~ Confirmations
|
// ~ Confirmations
|
||||||
stickerConfirmation = false;
|
stickerConfirmation = false;
|
||||||
gifConfirmation = false;
|
gifConfirmation = false;
|
||||||
voiceConfirmation = false;
|
voiceConfirmation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sendReadMessages;
|
bool sendReadMessages;
|
||||||
bool sendReadStories;
|
bool sendReadStories;
|
||||||
bool sendOnlinePackets;
|
bool sendOnlinePackets;
|
||||||
bool sendUploadProgress;
|
bool sendUploadProgress;
|
||||||
bool sendOfflinePacketAfterOnline;
|
bool sendOfflinePacketAfterOnline;
|
||||||
bool markReadAfterSend;
|
bool markReadAfterSend;
|
||||||
bool useScheduledMessages;
|
bool useScheduledMessages;
|
||||||
bool saveDeletedMessages;
|
bool saveDeletedMessages;
|
||||||
bool saveMessagesHistory;
|
bool saveMessagesHistory;
|
||||||
bool disableAds;
|
bool disableAds;
|
||||||
bool disableStories;
|
bool disableStories;
|
||||||
bool localPremium;
|
bool localPremium;
|
||||||
bool copyUsernameAsLink;
|
bool copyUsernameAsLink;
|
||||||
QString appIcon;
|
QString appIcon;
|
||||||
QString deletedMark;
|
QString deletedMark;
|
||||||
QString editedMark;
|
QString editedMark;
|
||||||
int recentStickersCount;
|
int recentStickersCount;
|
||||||
bool showGhostToggleInDrawer;
|
bool showGhostToggleInDrawer;
|
||||||
int showPeerId;
|
int showPeerId;
|
||||||
bool hideAllChatsFolder;
|
bool hideAllChatsFolder;
|
||||||
bool showMessageSeconds;
|
bool showMessageSeconds;
|
||||||
bool stickerConfirmation;
|
bool stickerConfirmation;
|
||||||
bool gifConfirmation;
|
bool gifConfirmation;
|
||||||
bool voiceConfirmation;
|
bool voiceConfirmation;
|
||||||
|
|
||||||
public:
|
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);
|
||||||
|
|
||||||
void set_sendUploadProgress(bool val);
|
void set_sendUploadProgress(bool val);
|
||||||
|
|
||||||
void set_sendOfflinePacketAfterOnline(bool val);
|
void set_sendOfflinePacketAfterOnline(bool val);
|
||||||
|
|
||||||
void set_ghostModeEnabled(bool val);
|
void set_ghostModeEnabled(bool val);
|
||||||
|
|
||||||
void set_markReadAfterSend(bool val);
|
void set_markReadAfterSend(bool val);
|
||||||
|
|
||||||
void set_useScheduledMessages(bool val);
|
void set_useScheduledMessages(bool val);
|
||||||
|
|
||||||
void set_keepDeletedMessages(bool val);
|
void set_keepDeletedMessages(bool val);
|
||||||
|
|
||||||
void set_keepMessagesHistory(bool val);
|
void set_keepMessagesHistory(bool val);
|
||||||
|
|
||||||
void set_disableAds(bool val);
|
void set_disableAds(bool val);
|
||||||
|
|
||||||
void set_disableStories(bool val);
|
void set_disableStories(bool val);
|
||||||
|
|
||||||
void set_localPremium(bool val);
|
void set_localPremium(bool val);
|
||||||
|
|
||||||
void set_copyUsernameAsLink(bool val);
|
void set_copyUsernameAsLink(bool val);
|
||||||
|
|
||||||
void set_appIcon(QString val);
|
void set_appIcon(QString val);
|
||||||
|
|
||||||
void set_deletedMark(QString val);
|
void set_deletedMark(QString val);
|
||||||
|
|
||||||
void set_editedMark(QString val);
|
void set_editedMark(QString val);
|
||||||
|
|
||||||
void set_recentStickersCount(int val);
|
void set_recentStickersCount(int val);
|
||||||
|
|
||||||
void set_showGhostToggleInDrawer(bool val);
|
void set_showGhostToggleInDrawer(bool val);
|
||||||
|
|
||||||
void set_showPeerId(int val);
|
void set_showPeerId(int val);
|
||||||
|
|
||||||
void set_showMessageSeconds(bool val);
|
void set_showMessageSeconds(bool val);
|
||||||
|
|
||||||
void set_hideAllChatsFolder(bool val);
|
void set_hideAllChatsFolder(bool val);
|
||||||
|
|
||||||
void set_stickerConfirmation(bool val);
|
void set_stickerConfirmation(bool val);
|
||||||
|
|
||||||
void set_gifConfirmation(bool val);
|
void set_gifConfirmation(bool val);
|
||||||
|
|
||||||
void set_voiceConfirmation(bool val);
|
void set_voiceConfirmation(bool val);
|
||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
|
||||||
AyuGramSettings,
|
AyuGramSettings,
|
||||||
sendReadMessages,
|
sendReadMessages,
|
||||||
sendReadStories,
|
sendReadStories,
|
||||||
sendOnlinePackets,
|
sendOnlinePackets,
|
||||||
sendUploadProgress,
|
sendUploadProgress,
|
||||||
sendOfflinePacketAfterOnline,
|
sendOfflinePacketAfterOnline,
|
||||||
markReadAfterSend,
|
markReadAfterSend,
|
||||||
useScheduledMessages,
|
useScheduledMessages,
|
||||||
saveDeletedMessages,
|
saveDeletedMessages,
|
||||||
saveMessagesHistory,
|
saveMessagesHistory,
|
||||||
disableAds,
|
disableAds,
|
||||||
disableStories,
|
disableStories,
|
||||||
localPremium,
|
localPremium,
|
||||||
copyUsernameAsLink,
|
copyUsernameAsLink,
|
||||||
appIcon,
|
appIcon,
|
||||||
deletedMark,
|
deletedMark,
|
||||||
editedMark,
|
editedMark,
|
||||||
recentStickersCount,
|
recentStickersCount,
|
||||||
showGhostToggleInDrawer,
|
showGhostToggleInDrawer,
|
||||||
showPeerId,
|
showPeerId,
|
||||||
showMessageSeconds,
|
showMessageSeconds,
|
||||||
hideAllChatsFolder,
|
hideAllChatsFolder,
|
||||||
stickerConfirmation,
|
stickerConfirmation,
|
||||||
gifConfirmation,
|
gifConfirmation,
|
||||||
voiceConfirmation
|
voiceConfirmation
|
||||||
);
|
);
|
||||||
|
|
||||||
AyuGramSettings& getInstance();
|
AyuGramSettings &getInstance();
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
rpl::producer<QString> get_deletedMarkReactive();
|
rpl::producer<QString> get_deletedMarkReactive();
|
||||||
|
|
||||||
rpl::producer<QString> get_editedMarkReactive();
|
rpl::producer<QString> get_editedMarkReactive();
|
||||||
|
|
||||||
rpl::producer<int> get_showPeerIdReactive();
|
rpl::producer<int> get_showPeerIdReactive();
|
||||||
|
|
||||||
bool get_ghostModeEnabled();
|
bool get_ghostModeEnabled();
|
||||||
|
|
||||||
|
rpl::producer<bool> get_ghostModeEnabledReactive();
|
||||||
|
|
||||||
rpl::producer<bool> get_ghostModeEnabledReactive();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,17 @@
|
||||||
|
|
||||||
namespace AyuState
|
namespace AyuState
|
||||||
{
|
{
|
||||||
void setAllowSendReadPacket(bool val, int resetAfter)
|
|
||||||
{
|
|
||||||
allowSendReadPacket.val = val;
|
|
||||||
allowSendReadPacket.resetAfter = resetAfter;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getAllowSendPacket()
|
void setAllowSendReadPacket(bool val, int resetAfter)
|
||||||
{
|
{
|
||||||
auto settings = &AyuSettings::getInstance();
|
allowSendReadPacket.val = val;
|
||||||
return settings->sendReadMessages || processVariable(allowSendReadPacket);
|
allowSendReadPacket.resetAfter = resetAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getAllowSendPacket()
|
||||||
|
{
|
||||||
|
auto settings = &AyuSettings::getInstance();
|
||||||
|
return settings->sendReadMessages || processVariable(allowSendReadPacket);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,44 +4,45 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ayu_settings.h"
|
#include "ayu_settings.h"
|
||||||
|
|
||||||
namespace AyuState
|
namespace AyuState
|
||||||
{
|
{
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class AyuStateVariable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool val;
|
|
||||||
int resetAfter;
|
|
||||||
};
|
|
||||||
|
|
||||||
AyuStateVariable allowSendReadPacket;
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
bool processVariable(AyuStateVariable& variable)
|
class AyuStateVariable
|
||||||
{
|
{
|
||||||
if (variable.resetAfter == -1)
|
public:
|
||||||
{
|
bool val;
|
||||||
return variable.val;
|
int resetAfter;
|
||||||
}
|
};
|
||||||
|
|
||||||
variable.resetAfter -= 1;
|
AyuStateVariable allowSendReadPacket;
|
||||||
auto val = variable.val;
|
|
||||||
|
|
||||||
if (variable.resetAfter == 0)
|
bool processVariable(AyuStateVariable &variable)
|
||||||
{
|
{
|
||||||
variable.val = false;
|
if (variable.resetAfter == -1) {
|
||||||
}
|
return variable.val;
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAllowSendReadPacket(bool val, int resetAfter = 1);
|
variable.resetAfter -= 1;
|
||||||
|
auto val = variable.val;
|
||||||
|
|
||||||
|
if (variable.resetAfter == 0) {
|
||||||
|
variable.val = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAllowSendReadPacket(bool val, int resetAfter = 1);
|
||||||
|
|
||||||
|
bool getAllowSendPacket();
|
||||||
|
|
||||||
bool getAllowSendPacket();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,102 +9,127 @@
|
||||||
|
|
||||||
#include "entities.h"
|
#include "entities.h"
|
||||||
#include "ayu/libs/sqlite/sqlite_orm.h"
|
#include "ayu/libs/sqlite/sqlite_orm.h"
|
||||||
#include "ayu/utils/telegram_helpers.h"
|
|
||||||
|
|
||||||
using namespace sqlite_orm;
|
using namespace sqlite_orm;
|
||||||
auto storage = make_storage(
|
|
||||||
"ayugram.db",
|
auto storage = make_storage("ayugram.db",
|
||||||
make_table(
|
make_table("DeletedMessage",
|
||||||
"editedmessage",
|
make_column("userId", &DeletedMessage::userId),
|
||||||
make_column("userId", &EditedMessage::get_user_id, &EditedMessage::set_user_id),
|
make_column("dialogId", &DeletedMessage::dialogId),
|
||||||
make_column("dialogId", &EditedMessage::get_dialog_id, &EditedMessage::set_dialog_id),
|
make_column("groupedId", &DeletedMessage::groupedId),
|
||||||
make_column("groupedId", &EditedMessage::get_grouped_id, &EditedMessage::set_grouped_id),
|
make_column("peerId", &DeletedMessage::peerId),
|
||||||
make_column("peerId", &EditedMessage::get_peer_id, &EditedMessage::set_peer_id),
|
make_column("fromId", &DeletedMessage::fromId),
|
||||||
make_column("fromId", &EditedMessage::get_from_id, &EditedMessage::set_from_id),
|
make_column("topicId", &DeletedMessage::topicId),
|
||||||
make_column("topicId", &EditedMessage::get_topic_id, &EditedMessage::set_topic_id),
|
make_column("messageId", &DeletedMessage::messageId),
|
||||||
make_column("messageId", &EditedMessage::get_message_id, &EditedMessage::set_message_id),
|
make_column("date", &DeletedMessage::date),
|
||||||
make_column("date", &EditedMessage::get_date, &EditedMessage::set_date),
|
make_column("flags", &DeletedMessage::flags),
|
||||||
make_column("flags", &EditedMessage::get_flags, &EditedMessage::set_flags),
|
make_column("editDate", &DeletedMessage::editDate),
|
||||||
make_column("editDate", &EditedMessage::get_edit_date, &EditedMessage::set_edit_date),
|
make_column("views", &DeletedMessage::views),
|
||||||
make_column("editHide", &EditedMessage::is_edit_hide, &EditedMessage::set_edit_hide),
|
make_column("fwdFlags", &DeletedMessage::fwdFlags),
|
||||||
make_column("out", &EditedMessage::is_out, &EditedMessage::set_out),
|
make_column("fwdFromId", &DeletedMessage::fwdFromId),
|
||||||
make_column("entityCreateDate", &EditedMessage::get_entity_create_date, &EditedMessage::set_entity_create_date),
|
make_column("fwdName", &DeletedMessage::fwdName),
|
||||||
make_column("text", &EditedMessage::get_text, &EditedMessage::set_text),
|
make_column("fwdDate", &DeletedMessage::fwdDate),
|
||||||
make_column("textEntities", &EditedMessage::get_text_entities, &EditedMessage::set_text_entities),
|
make_column("fwdPostAuthor", &DeletedMessage::fwdPostAuthor),
|
||||||
make_column("mediaPath", &EditedMessage::get_media_path, &EditedMessage::set_media_path),
|
make_column("replyFlags", &DeletedMessage::replyFlags),
|
||||||
make_column("documentType", &EditedMessage::get_document_type, &EditedMessage::set_document_type),
|
make_column("replyMessageId", &DeletedMessage::replyMessageId),
|
||||||
make_column("documentSerialized", &EditedMessage::get_document_serialized,
|
make_column("replyPeerId", &DeletedMessage::replyPeerId),
|
||||||
&EditedMessage::set_document_serialized),
|
make_column("replyTopId", &DeletedMessage::replyTopId),
|
||||||
make_column("thumbsSerialized", &EditedMessage::get_thumbs_serialized, &EditedMessage::set_thumbs_serialized),
|
make_column("replyForumTopic", &DeletedMessage::replyForumTopic),
|
||||||
make_column("documentAttributesSerialized", &EditedMessage::get_document_attributes_serialized,
|
make_column("entityCreateDate", &DeletedMessage::entityCreateDate),
|
||||||
&EditedMessage::set_document_attributes_serialized),
|
make_column("text", &DeletedMessage::text),
|
||||||
make_column("mimeType", &EditedMessage::get_mime_type, &EditedMessage::set_mime_type)
|
make_column("textEntities", &DeletedMessage::textEntities),
|
||||||
),
|
make_column("mediaPath", &DeletedMessage::mediaPath),
|
||||||
make_table(
|
make_column("hqThumbPath", &DeletedMessage::hqThumbPath),
|
||||||
"deletedmessage",
|
make_column("documentType", &DeletedMessage::documentType),
|
||||||
make_column("userId", &DeletedMessage::get_user_id, &DeletedMessage::set_user_id),
|
make_column("documentSerialized", &DeletedMessage::documentSerialized),
|
||||||
make_column("dialogId", &DeletedMessage::get_dialog_id, &DeletedMessage::set_dialog_id),
|
make_column("thumbsSerialized", &DeletedMessage::thumbsSerialized),
|
||||||
make_column("groupedId", &DeletedMessage::get_grouped_id, &DeletedMessage::set_grouped_id),
|
make_column("documentAttributesSerialized",
|
||||||
make_column("peerId", &DeletedMessage::get_peer_id, &DeletedMessage::set_peer_id),
|
&DeletedMessage::documentAttributesSerialized),
|
||||||
make_column("fromId", &DeletedMessage::get_from_id, &DeletedMessage::set_from_id),
|
make_column("mimeType", &DeletedMessage::mimeType)
|
||||||
make_column("topicId", &DeletedMessage::get_topic_id, &DeletedMessage::set_topic_id),
|
),
|
||||||
make_column("messageId", &DeletedMessage::get_message_id, &DeletedMessage::set_message_id),
|
make_table("EditedMessage",
|
||||||
make_column("date", &DeletedMessage::get_date, &DeletedMessage::set_date),
|
make_column("userId", &EditedMessage::userId),
|
||||||
make_column("flags", &DeletedMessage::get_flags, &DeletedMessage::set_flags),
|
make_column("dialogId", &EditedMessage::dialogId),
|
||||||
make_column("editDate", &DeletedMessage::get_edit_date, &DeletedMessage::set_edit_date),
|
make_column("groupedId", &EditedMessage::groupedId),
|
||||||
make_column("editHide", &DeletedMessage::is_edit_hide, &DeletedMessage::set_edit_hide),
|
make_column("peerId", &EditedMessage::peerId),
|
||||||
make_column("out", &DeletedMessage::is_out, &DeletedMessage::set_out),
|
make_column("fromId", &EditedMessage::fromId),
|
||||||
make_column("entityCreateDate", &DeletedMessage::get_entity_create_date,
|
make_column("topicId", &EditedMessage::topicId),
|
||||||
&DeletedMessage::set_entity_create_date),
|
make_column("messageId", &EditedMessage::messageId),
|
||||||
make_column("text", &DeletedMessage::get_text, &DeletedMessage::set_text),
|
make_column("date", &EditedMessage::date),
|
||||||
make_column("textEntities", &DeletedMessage::get_text_entities, &DeletedMessage::set_text_entities),
|
make_column("flags", &EditedMessage::flags),
|
||||||
make_column("mediaPath", &DeletedMessage::get_media_path, &DeletedMessage::set_media_path),
|
make_column("editDate", &EditedMessage::editDate),
|
||||||
make_column("documentType", &DeletedMessage::get_document_type, &DeletedMessage::set_document_type),
|
make_column("views", &EditedMessage::views),
|
||||||
make_column("documentSerialized", &DeletedMessage::get_document_serialized,
|
make_column("fwdFlags", &EditedMessage::fwdFlags),
|
||||||
&DeletedMessage::set_document_serialized),
|
make_column("fwdFromId", &EditedMessage::fwdFromId),
|
||||||
make_column("thumbsSerialized", &DeletedMessage::get_thumbs_serialized, &DeletedMessage::set_thumbs_serialized),
|
make_column("fwdName", &EditedMessage::fwdName),
|
||||||
make_column("documentAttributesSerialized", &DeletedMessage::get_document_attributes_serialized,
|
make_column("fwdDate", &EditedMessage::fwdDate),
|
||||||
&DeletedMessage::set_document_attributes_serialized),
|
make_column("fwdPostAuthor", &EditedMessage::fwdPostAuthor),
|
||||||
make_column("mimeType", &DeletedMessage::get_mime_type, &DeletedMessage::set_mime_type)
|
make_column("replyFlags", &EditedMessage::replyFlags),
|
||||||
)
|
make_column("replyMessageId", &EditedMessage::replyMessageId),
|
||||||
|
make_column("replyPeerId", &EditedMessage::replyPeerId),
|
||||||
|
make_column("replyTopId", &EditedMessage::replyTopId),
|
||||||
|
make_column("replyForumTopic", &EditedMessage::replyForumTopic),
|
||||||
|
make_column("entityCreateDate", &EditedMessage::entityCreateDate),
|
||||||
|
make_column("text", &EditedMessage::text),
|
||||||
|
make_column("textEntities", &EditedMessage::textEntities),
|
||||||
|
make_column("mediaPath", &EditedMessage::mediaPath),
|
||||||
|
make_column("hqThumbPath", &EditedMessage::hqThumbPath),
|
||||||
|
make_column("documentType", &EditedMessage::documentType),
|
||||||
|
make_column("documentSerialized", &EditedMessage::documentSerialized),
|
||||||
|
make_column("thumbsSerialized", &EditedMessage::thumbsSerialized),
|
||||||
|
make_column("documentAttributesSerialized",
|
||||||
|
&EditedMessage::documentAttributesSerialized),
|
||||||
|
make_column("mimeType", &EditedMessage::mimeType)
|
||||||
|
),
|
||||||
|
make_table("DeletedDialog",
|
||||||
|
make_column("userId", &DeletedDialog::userId),
|
||||||
|
make_column("dialogId", &DeletedDialog::dialogId),
|
||||||
|
make_column("peerId", &DeletedDialog::peerId),
|
||||||
|
make_column("topMessage", &DeletedDialog::topMessage),
|
||||||
|
make_column("lastMessageDate", &DeletedDialog::lastMessageDate),
|
||||||
|
make_column("flags", &DeletedDialog::flags),
|
||||||
|
make_column("entityCreateDate", &DeletedDialog::entityCreateDate)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
namespace AyuDatabase
|
namespace AyuDatabase
|
||||||
{
|
{
|
||||||
void initialize()
|
|
||||||
{
|
|
||||||
storage.sync_schema();
|
|
||||||
|
|
||||||
storage.begin_transaction();
|
void initialize()
|
||||||
storage.commit();
|
{
|
||||||
}
|
storage.sync_schema();
|
||||||
|
|
||||||
|
storage.begin_transaction();
|
||||||
|
storage.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addEditedMessage(const EditedMessage &message)
|
||||||
|
{
|
||||||
|
storage.begin_transaction();
|
||||||
|
storage.insert(message);
|
||||||
|
storage.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId)
|
||||||
|
{
|
||||||
|
return storage.get_all<EditedMessage>(
|
||||||
|
where(
|
||||||
|
c(&EditedMessage::userId) == userId and
|
||||||
|
c(&EditedMessage::dialogId) == dialogId and
|
||||||
|
c(&EditedMessage::messageId) == messageId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasRevisions(ID userId, ID dialogId, ID messageId)
|
||||||
|
{
|
||||||
|
return storage.count<EditedMessage>(
|
||||||
|
where(
|
||||||
|
c(&EditedMessage::userId) == userId and
|
||||||
|
c(&EditedMessage::dialogId) == dialogId and
|
||||||
|
c(&EditedMessage::messageId) == messageId
|
||||||
|
)
|
||||||
|
) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void addEditedMessage(const EditedMessage& message)
|
|
||||||
{
|
|
||||||
storage.begin_transaction();
|
|
||||||
storage.insert(message);
|
|
||||||
storage.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId)
|
|
||||||
{
|
|
||||||
return storage.get_all<EditedMessage>(
|
|
||||||
where(
|
|
||||||
c(&EditedMessage::get_user_id) == userId and
|
|
||||||
c(&EditedMessage::get_dialog_id) == dialogId and
|
|
||||||
c(&EditedMessage::get_message_id) == messageId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasRevisions(ID userId, ID dialogId, ID messageId)
|
|
||||||
{
|
|
||||||
return storage.count<EditedMessage>(
|
|
||||||
where(
|
|
||||||
c(&EditedMessage::get_user_id) == userId and
|
|
||||||
c(&EditedMessage::get_dialog_id) == dialogId and
|
|
||||||
c(&EditedMessage::get_message_id) == messageId
|
|
||||||
)
|
|
||||||
) > 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "entities.h"
|
#include "entities.h"
|
||||||
|
@ -13,9 +12,11 @@
|
||||||
|
|
||||||
namespace AyuDatabase
|
namespace AyuDatabase
|
||||||
{
|
{
|
||||||
void initialize();
|
|
||||||
|
|
||||||
void addEditedMessage(const EditedMessage& message);
|
void initialize();
|
||||||
std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId);
|
|
||||||
bool hasRevisions(ID userId, ID dialogId, ID messageId);
|
void addEditedMessage(const EditedMessage &message);
|
||||||
|
std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId);
|
||||||
|
bool hasRevisions(ID userId, ID dialogId, ID messageId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,17 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define ID long long
|
#define ID long long
|
||||||
|
|
||||||
// https://github.com/AyuGram/AyuGram4A/blob/rewrite/TMessagesProj/src/main/java/com/radolyn/ayugram/database/entities/AyuMessageBase.java
|
template<typename TableName>
|
||||||
class AyuMessageBase
|
class AyuMessageBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ID fakeId;
|
||||||
ID userId;
|
ID userId;
|
||||||
ID dialogId;
|
ID dialogId;
|
||||||
ID groupedId;
|
ID groupedId;
|
||||||
|
@ -24,449 +23,43 @@ public:
|
||||||
ID topicId;
|
ID topicId;
|
||||||
int messageId;
|
int messageId;
|
||||||
int date;
|
int date;
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
int editDate;
|
int editDate;
|
||||||
bool editHide;
|
int views;
|
||||||
bool out;
|
int fwdFlags;
|
||||||
|
ID fwdFromId;
|
||||||
|
std::string fwdName;
|
||||||
|
int fwdDate;
|
||||||
|
std::string fwdPostAuthor;
|
||||||
|
int replyFlags;
|
||||||
|
int replyMessageId;
|
||||||
|
ID replyPeerId;
|
||||||
|
int replyTopId;
|
||||||
|
bool replyForumTopic;
|
||||||
int entityCreateDate;
|
int entityCreateDate;
|
||||||
|
std::string text;
|
||||||
std::string text; // plain text
|
std::vector<char> textEntities;
|
||||||
std::string textEntities; // TL serialized
|
std::string mediaPath;
|
||||||
std::string mediaPath; // full path
|
std::string hqThumbPath;
|
||||||
int documentType; // see DOCUMENT_TYPE_*
|
int documentType;
|
||||||
std::string documentSerialized; // for sticker; TL serialized
|
std::vector<char> documentSerialized;
|
||||||
std::string thumbsSerialized; // for video/etc.; TL serialized
|
std::vector<char> thumbsSerialized;
|
||||||
std::string documentAttributesSerialized; // for video/voice/etc.; TL serialized
|
std::vector<char> documentAttributesSerialized;
|
||||||
std::string mimeType;
|
std::string mimeType;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeletedMessage : public AyuMessageBase
|
using DeletedMessage = AyuMessageBase<struct DeletedMessageTag>;
|
||||||
|
using EditedMessage = AyuMessageBase<struct EditedMessageTag>;
|
||||||
|
|
||||||
|
class DeletedDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] long long get_user_id() const
|
ID fakeId;
|
||||||
{
|
ID userId;
|
||||||
return userId;
|
ID dialogId;
|
||||||
}
|
ID peerId;
|
||||||
|
int topMessage;
|
||||||
void set_user_id(long long user_id)
|
int lastMessageDate;
|
||||||
{
|
int flags;
|
||||||
userId = user_id;
|
int entityCreateDate;
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_dialog_id() const
|
|
||||||
{
|
|
||||||
return dialogId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_dialog_id(long long dialog_id)
|
|
||||||
{
|
|
||||||
dialogId = dialog_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_grouped_id() const
|
|
||||||
{
|
|
||||||
return groupedId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_grouped_id(long long grouped_id)
|
|
||||||
{
|
|
||||||
groupedId = grouped_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_peer_id() const
|
|
||||||
{
|
|
||||||
return peerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_peer_id(long long peer_id)
|
|
||||||
{
|
|
||||||
peerId = peer_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_from_id() const
|
|
||||||
{
|
|
||||||
return fromId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_from_id(long long from_id)
|
|
||||||
{
|
|
||||||
fromId = from_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_topic_id() const
|
|
||||||
{
|
|
||||||
return topicId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_topic_id(long long topic_id)
|
|
||||||
{
|
|
||||||
topicId = topic_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_message_id() const
|
|
||||||
{
|
|
||||||
return messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_message_id(int message_id)
|
|
||||||
{
|
|
||||||
messageId = message_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_date() const
|
|
||||||
{
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_date(int date)
|
|
||||||
{
|
|
||||||
this->date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_flags() const
|
|
||||||
{
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_flags(int flags)
|
|
||||||
{
|
|
||||||
this->flags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_edit_date() const
|
|
||||||
{
|
|
||||||
return editDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_edit_date(int edit_date)
|
|
||||||
{
|
|
||||||
editDate = edit_date;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool is_edit_hide() const
|
|
||||||
{
|
|
||||||
return editHide;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_edit_hide(bool edit_hide)
|
|
||||||
{
|
|
||||||
editHide = edit_hide;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool is_out() const
|
|
||||||
{
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_out(bool out)
|
|
||||||
{
|
|
||||||
this->out = out;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_entity_create_date() const
|
|
||||||
{
|
|
||||||
return entityCreateDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_entity_create_date(int entity_create_date)
|
|
||||||
{
|
|
||||||
entityCreateDate = entity_create_date;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_text() const
|
|
||||||
{
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_text(const std::string& text)
|
|
||||||
{
|
|
||||||
this->text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_text_entities() const
|
|
||||||
{
|
|
||||||
return textEntities;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_text_entities(const std::string& text_entities)
|
|
||||||
{
|
|
||||||
textEntities = text_entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_media_path() const
|
|
||||||
{
|
|
||||||
return mediaPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_media_path(const std::string& media_path)
|
|
||||||
{
|
|
||||||
mediaPath = media_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_document_type() const
|
|
||||||
{
|
|
||||||
return documentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_document_type(int document_type)
|
|
||||||
{
|
|
||||||
documentType = document_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_document_serialized() const
|
|
||||||
{
|
|
||||||
return documentSerialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_document_serialized(const std::string& document_serialized)
|
|
||||||
{
|
|
||||||
documentSerialized = document_serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_thumbs_serialized() const
|
|
||||||
{
|
|
||||||
return thumbsSerialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_thumbs_serialized(const std::string& thumbs_serialized)
|
|
||||||
{
|
|
||||||
thumbsSerialized = thumbs_serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_document_attributes_serialized() const
|
|
||||||
{
|
|
||||||
return documentAttributesSerialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_document_attributes_serialized(const std::string& document_attributes_serialized)
|
|
||||||
{
|
|
||||||
documentAttributesSerialized = document_attributes_serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_mime_type() const
|
|
||||||
{
|
|
||||||
return mimeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_mime_type(const std::string& mime_type)
|
|
||||||
{
|
|
||||||
mimeType = mime_type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class EditedMessage : public AyuMessageBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
[[nodiscard]] long long get_user_id() const
|
|
||||||
{
|
|
||||||
return userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_user_id(long long user_id)
|
|
||||||
{
|
|
||||||
userId = user_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_dialog_id() const
|
|
||||||
{
|
|
||||||
return dialogId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_dialog_id(long long dialog_id)
|
|
||||||
{
|
|
||||||
dialogId = dialog_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_grouped_id() const
|
|
||||||
{
|
|
||||||
return groupedId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_grouped_id(long long grouped_id)
|
|
||||||
{
|
|
||||||
groupedId = grouped_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_peer_id() const
|
|
||||||
{
|
|
||||||
return peerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_peer_id(long long peer_id)
|
|
||||||
{
|
|
||||||
peerId = peer_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_from_id() const
|
|
||||||
{
|
|
||||||
return fromId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_from_id(long long from_id)
|
|
||||||
{
|
|
||||||
fromId = from_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] long long get_topic_id() const
|
|
||||||
{
|
|
||||||
return topicId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_topic_id(long long topic_id)
|
|
||||||
{
|
|
||||||
topicId = topic_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_message_id() const
|
|
||||||
{
|
|
||||||
return messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_message_id(int message_id)
|
|
||||||
{
|
|
||||||
messageId = message_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_date() const
|
|
||||||
{
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_date(int date)
|
|
||||||
{
|
|
||||||
this->date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_flags() const
|
|
||||||
{
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_flags(int flags)
|
|
||||||
{
|
|
||||||
this->flags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_edit_date() const
|
|
||||||
{
|
|
||||||
return editDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_edit_date(int edit_date)
|
|
||||||
{
|
|
||||||
editDate = edit_date;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool is_edit_hide() const
|
|
||||||
{
|
|
||||||
return editHide;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_edit_hide(bool edit_hide)
|
|
||||||
{
|
|
||||||
editHide = edit_hide;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool is_out() const
|
|
||||||
{
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_out(bool out)
|
|
||||||
{
|
|
||||||
this->out = out;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_entity_create_date() const
|
|
||||||
{
|
|
||||||
return entityCreateDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_entity_create_date(int entity_create_date)
|
|
||||||
{
|
|
||||||
entityCreateDate = entity_create_date;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_text() const
|
|
||||||
{
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_text(const std::string& text)
|
|
||||||
{
|
|
||||||
this->text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_text_entities() const
|
|
||||||
{
|
|
||||||
return textEntities;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_text_entities(const std::string& text_entities)
|
|
||||||
{
|
|
||||||
textEntities = text_entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_media_path() const
|
|
||||||
{
|
|
||||||
return mediaPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_media_path(const std::string& media_path)
|
|
||||||
{
|
|
||||||
mediaPath = media_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] int get_document_type() const
|
|
||||||
{
|
|
||||||
return documentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_document_type(int document_type)
|
|
||||||
{
|
|
||||||
documentType = document_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_document_serialized() const
|
|
||||||
{
|
|
||||||
return documentSerialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_document_serialized(const std::string& document_serialized)
|
|
||||||
{
|
|
||||||
documentSerialized = document_serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_thumbs_serialized() const
|
|
||||||
{
|
|
||||||
return thumbsSerialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_thumbs_serialized(const std::string& thumbs_serialized)
|
|
||||||
{
|
|
||||||
thumbsSerialized = thumbs_serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_document_attributes_serialized() const
|
|
||||||
{
|
|
||||||
return documentAttributesSerialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_document_attributes_serialized(const std::string& document_attributes_serialized)
|
|
||||||
{
|
|
||||||
documentAttributesSerialized = document_attributes_serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::string get_mime_type() const
|
|
||||||
{
|
|
||||||
return mimeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_mime_type(const std::string& mime_type)
|
|
||||||
{
|
|
||||||
mimeType = mime_type;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,16 +4,17 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace AyuFeatures::StreamerMode
|
namespace AyuFeatures::StreamerMode
|
||||||
{
|
{
|
||||||
bool isEnabled();
|
|
||||||
void enable();
|
bool isEnabled();
|
||||||
void disable();
|
void enable();
|
||||||
void hideWidgetWindow(QWidget* widget);
|
void disable();
|
||||||
void showWidgetWindow(QWidget* widget);
|
void hideWidgetWindow(QWidget *widget);
|
||||||
|
void showWidgetWindow(QWidget *widget);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,30 +14,34 @@
|
||||||
|
|
||||||
namespace AyuFeatures::StreamerMode
|
namespace AyuFeatures::StreamerMode
|
||||||
{
|
{
|
||||||
bool isEnabledVal;
|
|
||||||
|
|
||||||
bool isEnabled()
|
bool isEnabledVal;
|
||||||
{
|
|
||||||
return isEnabledVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enable()
|
bool isEnabled()
|
||||||
{
|
{
|
||||||
isEnabledVal = true;
|
return isEnabledVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void disable()
|
void enable()
|
||||||
{
|
{
|
||||||
isEnabledVal = false;
|
isEnabledVal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hideWidgetWindow(QWidget* widget) {
|
void disable()
|
||||||
|
{
|
||||||
|
isEnabledVal = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
void hideWidgetWindow(QWidget *widget)
|
||||||
|
{
|
||||||
|
|
||||||
void showWidgetWindow(QWidget* widget) {
|
}
|
||||||
|
|
||||||
|
void showWidgetWindow(QWidget *widget)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,40 +14,42 @@
|
||||||
|
|
||||||
namespace AyuFeatures::StreamerMode
|
namespace AyuFeatures::StreamerMode
|
||||||
{
|
{
|
||||||
bool isEnabledVal;
|
|
||||||
|
|
||||||
bool isEnabled()
|
bool isEnabledVal;
|
||||||
{
|
|
||||||
return isEnabledVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enable()
|
bool isEnabled()
|
||||||
{
|
{
|
||||||
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
return isEnabledVal;
|
||||||
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
}
|
||||||
|
|
||||||
isEnabledVal = true;
|
void enable()
|
||||||
}
|
{
|
||||||
|
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
||||||
|
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
||||||
|
|
||||||
void disable()
|
isEnabledVal = true;
|
||||||
{
|
}
|
||||||
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
|
||||||
SetWindowDisplayAffinity(handle, WDA_NONE);
|
|
||||||
|
|
||||||
isEnabledVal = false;
|
void disable()
|
||||||
}
|
{
|
||||||
|
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
||||||
|
SetWindowDisplayAffinity(handle, WDA_NONE);
|
||||||
|
|
||||||
void hideWidgetWindow(QWidget* widget)
|
isEnabledVal = false;
|
||||||
{
|
}
|
||||||
auto handle = reinterpret_cast<HWND>(widget->window()->winId());
|
|
||||||
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
void hideWidgetWindow(QWidget *widget)
|
||||||
}
|
{
|
||||||
|
auto handle = reinterpret_cast<HWND>(widget->window()->winId());
|
||||||
|
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showWidgetWindow(QWidget *widget)
|
||||||
|
{
|
||||||
|
auto handle = reinterpret_cast<HWND>(widget->window()->winId());
|
||||||
|
SetWindowDisplayAffinity(handle, WDA_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
void showWidgetWindow(QWidget* widget)
|
|
||||||
{
|
|
||||||
auto handle = reinterpret_cast<HWND>(widget->window()->winId());
|
|
||||||
SetWindowDisplayAffinity(handle, WDA_NONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "ayu/ayu_constants.h"
|
#include "ayu/ayu_constants.h"
|
||||||
#include "ayu/database/ayu_database.h"
|
#include "ayu/database/ayu_database.h"
|
||||||
|
#include "ayu/utils/ayu_mapper.h"
|
||||||
#include "ayu/utils/telegram_helpers.h"
|
#include "ayu/utils/telegram_helpers.h"
|
||||||
|
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
|
@ -18,87 +19,91 @@
|
||||||
|
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
#include "history/history_item_components.h"
|
||||||
|
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
|
||||||
namespace AyuMessages
|
namespace AyuMessages
|
||||||
{
|
{
|
||||||
std::optional<ayu_messages_controller> controller = std::nullopt;
|
|
||||||
|
|
||||||
void initialize()
|
std::optional<ayu_messages_controller> controller = std::nullopt;
|
||||||
{
|
|
||||||
if (controller.has_value())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller = ayu_messages_controller();
|
void initialize()
|
||||||
|
{
|
||||||
|
if (controller.has_value()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ayu_messages_controller& getInstance()
|
controller = ayu_messages_controller();
|
||||||
{
|
}
|
||||||
initialize();
|
|
||||||
return controller.value();
|
ayu_messages_controller &getInstance()
|
||||||
}
|
{
|
||||||
|
initialize();
|
||||||
void map(HistoryMessageEdition& edition, not_null<HistoryItem*> item, AyuMessageBase& message)
|
return controller.value();
|
||||||
{
|
}
|
||||||
message.userId = item->history()->owner().session().userId().bare;
|
|
||||||
message.dialogId = getDialogIdFromPeer(item->history()->peer);
|
void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMessage &message)
|
||||||
message.groupedId = item->groupId().value;
|
{
|
||||||
message.peerId = item->from()->id.value; // todo: ???
|
message.userId = item->history()->owner().session().userId().bare;
|
||||||
message.fromId = item->from()->id.value;
|
message.dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||||
if (auto topic = item->history()->asTopic())
|
message.groupedId = item->groupId().value;
|
||||||
{
|
message.peerId = item->from()->id.value; // todo: ???
|
||||||
message.topicId = topic->rootId().bare;
|
message.fromId = item->from()->id.value;
|
||||||
}
|
if (auto topic = item->history()->asTopic()) {
|
||||||
message.messageId = item->id.bare;
|
message.topicId = topic->rootId().bare;
|
||||||
message.date = item->date();
|
}
|
||||||
|
message.messageId = item->id.bare;
|
||||||
// message.flags = todo:
|
message.date = item->date();
|
||||||
|
message.flags = AyuMapper::mapItemFlagsToMTPFlags(item);
|
||||||
message.editDate = edition.editDate;
|
|
||||||
message.editHide = item->hideEditedBadge();
|
if (auto edited = item->Get<HistoryMessageEdited>()) {
|
||||||
message.out = item->out();
|
message.editDate = edited->date;
|
||||||
message.entityCreateDate = base::unixtime::now(); // todo: rework
|
} else {
|
||||||
|
message.editDate = base::unixtime::now();
|
||||||
auto serializedText = serializeTextWithEntities(item);
|
}
|
||||||
message.text = serializedText.first;
|
|
||||||
message.textEntities = serializedText.second;
|
message.views = item->viewsCount();
|
||||||
|
message.entityCreateDate = base::unixtime::now(); // todo: rework
|
||||||
// todo:
|
|
||||||
message.mediaPath = "/";
|
auto serializedText = serializeTextWithEntities(item);
|
||||||
message.documentType = DOCUMENT_TYPE_NONE;
|
message.text = serializedText.first;
|
||||||
|
// message.textEntities = serializedText.second;
|
||||||
// message.documentSerialized;
|
|
||||||
// message.thumbsSerialized;
|
// todo:
|
||||||
// message.documentAttributesSerialized;
|
message.mediaPath = "/";
|
||||||
// message.mimeType;
|
message.documentType = DOCUMENT_TYPE_NONE;
|
||||||
}
|
|
||||||
|
// message.documentSerialized;
|
||||||
void ayu_messages_controller::addEditedMessage(HistoryMessageEdition& edition, not_null<HistoryItem*> item)
|
// message.thumbsSerialized;
|
||||||
{
|
// message.documentAttributesSerialized;
|
||||||
EditedMessage message;
|
// message.mimeType;
|
||||||
map(edition, item, message);
|
}
|
||||||
|
|
||||||
AyuDatabase::addEditedMessage(message);
|
void ayu_messages_controller::addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item)
|
||||||
}
|
{
|
||||||
|
EditedMessage message;
|
||||||
std::vector<EditedMessage> ayu_messages_controller::getEditedMessages(HistoryItem* item)
|
map(edition, item, message);
|
||||||
{
|
|
||||||
auto userId = item->history()->owner().session().userId().bare;
|
AyuDatabase::addEditedMessage(message);
|
||||||
auto dialogId = getDialogIdFromPeer(item->history()->peer);
|
}
|
||||||
auto msgId = item->id.bare;
|
|
||||||
|
std::vector<EditedMessage> ayu_messages_controller::getEditedMessages(HistoryItem *item)
|
||||||
return AyuDatabase::getEditedMessages(userId, dialogId, msgId);
|
{
|
||||||
}
|
auto userId = item->history()->owner().session().userId().bare;
|
||||||
|
auto dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||||
bool ayu_messages_controller::hasRevisions(not_null<HistoryItem*> item)
|
auto msgId = item->id.bare;
|
||||||
{
|
|
||||||
auto userId = item->history()->owner().session().userId().bare;
|
return AyuDatabase::getEditedMessages(userId, dialogId, msgId);
|
||||||
auto dialogId = getDialogIdFromPeer(item->history()->peer);
|
}
|
||||||
auto msgId = item->id.bare;
|
|
||||||
|
bool ayu_messages_controller::hasRevisions(not_null<HistoryItem *> item)
|
||||||
return AyuDatabase::hasRevisions(userId, dialogId, msgId);
|
{
|
||||||
}
|
auto userId = item->history()->owner().session().userId().bare;
|
||||||
|
auto dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||||
|
auto msgId = item->id.bare;
|
||||||
|
|
||||||
|
return AyuDatabase::hasRevisions(userId, dialogId, msgId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ayu/database/entities.h"
|
#include "ayu/database/entities.h"
|
||||||
|
@ -13,13 +12,15 @@
|
||||||
|
|
||||||
namespace AyuMessages
|
namespace AyuMessages
|
||||||
{
|
{
|
||||||
class ayu_messages_controller
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void addEditedMessage(HistoryMessageEdition& edition, not_null<HistoryItem*> item);
|
|
||||||
std::vector<EditedMessage> getEditedMessages(HistoryItem* item);
|
|
||||||
bool hasRevisions(not_null<HistoryItem*> item);
|
|
||||||
};
|
|
||||||
|
|
||||||
ayu_messages_controller& getInstance();
|
class ayu_messages_controller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item);
|
||||||
|
std::vector<EditedMessage> getEditedMessages(HistoryItem *item);
|
||||||
|
bool hasRevisions(not_null<HistoryItem *> item);
|
||||||
|
};
|
||||||
|
|
||||||
|
ayu_messages_controller &getInstance();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,198 +24,183 @@
|
||||||
|
|
||||||
namespace AyuSync
|
namespace AyuSync
|
||||||
{
|
{
|
||||||
std::optional<ayu_sync_controller> controller = std::nullopt;
|
|
||||||
|
|
||||||
bool isAgentDownloaded()
|
std::optional<ayu_sync_controller> controller = std::nullopt;
|
||||||
{
|
|
||||||
return std::filesystem::exists(AgentPath);
|
bool isAgentDownloaded()
|
||||||
|
{
|
||||||
|
return std::filesystem::exists(AgentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAgentRunning()
|
||||||
|
{
|
||||||
|
return isProcessRunning(AgentFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
if (controller.has_value()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAgentRunning()
|
controller = ayu_sync_controller();
|
||||||
{
|
}
|
||||||
return isProcessRunning(AgentFilename);
|
|
||||||
|
ayu_sync_controller &getInstance()
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
return controller.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ayu_sync_controller::initializeAgent()
|
||||||
|
{
|
||||||
|
if (!isAgentDownloaded()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize()
|
if (isAgentRunning()) {
|
||||||
{
|
killProcess(AgentFilename);
|
||||||
if (controller.has_value())
|
}
|
||||||
{
|
|
||||||
return;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller = ayu_sync_controller();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
ayu_sync_controller& getInstance()
|
if (type == "sync_force") {
|
||||||
{
|
auto ev = p.get<SyncForce>();
|
||||||
initialize();
|
onSyncForce(ev);
|
||||||
return controller.value();
|
|
||||||
}
|
}
|
||||||
|
else if (type == "sync_batch") {
|
||||||
void ayu_sync_controller::initializeAgent()
|
onSyncBatch(p);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
else if (type == "sync_read") {
|
||||||
void ayu_sync_controller::syncRead(not_null<History*> history, MsgId untilId)
|
auto ev = p.get<SyncRead>();
|
||||||
{
|
onSyncRead(ev);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
LOG(("Unknown sync type: %1").arg(type.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ayu_sync_controller::receiver()
|
void ayu_sync_controller::onSyncForce(SyncForce ev)
|
||||||
{
|
{
|
||||||
pipe = std::make_unique<ayu_pipe_wrapper>();
|
auto session = getSession(ev.userId);
|
||||||
pipe->connect();
|
auto histories = session->data().chatsList();
|
||||||
|
|
||||||
LOG(("Pipe created"));
|
SyncBatch readsBatchEvent;
|
||||||
|
readsBatchEvent.userId = ev.userId;
|
||||||
|
|
||||||
while (true)
|
for (const auto &row : histories->indexed()->all()) {
|
||||||
{
|
if (const auto history = row->history()) {
|
||||||
auto p = pipe->receive();
|
auto dialogId = getDialogIdFromPeer(history->peer);
|
||||||
if (p == std::nullopt)
|
|
||||||
{
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string s = p->dump();
|
auto untilId = unreadElement ? unreadElement->data()->id.bare : history->lastMessage()->id.bare;
|
||||||
LOG(("[AyuSync] Received message: %1").arg(QString::fromStdString(s)));
|
|
||||||
|
|
||||||
invokeHandler(p.value());
|
readEv.args.dialogId = dialogId;
|
||||||
|
readEv.args.untilId = untilId;
|
||||||
|
readEv.args.unread = history->unreadCount();
|
||||||
|
|
||||||
|
readsBatchEvent.args.events.emplace_back(readEv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ayu_sync_controller::invokeHandler(json p)
|
pipe->send(readsBatchEvent);
|
||||||
{
|
|
||||||
LOG(("Invoking handler on %1").arg(p.dump().c_str()));
|
|
||||||
|
|
||||||
auto userId = p["userId"].get<long>();
|
// send finish event
|
||||||
auto type = p["type"].get<std::string>();
|
SyncForceFinish newEv;
|
||||||
|
newEv.userId = ev.userId;
|
||||||
|
|
||||||
LOG(("userId: %1, type: %2").arg(userId).arg(type.c_str()));
|
pipe->send(newEv);
|
||||||
|
}
|
||||||
|
|
||||||
if (!accountExists(userId))
|
void ayu_sync_controller::onSyncBatch(json ev)
|
||||||
{
|
{
|
||||||
LOG(("Sync for unknown account: %1").arg(userId));
|
for (auto &item : ev["args"]["events"]) {
|
||||||
return;
|
invokeHandler(item);
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "models.h"
|
#include "models.h"
|
||||||
|
@ -16,39 +15,44 @@
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
const std::string AgentFilename =
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
"AyuSync.Agent.exe";
|
|
||||||
|
const std::string AgentFilename = "AyuSync.Agent.exe";
|
||||||
|
|
||||||
#else
|
#else
|
||||||
"AyuSync.Agent";
|
|
||||||
|
const std::string AgentFilename = "AyuSync.Agent";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const std::string AgentPath = "./AyuSync/" + AgentFilename;
|
const std::string AgentPath = "./AyuSync/" + AgentFilename;
|
||||||
|
|
||||||
namespace AyuSync
|
namespace AyuSync
|
||||||
{
|
{
|
||||||
class ayu_sync_controller
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void initializeAgent();
|
|
||||||
|
|
||||||
void syncRead(not_null<History*> history, MsgId untilId);
|
class ayu_sync_controller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void initializeAgent();
|
||||||
|
|
||||||
void onSyncForce(SyncForce ev);
|
void syncRead(not_null<History *> history, MsgId untilId);
|
||||||
void onSyncBatch(json ev);
|
|
||||||
void onSyncRead(SyncRead ev);
|
|
||||||
|
|
||||||
void invokeHandler(json p);
|
void onSyncForce(SyncForce ev);
|
||||||
|
void onSyncBatch(json ev);
|
||||||
|
void onSyncRead(SyncRead ev);
|
||||||
|
|
||||||
private:
|
void invokeHandler(json p);
|
||||||
void receiver();
|
|
||||||
|
|
||||||
std::unique_ptr<ayu_pipe_wrapper> pipe;
|
private:
|
||||||
bool initialized;
|
void receiver();
|
||||||
};
|
|
||||||
|
|
||||||
ayu_sync_controller& getInstance();
|
std::unique_ptr<ayu_pipe_wrapper> pipe;
|
||||||
|
bool initialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
ayu_sync_controller &getInstance();
|
||||||
|
|
||||||
|
bool isAgentDownloaded();
|
||||||
|
bool isAgentRunning();
|
||||||
|
|
||||||
bool isAgentDownloaded();
|
|
||||||
bool isAgentRunning();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
|
// 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
|
#pragma once
|
||||||
|
|
||||||
#include "ayu/libs/json.hpp"
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ayu/libs/json.hpp"
|
||||||
#include "ayu/database/entities.h"
|
#include "ayu/database/entities.h"
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
@ -30,7 +35,41 @@ public:
|
||||||
std::vector<json> events;
|
std::vector<json> events;
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncBatchArgs args;
|
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
|
class SyncRead : public SyncEvent
|
||||||
|
@ -49,50 +88,53 @@ public:
|
||||||
int unread;
|
int unread;
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncReadArgs args;
|
SyncReadArgs args{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyncForce : public SyncEvent
|
class SyncDeletedMessage : public SyncEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SyncForce()
|
explicit SyncDeletedMessage()
|
||||||
{
|
{
|
||||||
type = "sync_force";
|
type = "sync_deleted_message";
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncForceArgs
|
class SyncDeletedMessageArgs
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int fromDate;
|
json message;
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncForceArgs args;
|
SyncDeletedMessageArgs args{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyncForceFinish : public SyncEvent
|
class SyncEditedMessage : public SyncEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SyncForceFinish()
|
explicit SyncEditedMessage()
|
||||||
{
|
{
|
||||||
type = "sync_force_finish";
|
type = "sync_edited_message";
|
||||||
}
|
}
|
||||||
|
|
||||||
class SyncForceFinishArgs
|
class SyncEditedMessageArgs
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
short dummy; // required to be JSON serializable
|
json message;
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncForceFinishArgs args;
|
SyncEditedMessageArgs args{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEvent, type, userId)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEvent, type, userId)
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncBatch::SyncBatchArgs, events)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncBatch::SyncBatchArgs, events)
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncBatch, type, userId, args)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncBatch, 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(SyncForce::SyncForceArgs, fromDate)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce::SyncForceArgs, fromDate)
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce, type, userId, args)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForce, type, userId, args)
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish::SyncForceFinishArgs, dummy)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish::SyncForceFinishArgs, dummy)
|
||||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish, type, userId, args)
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish, type, userId, args)
|
||||||
|
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)
|
||||||
|
|
|
@ -26,14 +26,13 @@ void ayu_pipe_wrapper::send(json p)
|
||||||
bit_converter::i32_to_bytes(length, false, lengthBuff);
|
bit_converter::i32_to_bytes(length, false, lengthBuff);
|
||||||
|
|
||||||
os->write(lengthBuff, 4);
|
os->write(lengthBuff, 4);
|
||||||
os->write(reinterpret_cast<const unsigned char*>(s.c_str()), length);
|
os->write(reinterpret_cast<const unsigned char *>(s.c_str()), length);
|
||||||
os->flush();
|
os->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<json> ayu_pipe_wrapper::receive()
|
std::optional<json> ayu_pipe_wrapper::receive()
|
||||||
{
|
{
|
||||||
if (!is->is_open())
|
if (!is->is_open()) {
|
||||||
{
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,16 +43,14 @@ std::optional<json> ayu_pipe_wrapper::receive()
|
||||||
|
|
||||||
LOG(("ayu_pipe_wrapper::receive() length: %1").arg(length));
|
LOG(("ayu_pipe_wrapper::receive() length: %1").arg(length));
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0) {
|
||||||
{
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sb = stringbuf();
|
auto sb = stringbuf();
|
||||||
unsigned char buff[4096];
|
unsigned char buff[4096];
|
||||||
|
|
||||||
while (length > 0)
|
while (length > 0) {
|
||||||
{
|
|
||||||
auto readSize = std::min(length, static_cast<int>(sizeof(buff)));
|
auto readSize = std::min(length, static_cast<int>(sizeof(buff)));
|
||||||
is->read(buff, readSize);
|
is->read(buff, readSize);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ayu/libs/json.hpp"
|
#include "ayu/libs/json.hpp"
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
// 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 <codecvt>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
@ -12,31 +19,27 @@
|
||||||
|
|
||||||
// A function to check if a process is running by its name
|
// A function to check if a process is running by its name
|
||||||
// Bing AI generated
|
// Bing AI generated
|
||||||
inline bool isProcessRunning(const std::string& name)
|
inline bool isProcessRunning(const std::string &name)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Create a snapshot of all processes
|
// Create a snapshot of all processes
|
||||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
if (snapshot == INVALID_HANDLE_VALUE)
|
if (snapshot == INVALID_HANDLE_VALUE) {
|
||||||
{
|
|
||||||
std::cerr << "Failed to create snapshot\n";
|
std::cerr << "Failed to create snapshot\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Iterate over the processes and compare the names
|
// Iterate over the processes and compare the names
|
||||||
PROCESSENTRY32 entry;
|
PROCESSENTRY32 entry;
|
||||||
entry.dwSize = sizeof(entry);
|
entry.dwSize = sizeof(entry);
|
||||||
if (!Process32First(snapshot, &entry))
|
if (!Process32First(snapshot, &entry)) {
|
||||||
{
|
|
||||||
std::cerr << "Failed to get first process\n";
|
std::cerr << "Failed to get first process\n";
|
||||||
CloseHandle(snapshot);
|
CloseHandle(snapshot);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||||
std::string entry_name = converter.to_bytes(entry.szExeFile);
|
std::string entry_name = converter.to_bytes(entry.szExeFile);
|
||||||
if (name == entry_name)
|
if (name == entry_name) {
|
||||||
{
|
|
||||||
// Found a match
|
// Found a match
|
||||||
CloseHandle(snapshot);
|
CloseHandle(snapshot);
|
||||||
return true;
|
return true;
|
||||||
|
@ -52,34 +55,29 @@ inline bool isProcessRunning(const std::string& name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copilot generated
|
// Copilot generated
|
||||||
void killProcess(const std::string& name)
|
void killProcess(const std::string &name)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
if (snapshot == INVALID_HANDLE_VALUE)
|
if (snapshot == INVALID_HANDLE_VALUE) {
|
||||||
{
|
|
||||||
std::cerr << "Failed to create snapshot\n";
|
std::cerr << "Failed to create snapshot\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Iterate over the processes and compare the names
|
// Iterate over the processes and compare the names
|
||||||
PROCESSENTRY32 entry;
|
PROCESSENTRY32 entry;
|
||||||
entry.dwSize = sizeof(entry);
|
entry.dwSize = sizeof(entry);
|
||||||
if (!Process32First(snapshot, &entry))
|
if (!Process32First(snapshot, &entry)) {
|
||||||
{
|
|
||||||
std::cerr << "Failed to get first process\n";
|
std::cerr << "Failed to get first process\n";
|
||||||
CloseHandle(snapshot);
|
CloseHandle(snapshot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||||
std::string entry_name = converter.to_bytes(entry.szExeFile);
|
std::string entry_name = converter.to_bytes(entry.szExeFile);
|
||||||
if (name == entry_name)
|
if (name == entry_name) {
|
||||||
{
|
|
||||||
// Found a match
|
// Found a match
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
|
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
|
||||||
if (hProcess != nullptr)
|
if (hProcess != nullptr) {
|
||||||
{
|
|
||||||
TerminateProcess(hProcess, 9);
|
TerminateProcess(hProcess, 9);
|
||||||
CloseHandle(hProcess);
|
CloseHandle(hProcess);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,13 @@
|
||||||
#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;
|
||||||
|
|
||||||
void loadAppIco() {
|
void loadAppIco()
|
||||||
|
{
|
||||||
auto settings = &AyuSettings::getInstance();
|
auto settings = &AyuSettings::getInstance();
|
||||||
|
|
||||||
QString appDataPath = QDir::fromNativeSeparators(qgetenv("APPDATA"));
|
QString appDataPath = QDir::fromNativeSeparators(qgetenv("APPDATA"));
|
||||||
|
@ -31,8 +34,7 @@ void loadAppIco() {
|
||||||
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;
|
||||||
|
|
||||||
LAST_LOADED = QImage(qsl(":/gui/art/ayu/%1/logo256.png").arg(settings->appIcon));
|
LAST_LOADED = QImage(qsl(":/gui/art/ayu/%1/logo256.png").arg(settings->appIcon));
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void loadAppIco();
|
void loadAppIco();
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
std::unique_ptr<Lottie::Icon> getLottie(const QString& text)
|
|
||||||
{
|
std::unique_ptr<Lottie::Icon> getLottie(const QString &text)
|
||||||
// todo: some kind of mapping
|
{
|
||||||
// Lottie::MakeIcon({.json = QString(), .sizeOverride = {24, 24}});
|
// todo: some kind of mapping
|
||||||
return nullptr;
|
// Lottie::MakeIcon({.json = QString(), .sizeOverride = {24, 24}});
|
||||||
}
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "lottie/lottie_icon.h"
|
#include "lottie/lottie_icon.h"
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
std::unique_ptr<Lottie::Icon> getLottie(const QString& text);
|
|
||||||
|
std::unique_ptr<Lottie::Icon> getLottie(const QString &text);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,48 +17,52 @@
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
ConfirmationBox::ConfirmationBox(
|
|
||||||
QWidget*,
|
|
||||||
not_null<Window::SessionController*> controller) : _controller(controller)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfirmationBox::prepare()
|
ConfirmationBox::ConfirmationBox(
|
||||||
{
|
QWidget *,
|
||||||
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
|
not_null<Window::SessionController *> controller)
|
||||||
|
: _controller(controller)
|
||||||
auto fullHeight = st::boxPadding.top()
|
{
|
||||||
+ _text->height()
|
//
|
||||||
+ st::boxPadding.bottom();
|
}
|
||||||
|
|
||||||
setDimensions(st::boxWidth, fullHeight);
|
void ConfirmationBox::prepare()
|
||||||
|
{
|
||||||
addButton(tr::ayu_ReadConfirmationBoxActionText(), [=, this]
|
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
|
||||||
{
|
|
||||||
ReadAllPeers();
|
auto fullHeight = st::boxPadding.top()
|
||||||
closeBox();
|
+ _text->height()
|
||||||
});
|
+ st::boxPadding.bottom();
|
||||||
addButton(tr::lng_cancel(), [=, this] { closeBox(); });
|
|
||||||
}
|
setDimensions(st::boxWidth, fullHeight);
|
||||||
|
|
||||||
void ConfirmationBox::resizeEvent(QResizeEvent* e)
|
addButton(tr::ayu_ReadConfirmationBoxActionText(), [=, this]
|
||||||
{
|
{
|
||||||
BoxContent::resizeEvent(e);
|
ReadAllPeers();
|
||||||
|
closeBox();
|
||||||
const auto& padding = st::boxPadding;
|
});
|
||||||
_text->moveToLeft(padding.left(), padding.top());
|
addButton(tr::lng_cancel(), [=, this]
|
||||||
}
|
{ closeBox(); });
|
||||||
|
}
|
||||||
void ConfirmationBox::ReadAllPeers()
|
|
||||||
{
|
void ConfirmationBox::resizeEvent(QResizeEvent *e)
|
||||||
auto settings = &AyuSettings::getInstance();
|
{
|
||||||
auto prev = settings->sendReadMessages;
|
BoxContent::resizeEvent(e);
|
||||||
settings->set_sendReadMessages(true);
|
|
||||||
|
const auto &padding = st::boxPadding;
|
||||||
auto chats = _controller->session().data().chatsList();
|
_text->moveToLeft(padding.left(), padding.top());
|
||||||
Window::MarkAsReadChatListHack(chats);
|
}
|
||||||
|
|
||||||
settings->set_sendReadMessages(prev);
|
void ConfirmationBox::ReadAllPeers()
|
||||||
}
|
{
|
||||||
|
auto settings = &AyuSettings::getInstance();
|
||||||
|
auto prev = settings->sendReadMessages;
|
||||||
|
settings->set_sendReadMessages(true);
|
||||||
|
|
||||||
|
auto chats = _controller->session().data().chatsList();
|
||||||
|
Window::MarkAsReadChatListHack(chats);
|
||||||
|
|
||||||
|
settings->set_sendReadMessages(prev);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,26 +4,29 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "ui/layers/box_content.h"
|
#include "ui/layers/box_content.h"
|
||||||
#include "window/window_main_menu.h"
|
#include "window/window_main_menu.h"
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
class ConfirmationBox : public Ui::BoxContent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConfirmationBox(QWidget*, not_null<Window::SessionController*> controller);
|
|
||||||
|
|
||||||
protected:
|
class ConfirmationBox : public Ui::BoxContent
|
||||||
void prepare() override;
|
{
|
||||||
|
public:
|
||||||
|
ConfirmationBox(QWidget *, not_null<Window::SessionController *> controller);
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* e) override;
|
protected:
|
||||||
|
void prepare() override;
|
||||||
|
|
||||||
private:
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
void ReadAllPeers();
|
|
||||||
|
private:
|
||||||
|
void ReadAllPeers();
|
||||||
|
|
||||||
|
not_null<Window::SessionController *> _controller;
|
||||||
|
object_ptr<Ui::FlatLabel> _text = {nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
not_null<Window::SessionController*> _controller;
|
|
||||||
object_ptr<Ui::FlatLabel> _text = {nullptr};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
#include "ayu/ayu_settings.h"
|
#include "ayu/ayu_settings.h"
|
||||||
|
|
||||||
EditDeletedMarkBox::EditDeletedMarkBox(QWidget*) :
|
EditDeletedMarkBox::EditDeletedMarkBox(QWidget *)
|
||||||
|
:
|
||||||
_text(
|
_text(
|
||||||
this,
|
this,
|
||||||
st::defaultInputField,
|
st::defaultInputField,
|
||||||
|
@ -47,12 +48,16 @@ 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(), [=] { _text->setText(defaultDeletedMark); });
|
addLeftButton(tr::ayu_BoxActionReset(), [=]
|
||||||
|
{ _text->setText(defaultDeletedMark); });
|
||||||
|
|
||||||
addButton(tr::lng_settings_save(), [=] { save(); });
|
addButton(tr::lng_settings_save(), [=]
|
||||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
{ save(); });
|
||||||
|
addButton(tr::lng_cancel(), [=]
|
||||||
|
{ closeBox(); });
|
||||||
|
|
||||||
connect(_text, &Ui::InputField::submitted, [=] { submit(); });
|
connect(_text, &Ui::InputField::submitted, [=]
|
||||||
|
{ submit(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditDeletedMarkBox::setInnerFocus()
|
void EditDeletedMarkBox::setInnerFocus()
|
||||||
|
@ -62,26 +67,24 @@ void EditDeletedMarkBox::setInnerFocus()
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
@ -14,14 +13,14 @@
|
||||||
class EditDeletedMarkBox : public Ui::BoxContent
|
class EditDeletedMarkBox : public Ui::BoxContent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EditDeletedMarkBox(QWidget*);
|
EditDeletedMarkBox(QWidget *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setInnerFocus() override;
|
void setInnerFocus() override;
|
||||||
|
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void submit();
|
void submit();
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
#include "ayu/ayu_settings.h"
|
#include "ayu/ayu_settings.h"
|
||||||
|
|
||||||
EditEditedMarkBox::EditEditedMarkBox(QWidget*) :
|
EditEditedMarkBox::EditEditedMarkBox(QWidget *)
|
||||||
|
:
|
||||||
_text(
|
_text(
|
||||||
this,
|
this,
|
||||||
st::defaultInputField,
|
st::defaultInputField,
|
||||||
|
@ -37,7 +38,6 @@ EditEditedMarkBox::EditEditedMarkBox(QWidget*) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EditEditedMarkBox::prepare()
|
void EditEditedMarkBox::prepare()
|
||||||
{
|
{
|
||||||
const auto defaultEditedMark = tr::lng_edited(tr::now);
|
const auto defaultEditedMark = tr::lng_edited(tr::now);
|
||||||
|
@ -48,14 +48,17 @@ 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(), [=] { _text->setText(defaultEditedMark); });
|
addLeftButton(tr::ayu_BoxActionReset(), [=]
|
||||||
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(); });
|
||||||
|
|
||||||
connect(_text, &Ui::InputField::submitted, [=] { submit(); });
|
connect(_text, &Ui::InputField::submitted, [=]
|
||||||
|
{ submit(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EditEditedMarkBox::setInnerFocus()
|
void EditEditedMarkBox::setInnerFocus()
|
||||||
{
|
{
|
||||||
_text->setFocusFast();
|
_text->setFocusFast();
|
||||||
|
@ -63,26 +66,24 @@ void EditEditedMarkBox::setInnerFocus()
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
@ -14,14 +13,14 @@
|
||||||
class EditEditedMarkBox : public Ui::BoxContent
|
class EditEditedMarkBox : public Ui::BoxContent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EditEditedMarkBox(QWidget*);
|
EditEditedMarkBox(QWidget *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setInnerFocus() override;
|
void setInnerFocus() override;
|
||||||
|
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void submit();
|
void submit();
|
||||||
|
|
|
@ -20,59 +20,58 @@ using namespace Settings;
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
MessageHistoryBox::MessageHistoryBox(QWidget*, HistoryItem* item)
|
|
||||||
: _content(this), _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll))
|
|
||||||
{
|
|
||||||
setupControls();
|
|
||||||
addEditedMessagesToLayout(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHistoryBox::setupControls()
|
MessageHistoryBox::MessageHistoryBox(QWidget *, HistoryItem *item)
|
||||||
{
|
: _content(this), _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll))
|
||||||
_content.create(this);
|
{
|
||||||
|
setupControls();
|
||||||
|
addEditedMessagesToLayout(item);
|
||||||
|
}
|
||||||
|
|
||||||
_content->resizeToWidth(st::boxWideWidth);
|
void MessageHistoryBox::setupControls()
|
||||||
_content->moveToLeft(0, 0);
|
{
|
||||||
|
_content.create(this);
|
||||||
|
|
||||||
_content->heightValue(
|
_content->resizeToWidth(st::boxWideWidth);
|
||||||
) | start_to_stream(_contentHeight, _content->lifetime());
|
_content->moveToLeft(0, 0);
|
||||||
|
|
||||||
_scroll->setOwnedWidget(
|
_content->heightValue(
|
||||||
object_ptr<RpWidget>::fromRaw(_content));
|
) | start_to_stream(_contentHeight, _content->lifetime());
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHistoryBox::resizeEvent(QResizeEvent* e)
|
_scroll->setOwnedWidget(
|
||||||
{
|
object_ptr<RpWidget>::fromRaw(_content));
|
||||||
_scroll->resize(width(), height() - st::boxPhotoPadding.top() - st::boxPadding.bottom());
|
}
|
||||||
_scroll->move(0, st::boxPadding.top());
|
|
||||||
|
|
||||||
if (_content)
|
void MessageHistoryBox::resizeEvent(QResizeEvent *e)
|
||||||
{
|
{
|
||||||
_content->resize(_scroll->width(), _content->height());
|
_scroll->resize(width(), height() - st::boxPhotoPadding.top() - st::boxPadding.bottom());
|
||||||
}
|
_scroll->move(0, st::boxPadding.top());
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHistoryBox::prepare()
|
if (_content) {
|
||||||
{
|
_content->resize(_scroll->width(), _content->height());
|
||||||
setTitle(tr::ayu_EditsHistoryTitle());
|
|
||||||
|
|
||||||
setDimensions(st::boxWideWidth, 900);
|
|
||||||
SetupShadowsToScrollContent(this, _scroll, _contentHeight.events());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHistoryBox::addEditedMessagesToLayout(HistoryItem* item)
|
|
||||||
{
|
|
||||||
auto messages = AyuMessages::getInstance().getEditedMessages(item);
|
|
||||||
if (messages.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& message : messages)
|
|
||||||
{
|
|
||||||
AddSkip(_content);
|
|
||||||
AddDividerText(_content, rpl::single(QString::fromStdString(message.text)));
|
|
||||||
AddSkip(_content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageHistoryBox::prepare()
|
||||||
|
{
|
||||||
|
setTitle(tr::ayu_EditsHistoryTitle());
|
||||||
|
|
||||||
|
setDimensions(st::boxWideWidth, 900);
|
||||||
|
SetupShadowsToScrollContent(this, _scroll, _contentHeight.events());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageHistoryBox::addEditedMessagesToLayout(HistoryItem *item)
|
||||||
|
{
|
||||||
|
auto messages = AyuMessages::getInstance().getEditedMessages(item);
|
||||||
|
if (messages.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &message : messages) {
|
||||||
|
AddSkip(_content);
|
||||||
|
AddDividerText(_content, rpl::single(QString::fromStdString(message.text)));
|
||||||
|
AddSkip(_content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
@ -14,24 +13,26 @@
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
class MessageHistoryBox : public Ui::BoxContent
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MessageHistoryBox(QWidget*, HistoryItem* item);
|
|
||||||
|
|
||||||
protected:
|
class MessageHistoryBox : public Ui::BoxContent
|
||||||
void prepare() override;
|
{
|
||||||
|
public:
|
||||||
|
MessageHistoryBox(QWidget *, HistoryItem *item);
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* e) override;
|
protected:
|
||||||
|
void prepare() override;
|
||||||
|
|
||||||
private:
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
void setupControls();
|
|
||||||
|
|
||||||
void addEditedMessagesToLayout(HistoryItem* item);
|
private:
|
||||||
|
void setupControls();
|
||||||
|
|
||||||
object_ptr<Ui::VerticalLayout> _content;
|
void addEditedMessagesToLayout(HistoryItem *item);
|
||||||
const base::unique_qptr<Ui::ScrollArea> _scroll;
|
|
||||||
|
object_ptr<Ui::VerticalLayout> _content;
|
||||||
|
const base::unique_qptr<Ui::ScrollArea> _scroll;
|
||||||
|
|
||||||
|
rpl::event_stream<int> _contentHeight;
|
||||||
|
};
|
||||||
|
|
||||||
rpl::event_stream<int> _contentHeight;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,112 +14,105 @@
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
void VoiceConfirmBox(not_null<Ui::GenericBox*> box, Ui::ConfirmBoxArgs&& args)
|
|
||||||
|
void VoiceConfirmBox(not_null<Ui::GenericBox *> box, Ui::ConfirmBoxArgs &&args)
|
||||||
|
{
|
||||||
|
const auto weak = MakeWeak(box);
|
||||||
|
const auto lifetime = box->lifetime().make_state<rpl::lifetime>();
|
||||||
|
|
||||||
|
v::match(args.text, [](v::null_t)
|
||||||
{
|
{
|
||||||
const auto weak = MakeWeak(box);
|
}, [&](auto &&)
|
||||||
const auto lifetime = box->lifetime().make_state<rpl::lifetime>();
|
{
|
||||||
|
const auto label = box->addRow(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
box.get(),
|
||||||
|
v::text::take_marked(std::move(args.text)),
|
||||||
|
args.labelStyle ? *args.labelStyle : st::boxLabel),
|
||||||
|
st::boxPadding);
|
||||||
|
if (args.labelFilter) {
|
||||||
|
label->setClickHandlerFilter(std::move(args.labelFilter));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
v::match(args.text, [](v::null_t)
|
const auto prepareCallback = [&](Ui::ConfirmBoxArgs::Callback &callback)
|
||||||
{
|
{
|
||||||
}, [&](auto&&)
|
return [=, confirmed = std::move(callback)]()
|
||||||
{
|
|
||||||
const auto label = box->addRow(
|
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
box.get(),
|
|
||||||
v::text::take_marked(std::move(args.text)),
|
|
||||||
args.labelStyle ? *args.labelStyle : st::boxLabel),
|
|
||||||
st::boxPadding);
|
|
||||||
if (args.labelFilter)
|
|
||||||
{
|
|
||||||
label->setClickHandlerFilter(std::move(args.labelFilter));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto prepareCallback = [&](Ui::ConfirmBoxArgs::Callback& callback)
|
|
||||||
{
|
{
|
||||||
return [=, confirmed = std::move(callback)]()
|
if (const auto callbackPtr = std::get_if<1>(&confirmed)) {
|
||||||
{
|
if (auto callback = (*callbackPtr)) {
|
||||||
if (const auto callbackPtr = std::get_if<1>(&confirmed))
|
callback();
|
||||||
{
|
|
||||||
if (auto callback = (*callbackPtr))
|
|
||||||
{
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (const auto callbackPtr = std::get_if<2>(&confirmed))
|
}
|
||||||
{
|
else if (const auto callbackPtr = std::get_if<2>(&confirmed)) {
|
||||||
if (auto callback = (*callbackPtr))
|
if (auto callback = (*callbackPtr)) {
|
||||||
{
|
callback(crl::guard(weak, [=]
|
||||||
callback(crl::guard(weak, [=] { weak->closeBox(); }));
|
{ weak->closeBox(); }));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (weak)
|
}
|
||||||
{
|
else if (weak) {
|
||||||
weak->closeBox();
|
weak->closeBox();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const auto& defaultButtonStyle = box->getDelegate()->style().button;
|
const auto &defaultButtonStyle = box->getDelegate()->style().button;
|
||||||
|
|
||||||
const auto confirmButton = box->addButton(
|
const auto confirmButton = box->addButton(
|
||||||
v::text::take_plain(std::move(args.confirmText), tr::lng_box_ok()),
|
v::text::take_plain(std::move(args.confirmText), tr::lng_box_ok()),
|
||||||
[=, c = prepareCallback(args.confirmed)]()
|
[=, c = prepareCallback(args.confirmed)]()
|
||||||
|
{
|
||||||
|
lifetime->destroy();
|
||||||
|
c();
|
||||||
|
|
||||||
|
weak->closeBox();
|
||||||
|
},
|
||||||
|
args.confirmStyle ? *args.confirmStyle : defaultButtonStyle);
|
||||||
|
box->events(
|
||||||
|
) | start_with_next([=](not_null<QEvent *> e)
|
||||||
|
{
|
||||||
|
if ((e->type() != QEvent::KeyPress) || !confirmButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto k = static_cast<QKeyEvent *>(e.get());
|
||||||
|
if (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return) {
|
||||||
|
confirmButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
|
||||||
|
}
|
||||||
|
}, box->lifetime());
|
||||||
|
|
||||||
|
if (!args.inform) {
|
||||||
|
const auto cancelButton = box->addButton(
|
||||||
|
v::text::take_plain(std::move(args.cancelText), tr::lng_cancel()),
|
||||||
|
crl::guard(weak, [=, c = prepareCallback(args.cancelled)]()
|
||||||
{
|
{
|
||||||
lifetime->destroy();
|
lifetime->destroy();
|
||||||
c();
|
c();
|
||||||
|
}),
|
||||||
|
args.cancelStyle ? *args.cancelStyle : defaultButtonStyle);
|
||||||
|
|
||||||
weak->closeBox();
|
box->boxClosing(
|
||||||
},
|
) | start_with_next(crl::guard(cancelButton, [=]
|
||||||
args.confirmStyle ? *args.confirmStyle : defaultButtonStyle);
|
|
||||||
box->events(
|
|
||||||
) | start_with_next([=](not_null<QEvent*> e)
|
|
||||||
{
|
{
|
||||||
if ((e->type() != QEvent::KeyPress) || !confirmButton)
|
cancelButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
|
||||||
{
|
}), *lifetime);
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto k = static_cast<QKeyEvent*>(e.get());
|
|
||||||
if (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return)
|
|
||||||
{
|
|
||||||
confirmButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
|
|
||||||
}
|
|
||||||
}, box->lifetime());
|
|
||||||
|
|
||||||
if (!args.inform)
|
|
||||||
{
|
|
||||||
const auto cancelButton = box->addButton(
|
|
||||||
v::text::take_plain(std::move(args.cancelText), tr::lng_cancel()),
|
|
||||||
crl::guard(weak, [=, c = prepareCallback(args.cancelled)]()
|
|
||||||
{
|
|
||||||
lifetime->destroy();
|
|
||||||
c();
|
|
||||||
}),
|
|
||||||
args.cancelStyle ? *args.cancelStyle : defaultButtonStyle);
|
|
||||||
|
|
||||||
box->boxClosing(
|
|
||||||
) | start_with_next(crl::guard(cancelButton, [=]
|
|
||||||
{
|
|
||||||
cancelButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
|
|
||||||
}), *lifetime);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.strictCancel)
|
|
||||||
{
|
|
||||||
lifetime->destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object_ptr<Ui::GenericBox> MakeConfirmBox(Ui::ConfirmBoxArgs&& args)
|
if (args.strictCancel) {
|
||||||
{
|
lifetime->destroy();
|
||||||
return Box(VoiceConfirmBox, std::move(args));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::GenericBox> MakeConfirmBox(Ui::ConfirmBoxArgs &&args)
|
||||||
|
{
|
||||||
|
return Box(VoiceConfirmBox, std::move(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text)
|
||||||
|
{
|
||||||
|
return MakeConfirmBox({
|
||||||
|
.text = std::move(text),
|
||||||
|
.inform = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text)
|
|
||||||
{
|
|
||||||
return MakeConfirmBox({
|
|
||||||
.text = std::move(text),
|
|
||||||
.inform = true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} // namespace AyuUi
|
} // namespace AyuUi
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/boxes/confirm_box.h"
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
@ -13,10 +12,12 @@
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
void VoiceConfirmBox(not_null<Ui::GenericBox*> box, Ui::ConfirmBoxArgs&& args);
|
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::GenericBox> MakeConfirmBox(
|
void VoiceConfirmBox(not_null<Ui::GenericBox *> box, Ui::ConfirmBoxArgs &&args);
|
||||||
Ui::ConfirmBoxArgs&& args);
|
|
||||||
|
[[nodiscard]] object_ptr<Ui::GenericBox> MakeConfirmBox(
|
||||||
|
Ui::ConfirmBoxArgs &&args);
|
||||||
|
|
||||||
|
[[nodiscard]] object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text);
|
||||||
|
|
||||||
[[nodiscard]] object_ptr<Ui::GenericBox> MakeInformBox(v::text::data text);
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
#include "ayu/ui/context_menu/context_menu.h"
|
||||||
#include "context_menu.h"
|
|
||||||
#include "lang_auto.h"
|
#include "lang_auto.h"
|
||||||
#include "ayu/ayu_state.h"
|
#include "ayu/ayu_state.h"
|
||||||
#include "ayu/database/ayu_database.h"
|
|
||||||
#include "ayu/messages/ayu_messages_controller.h"
|
#include "ayu/messages/ayu_messages_controller.h"
|
||||||
#include "ayu/ui/boxes/message_history_box.h"
|
#include "ayu/ui/boxes/message_history_box.h"
|
||||||
|
|
||||||
|
@ -17,46 +15,49 @@
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
|
||||||
|
#include "ayu/ui/sections/edited/edited_log_section.h"
|
||||||
|
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
AyuPopupMenu::AyuPopupMenu(HistoryInner* parent)
|
|
||||||
{
|
|
||||||
_ayuSubMenu = std::make_unique<Ui::PopupMenu>(parent, st::popupMenuWithIcons);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AyuPopupMenu::addHistoryAction(HistoryItem* item)
|
AyuPopupMenu::AyuPopupMenu(HistoryInner *parent)
|
||||||
{
|
{
|
||||||
if (AyuMessages::getInstance().hasRevisions(item))
|
_ayuSubMenu = std::make_unique<Ui::PopupMenu>(parent, st::popupMenuWithIcons);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AyuPopupMenu::addHistoryAction(HistoryItem *item)
|
||||||
|
{
|
||||||
|
if (AyuMessages::getInstance().hasRevisions(item)) {
|
||||||
|
_ayuSubMenu->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=]
|
||||||
{
|
{
|
||||||
_ayuSubMenu->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=]
|
item->history()->session().tryResolveWindow()->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item));
|
||||||
{
|
}, &st::menuIconInfo);
|
||||||
auto box = Box<MessageHistoryBox>(item);
|
|
||||||
show(std::move(box));
|
|
||||||
}, &st::menuIconInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AyuPopupMenu::addHideMessageAction(HistoryItem* item) const
|
void AyuPopupMenu::addHideMessageAction(HistoryItem *item) const
|
||||||
|
{
|
||||||
|
const auto settings = &AyuSettings::getInstance();
|
||||||
|
const auto history = item->history();
|
||||||
|
_ayuSubMenu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]()
|
||||||
{
|
{
|
||||||
const auto settings = &AyuSettings::getInstance();
|
const auto initSaveDeleted = settings->saveDeletedMessages;
|
||||||
const auto history = item->history();
|
|
||||||
_ayuSubMenu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]()
|
|
||||||
{
|
|
||||||
const auto initSaveDeleted = settings->saveDeletedMessages;
|
|
||||||
|
|
||||||
settings->set_keepDeletedMessages(false);
|
settings->set_keepDeletedMessages(false);
|
||||||
history->destroyMessage(item);
|
history->destroyMessage(item);
|
||||||
settings->set_keepDeletedMessages(initSaveDeleted);
|
settings->set_keepDeletedMessages(initSaveDeleted);
|
||||||
}, &st::menuIconClear);
|
}, &st::menuIconClear);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AyuPopupMenu::addReadUntilAction(HistoryItem* item) const
|
void AyuPopupMenu::addReadUntilAction(HistoryItem *item) const
|
||||||
|
{
|
||||||
|
const auto history = item->history();
|
||||||
|
_ayuSubMenu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]()
|
||||||
{
|
{
|
||||||
const auto history = item->history();
|
AyuState::setAllowSendReadPacket(true);
|
||||||
_ayuSubMenu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]()
|
history->session().data().histories().readInboxOnNewMessage(item);
|
||||||
{
|
}, &st::menuIconShowInChat);
|
||||||
AyuState::setAllowSendReadPacket(true);
|
}
|
||||||
history->session().data().histories().readInboxOnNewMessage(item);
|
|
||||||
}, &st::menuIconShowInChat);
|
|
||||||
}
|
|
||||||
} // namespace AyuUi
|
} // namespace AyuUi
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
@ -78,22 +77,24 @@
|
||||||
|
|
||||||
#include "history/view/history_view_context_menu.h"
|
#include "history/view/history_view_context_menu.h"
|
||||||
|
|
||||||
#include <ayu/ayu_settings.h>
|
#include "ayu/ayu_settings.h"
|
||||||
#include <styles/style_info.h>
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
namespace AyuUi
|
namespace AyuUi
|
||||||
{
|
{
|
||||||
class AyuPopupMenu
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AyuPopupMenu(HistoryInner* parent);
|
|
||||||
|
|
||||||
void addHistoryAction(HistoryItem* item);
|
class AyuPopupMenu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AyuPopupMenu(HistoryInner *parent);
|
||||||
|
|
||||||
void addHideMessageAction(HistoryItem* item) const;
|
void addHistoryAction(HistoryItem *item);
|
||||||
|
|
||||||
void addReadUntilAction(HistoryItem* item) const;
|
void addHideMessageAction(HistoryItem *item) const;
|
||||||
|
|
||||||
|
void addReadUntilAction(HistoryItem *item) const;
|
||||||
|
|
||||||
|
std::unique_ptr<Ui::PopupMenu> _ayuSubMenu;
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<Ui::PopupMenu> _ayuSubMenu;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
1774
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_inner.cpp
Normal file
1774
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_inner.cpp
Normal file
File diff suppressed because it is too large
Load diff
312
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_inner.h
Normal file
312
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_inner.h
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#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_section.h"
|
||||||
|
#include "menu/menu_antispam_validator.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
#include "ui/effects/animations.h"
|
||||||
|
#include "ui/widgets/tooltip.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
|
||||||
|
struct ChatRestrictionsInfo;
|
||||||
|
|
||||||
|
namespace Main
|
||||||
|
{
|
||||||
|
class Session;
|
||||||
|
} // namespace Main
|
||||||
|
|
||||||
|
namespace HistoryView
|
||||||
|
{
|
||||||
|
class Element;
|
||||||
|
struct TextState;
|
||||||
|
struct StateRequest;
|
||||||
|
enum class CursorState : char;
|
||||||
|
enum class PointState : char;
|
||||||
|
} // namespace HistoryView
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class PopupMenu;
|
||||||
|
class ChatStyle;
|
||||||
|
struct PeerUserpicView;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Window
|
||||||
|
{
|
||||||
|
class SessionController;
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace EditedLog
|
||||||
|
{
|
||||||
|
|
||||||
|
class SectionMemento;
|
||||||
|
|
||||||
|
class InnerWidget final
|
||||||
|
: public Ui::RpWidget, public Ui::AbstractTooltipShower, public HistoryView::ElementDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InnerWidget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
not_null<PeerData *> peer,
|
||||||
|
not_null<HistoryItem *> item);
|
||||||
|
|
||||||
|
[[nodiscard]] Main::Session &session() const;
|
||||||
|
[[nodiscard]] not_null<Ui::ChatTheme *> theme() const
|
||||||
|
{
|
||||||
|
return _theme.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<int> scrollToSignal() const;
|
||||||
|
|
||||||
|
[[nodiscard]] not_null<PeerData *> channel() const
|
||||||
|
{
|
||||||
|
return _peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the correct scroll position after being resized.
|
||||||
|
void restoreScrollPosition();
|
||||||
|
|
||||||
|
void resizeToWidth(int newWidth, int minHeight)
|
||||||
|
{
|
||||||
|
_minHeight = minHeight;
|
||||||
|
return TWidget::resizeToWidth(newWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveState(not_null<SectionMemento *> memento);
|
||||||
|
void restoreState(not_null<SectionMemento *> memento);
|
||||||
|
|
||||||
|
// Ui::AbstractTooltipShower interface.
|
||||||
|
QString tooltipText() const override;
|
||||||
|
QPoint tooltipPos() const override;
|
||||||
|
bool tooltipWindowActive() const override;
|
||||||
|
|
||||||
|
// HistoryView::ElementDelegate interface.
|
||||||
|
HistoryView::Context elementContext() override;
|
||||||
|
bool elementUnderCursor(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
[[nodiscard]] float64 elementHighlightOpacity(
|
||||||
|
not_null<const HistoryItem *> item) const override;
|
||||||
|
bool elementInSelectionMode() override;
|
||||||
|
bool elementIntersectsRange(
|
||||||
|
not_null<const HistoryView::Element *> view,
|
||||||
|
int from,
|
||||||
|
int till) override;
|
||||||
|
void elementStartStickerLoop(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
void elementShowPollResults(
|
||||||
|
not_null<PollData *> poll,
|
||||||
|
FullMsgId context) override;
|
||||||
|
void elementOpenPhoto(
|
||||||
|
not_null<PhotoData *> photo,
|
||||||
|
FullMsgId context) override;
|
||||||
|
void elementOpenDocument(
|
||||||
|
not_null<DocumentData *> document,
|
||||||
|
FullMsgId context,
|
||||||
|
bool showInMediaView = false) override;
|
||||||
|
void elementCancelUpload(const FullMsgId &context) override;
|
||||||
|
void elementShowTooltip(
|
||||||
|
const TextWithEntities &text,
|
||||||
|
Fn<void()> hiddenCallback) override;
|
||||||
|
bool elementAnimationsPaused() override;
|
||||||
|
bool elementHideReply(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
bool elementShownUnread(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
void elementSendBotCommand(
|
||||||
|
const QString &command,
|
||||||
|
const FullMsgId &context) override;
|
||||||
|
void elementHandleViaClick(not_null<UserData *> bot) override;
|
||||||
|
bool elementIsChatWide() override;
|
||||||
|
not_null<Ui::PathShiftGradient *> elementPathShiftGradient() override;
|
||||||
|
void elementReplyTo(const FullMsgId &to) override;
|
||||||
|
void elementStartInteraction(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
void elementStartPremium(
|
||||||
|
not_null<const HistoryView::Element *> view,
|
||||||
|
HistoryView::Element *replacing) override;
|
||||||
|
void elementCancelPremium(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
QString elementAuthorRank(
|
||||||
|
not_null<const HistoryView::Element *> view) override;
|
||||||
|
|
||||||
|
~InnerWidget();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void visibleTopBottomUpdated(
|
||||||
|
int visibleTop,
|
||||||
|
int visibleBottom) override;
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
void mouseDoubleClickEvent(QMouseEvent *e) override;
|
||||||
|
void enterEventHook(QEnterEvent *e) override;
|
||||||
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
|
|
||||||
|
// Resizes content and counts natural widget height for the desired width.
|
||||||
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using Element = HistoryView::Element;
|
||||||
|
enum class Direction
|
||||||
|
{
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
};
|
||||||
|
enum class MouseAction
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
PrepareDrag,
|
||||||
|
Dragging,
|
||||||
|
Selecting,
|
||||||
|
};
|
||||||
|
enum class EnumItemsDirection
|
||||||
|
{
|
||||||
|
TopToBottom,
|
||||||
|
BottomToTop,
|
||||||
|
};
|
||||||
|
using TextState = HistoryView::TextState;
|
||||||
|
using CursorState = HistoryView::CursorState;
|
||||||
|
using PointState = HistoryView::PointState;
|
||||||
|
using StateRequest = HistoryView::StateRequest;
|
||||||
|
|
||||||
|
void mouseActionStart(const QPoint &screenPos, Qt::MouseButton button);
|
||||||
|
void mouseActionUpdate(const QPoint &screenPos);
|
||||||
|
void mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button);
|
||||||
|
void mouseActionCancel();
|
||||||
|
void updateSelected();
|
||||||
|
void performDrag();
|
||||||
|
int itemTop(not_null<const Element *> view) const;
|
||||||
|
void repaintItem(const Element *view);
|
||||||
|
void refreshItem(not_null<const Element *> view);
|
||||||
|
void resizeItem(not_null<Element *> view);
|
||||||
|
QPoint mapPointToItem(QPoint point, const Element *view) const;
|
||||||
|
|
||||||
|
void showContextMenu(QContextMenuEvent *e, bool showFromTouch = false);
|
||||||
|
void savePhotoToFile(not_null<PhotoData *> photo);
|
||||||
|
void saveDocumentToFile(not_null<DocumentData *> document);
|
||||||
|
void copyContextImage(not_null<PhotoData *> photo);
|
||||||
|
void showStickerPackInfo(not_null<DocumentData *> document);
|
||||||
|
void cancelContextDownload(not_null<DocumentData *> document);
|
||||||
|
void showContextInFolder(not_null<DocumentData *> document);
|
||||||
|
void openContextGif(FullMsgId itemId);
|
||||||
|
void copyContextText(FullMsgId itemId);
|
||||||
|
void copySelectedText();
|
||||||
|
TextForMimeData getSelectedText() const;
|
||||||
|
|
||||||
|
void updateVisibleTopItem();
|
||||||
|
void itemsAdded(Direction direction, int addedCount);
|
||||||
|
void updateSize();
|
||||||
|
void updateEmptyText();
|
||||||
|
void paintEmpty(Painter &p, not_null<const Ui::ChatStyle *> st);
|
||||||
|
void addEvents(Direction direction);
|
||||||
|
Element *viewForItem(const HistoryItem *item);
|
||||||
|
|
||||||
|
void toggleScrollDateShown();
|
||||||
|
void repaintScrollDateCallback();
|
||||||
|
bool displayScrollDate() const;
|
||||||
|
void scrollDateHide();
|
||||||
|
void scrollDateCheck();
|
||||||
|
void scrollDateHideByTimer();
|
||||||
|
|
||||||
|
// This function finds all history items that are displayed and calls template method
|
||||||
|
// for each found message (in given direction) in the passed history with passed top offset.
|
||||||
|
//
|
||||||
|
// Method has "bool (*Method)(not_null<Element*> view, int itemtop, int itembottom)" signature
|
||||||
|
// if it returns false the enumeration stops immidiately.
|
||||||
|
template<EnumItemsDirection direction, typename Method>
|
||||||
|
void enumerateItems(Method method);
|
||||||
|
|
||||||
|
// This function finds all userpics on the left that are displayed and calls template method
|
||||||
|
// for each found userpic (from the top to the bottom) using enumerateItems() method.
|
||||||
|
//
|
||||||
|
// Method has "bool (*Method)(not_null<Element*> view, int userpicTop)" signature
|
||||||
|
// if it returns false the enumeration stops immediately.
|
||||||
|
template<typename Method>
|
||||||
|
void enumerateUserpics(Method method);
|
||||||
|
|
||||||
|
// This function finds all date elements that are displayed and calls template method
|
||||||
|
// for each found date element (from the bottom to the top) using enumerateItems() method.
|
||||||
|
//
|
||||||
|
// Method has "bool (*Method)(not_null<HistoryItem*> item, int itemtop, int dateTop)" signature
|
||||||
|
// if it returns false the enumeration stops immediately.
|
||||||
|
template<typename Method>
|
||||||
|
void enumerateDates(Method method);
|
||||||
|
|
||||||
|
const not_null<Window::SessionController *> _controller;
|
||||||
|
const not_null<PeerData *> _peer;
|
||||||
|
const not_null<HistoryItem *> _item;
|
||||||
|
const not_null<History *> _history;
|
||||||
|
MTP::Sender _api;
|
||||||
|
|
||||||
|
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
|
||||||
|
std::shared_ptr<Ui::ChatTheme> _theme;
|
||||||
|
|
||||||
|
std::vector<OwnedItem> _items;
|
||||||
|
std::set<uint64> _eventIds;
|
||||||
|
std::map<not_null<const HistoryItem *>, not_null<Element *>> _itemsByData;
|
||||||
|
base::flat_map<not_null<const HistoryItem *>, TimeId> _itemDates;
|
||||||
|
base::flat_set<FullMsgId> _animatedStickersPlayed;
|
||||||
|
base::flat_map<not_null<PeerData *>, Ui::PeerUserpicView> _userpics;
|
||||||
|
base::flat_map<not_null<PeerData *>, Ui::PeerUserpicView> _userpicsCache;
|
||||||
|
int _itemsTop = 0;
|
||||||
|
int _itemsWidth = 0;
|
||||||
|
int _itemsHeight = 0;
|
||||||
|
|
||||||
|
int _minHeight = 0;
|
||||||
|
int _visibleTop = 0;
|
||||||
|
int _visibleBottom = 0;
|
||||||
|
Element *_visibleTopItem = nullptr;
|
||||||
|
int _visibleTopFromItem = 0;
|
||||||
|
|
||||||
|
bool _isChatWide = false;
|
||||||
|
bool _scrollDateShown = false;
|
||||||
|
Ui::Animations::Simple _scrollDateOpacity;
|
||||||
|
SingleQueuedInvokation _scrollDateCheck;
|
||||||
|
base::Timer _scrollDateHideTimer;
|
||||||
|
Element *_scrollDateLastItem = nullptr;
|
||||||
|
int _scrollDateLastItemTop = 0;
|
||||||
|
|
||||||
|
// Don't load anything until the memento was read.
|
||||||
|
bool _upLoaded = true;
|
||||||
|
bool _downLoaded = true;
|
||||||
|
bool _filterChanged = false;
|
||||||
|
Ui::Text::String _emptyText;
|
||||||
|
|
||||||
|
MouseAction _mouseAction = MouseAction::None;
|
||||||
|
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
||||||
|
QPoint _dragStartPosition;
|
||||||
|
QPoint _mousePosition;
|
||||||
|
Element *_mouseActionItem = nullptr;
|
||||||
|
CursorState _mouseCursorState = CursorState();
|
||||||
|
uint16 _mouseTextSymbol = 0;
|
||||||
|
bool _pressWasInactive = false;
|
||||||
|
|
||||||
|
Element *_selectedItem = nullptr;
|
||||||
|
TextSelection _selectedText;
|
||||||
|
bool _wasSelectedText = false; // was some text selected in current drag action
|
||||||
|
Qt::CursorShape _cursor = style::cur_default;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
|
QPoint _trippleClickPoint;
|
||||||
|
base::Timer _trippleClickTimer;
|
||||||
|
|
||||||
|
rpl::event_stream<int> _scrollToSignal;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace EditedLog
|
1952
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_item.cpp
Normal file
1952
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_item.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ayu/database/entities.h"
|
||||||
|
|
||||||
|
class History;
|
||||||
|
|
||||||
|
namespace HistoryView
|
||||||
|
{
|
||||||
|
class ElementDelegate;
|
||||||
|
class Element;
|
||||||
|
} // namespace HistoryView
|
||||||
|
|
||||||
|
namespace EditedLog
|
||||||
|
{
|
||||||
|
|
||||||
|
class OwnedItem;
|
||||||
|
|
||||||
|
void GenerateItems(
|
||||||
|
not_null<HistoryView::ElementDelegate *> delegate,
|
||||||
|
not_null<History *> history,
|
||||||
|
EditedMessage message,
|
||||||
|
Fn<void(OwnedItem item, TimeId sentDate, MsgId)> callback);
|
||||||
|
|
||||||
|
// Smart pointer wrapper for HistoryItem* that destroys the owned item.
|
||||||
|
class OwnedItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OwnedItem(std::nullptr_t = nullptr);
|
||||||
|
OwnedItem(
|
||||||
|
not_null<HistoryView::ElementDelegate *> delegate,
|
||||||
|
not_null<HistoryItem *> data);
|
||||||
|
OwnedItem(const OwnedItem &other) = delete;
|
||||||
|
OwnedItem &operator=(const OwnedItem &other) = delete;
|
||||||
|
OwnedItem(OwnedItem &&other);
|
||||||
|
OwnedItem &operator=(OwnedItem &&other);
|
||||||
|
~OwnedItem();
|
||||||
|
|
||||||
|
[[nodiscard]] HistoryView::Element *get() const
|
||||||
|
{
|
||||||
|
return _view.get();
|
||||||
|
}
|
||||||
|
[[nodiscard]] HistoryView::Element *operator->() const
|
||||||
|
{
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
[[nodiscard]] operator HistoryView::Element *() const
|
||||||
|
{
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshView(not_null<HistoryView::ElementDelegate *> delegate);
|
||||||
|
void clearView();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HistoryItem *_data = nullptr;
|
||||||
|
std::unique_ptr<HistoryView::Element> _view;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace EditedLog
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#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/widgets/input_fields.h"
|
||||||
|
#include "ui/ui_utility.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "window/themes/window_theme.h"
|
||||||
|
#include "window/window_adaptive.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "base/timer.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
#include "styles/style_chat_helpers.h"
|
||||||
|
#include "styles/style_window.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
|
||||||
|
namespace EditedLog
|
||||||
|
{
|
||||||
|
|
||||||
|
class FixedBar final : public TWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FixedBar(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
not_null<PeerData *> peer);
|
||||||
|
|
||||||
|
// When animating mode is enabled the content is hidden and the
|
||||||
|
// whole fixed bar acts like a back button.
|
||||||
|
void setAnimatingMode(bool enabled);
|
||||||
|
|
||||||
|
void goBack();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
not_null<Window::SessionController *> _controller;
|
||||||
|
not_null<PeerData *> _peer;
|
||||||
|
object_ptr<Profile::BackButton> _backButton;
|
||||||
|
object_ptr<Ui::CrossButton> _cancel;
|
||||||
|
|
||||||
|
bool _animatingMode = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
object_ptr<Window::SectionWidget> SectionMemento::createWidget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
Window::Column column,
|
||||||
|
const QRect &geometry)
|
||||||
|
{
|
||||||
|
if (column == Window::Column::Third) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto result = object_ptr<Widget>(parent, controller, _peer, _item);
|
||||||
|
result->setInternalState(geometry, this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedBar::FixedBar(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
not_null<PeerData *> peer)
|
||||||
|
: TWidget(parent), _controller(controller), _peer(peer), _backButton(
|
||||||
|
this,
|
||||||
|
&controller->session(),
|
||||||
|
tr::lng_admin_log_title_all(tr::now),
|
||||||
|
controller->adaptive().oneColumnValue()), _cancel(this, st::historyAdminLogCancelSearch)
|
||||||
|
{
|
||||||
|
_backButton->moveToLeft(0, 0);
|
||||||
|
_backButton->setClickedCallback([=]
|
||||||
|
{ goBack(); });
|
||||||
|
|
||||||
|
_cancel->hide(anim::type::instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedBar::goBack()
|
||||||
|
{
|
||||||
|
_controller->showBackFromStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FixedBar::resizeGetHeight(int newWidth)
|
||||||
|
{
|
||||||
|
auto filterLeft = newWidth;
|
||||||
|
|
||||||
|
auto cancelLeft = filterLeft - _cancel->width();
|
||||||
|
_cancel->moveToLeft(cancelLeft, 0);
|
||||||
|
|
||||||
|
auto searchShownLeft = st::topBarArrowPadding.left();
|
||||||
|
auto searchHiddenLeft = filterLeft - 0;
|
||||||
|
auto searchCurrentLeft = anim::interpolate(searchHiddenLeft, searchShownLeft, 0.0);
|
||||||
|
_backButton->resizeToWidth(searchCurrentLeft);
|
||||||
|
_backButton->moveToLeft(0, 0);
|
||||||
|
|
||||||
|
auto newHeight = _backButton->height();
|
||||||
|
|
||||||
|
return newHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedBar::setAnimatingMode(bool enabled)
|
||||||
|
{
|
||||||
|
if (_animatingMode != enabled) {
|
||||||
|
_animatingMode = enabled;
|
||||||
|
setCursor(_animatingMode ? style::cur_pointer : style::cur_default);
|
||||||
|
if (_animatingMode) {
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||||
|
hideChildren();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
showChildren();
|
||||||
|
_cancel->setVisible(false);
|
||||||
|
}
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedBar::paintEvent(QPaintEvent *e)
|
||||||
|
{
|
||||||
|
if (!_animatingMode) {
|
||||||
|
auto p = QPainter(this);
|
||||||
|
p.fillRect(e->rect(), st::topBarBg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedBar::mousePressEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
if (e->button() == Qt::LeftButton) {
|
||||||
|
goBack();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TWidget::mousePressEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget::Widget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
not_null<PeerData *> peer,
|
||||||
|
not_null<HistoryItem *> item)
|
||||||
|
: Window::SectionWidget(parent, controller, rpl::single<PeerData *>(peer)),
|
||||||
|
_scroll(this, st::historyScroll, false),
|
||||||
|
_fixedBar(this, controller, peer),
|
||||||
|
_fixedBarShadow(this),
|
||||||
|
_whatIsThis(
|
||||||
|
this,
|
||||||
|
tr::lng_admin_log_about(tr::now),
|
||||||
|
st::historyComposeButton),
|
||||||
|
_item(item)
|
||||||
|
{
|
||||||
|
_fixedBar->move(0, 0);
|
||||||
|
_fixedBar->resizeToWidth(width());
|
||||||
|
_fixedBar->show();
|
||||||
|
|
||||||
|
_fixedBarShadow->raise();
|
||||||
|
|
||||||
|
controller->adaptive().value(
|
||||||
|
) | rpl::start_with_next([=]
|
||||||
|
{
|
||||||
|
updateAdaptiveLayout();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_inner = _scroll->setOwnedWidget(object_ptr<InnerWidget>(this, controller, peer, item));
|
||||||
|
_inner->scrollToSignal(
|
||||||
|
) | rpl::start_with_next([=](int top)
|
||||||
|
{
|
||||||
|
_scroll->scrollToY(top);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_scroll->move(0, _fixedBar->height());
|
||||||
|
_scroll->show();
|
||||||
|
_scroll->scrolls(
|
||||||
|
) | rpl::start_with_next([=]
|
||||||
|
{
|
||||||
|
onScroll();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
_whatIsThis->setClickedCallback([=]
|
||||||
|
{
|
||||||
|
controller->show(Ui::MakeInformBox(peer->isMegagroup()
|
||||||
|
? tr::lng_admin_log_about_text()
|
||||||
|
: tr::lng_admin_log_about_text_channel()));
|
||||||
|
});
|
||||||
|
|
||||||
|
setupShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::updateAdaptiveLayout()
|
||||||
|
{
|
||||||
|
_fixedBarShadow->moveToLeft(
|
||||||
|
controller()->adaptive().isOneColumn()
|
||||||
|
? 0
|
||||||
|
: st::lineWidth,
|
||||||
|
_fixedBar->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<PeerData *> Widget::channel() const
|
||||||
|
{
|
||||||
|
return _inner->channel();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialogs::RowDescriptor Widget::activeChat() const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
channel()->owner().history(channel()),
|
||||||
|
FullMsgId(channel()->id, ShowAtUnreadMsgId)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Widget::grabForShowAnimation(const Window::SectionSlideParams ¶ms)
|
||||||
|
{
|
||||||
|
if (params.withTopBarShadow) _fixedBarShadow->hide();
|
||||||
|
auto result = Ui::GrabWidget(this);
|
||||||
|
if (params.withTopBarShadow) _fixedBarShadow->show();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::doSetInnerFocus()
|
||||||
|
{
|
||||||
|
_inner->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Widget::showInternal(
|
||||||
|
not_null<Window::SectionMemento *> memento,
|
||||||
|
const Window::SectionShow ¶ms)
|
||||||
|
{
|
||||||
|
if (auto logMemento = dynamic_cast<SectionMemento *>(memento.get())) {
|
||||||
|
if (logMemento->getPeer() == channel()) {
|
||||||
|
restoreState(logMemento);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setInternalState(const QRect &geometry, not_null<SectionMemento *> memento)
|
||||||
|
{
|
||||||
|
setGeometry(geometry);
|
||||||
|
Ui::SendPendingMoveResizeEvents(this);
|
||||||
|
restoreState(memento);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setupShortcuts()
|
||||||
|
{
|
||||||
|
// todo: smth
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Window::SectionMemento> Widget::createMemento()
|
||||||
|
{
|
||||||
|
auto result = std::make_shared<SectionMemento>(channel(), _item);
|
||||||
|
saveState(result.get());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::saveState(not_null<SectionMemento *> memento)
|
||||||
|
{
|
||||||
|
memento->setScrollTop(_scroll->scrollTop());
|
||||||
|
_inner->saveState(memento);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::restoreState(not_null<SectionMemento *> memento)
|
||||||
|
{
|
||||||
|
_inner->restoreState(memento);
|
||||||
|
auto scrollTop = memento->getScrollTop();
|
||||||
|
_scroll->scrollToY(scrollTop);
|
||||||
|
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::resizeEvent(QResizeEvent *e)
|
||||||
|
{
|
||||||
|
if (!width() || !height()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto contentWidth = width();
|
||||||
|
|
||||||
|
auto newScrollTop = _scroll->scrollTop() + topDelta();
|
||||||
|
_fixedBar->resizeToWidth(contentWidth);
|
||||||
|
_fixedBarShadow->resize(contentWidth, st::lineWidth);
|
||||||
|
|
||||||
|
auto bottom = height();
|
||||||
|
auto scrollHeight = bottom - _fixedBar->height() - _whatIsThis->height();
|
||||||
|
auto scrollSize = QSize(contentWidth, scrollHeight);
|
||||||
|
if (_scroll->size() != scrollSize) {
|
||||||
|
_scroll->resize(scrollSize);
|
||||||
|
_inner->resizeToWidth(scrollSize.width(), _scroll->height());
|
||||||
|
_inner->restoreScrollPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_scroll->isHidden()) {
|
||||||
|
if (topDelta()) {
|
||||||
|
_scroll->scrollToY(newScrollTop);
|
||||||
|
}
|
||||||
|
auto scrollTop = _scroll->scrollTop();
|
||||||
|
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
|
||||||
|
}
|
||||||
|
auto fullWidthButtonRect = myrtlrect(0, bottom - _whatIsThis->height(), contentWidth, _whatIsThis->height());
|
||||||
|
_whatIsThis->setGeometry(fullWidthButtonRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::paintEvent(QPaintEvent *e)
|
||||||
|
{
|
||||||
|
if (animatingShow()) {
|
||||||
|
SectionWidget::paintEvent(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (controller()->contentOverlapped(this, e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//if (hasPendingResizedItems()) {
|
||||||
|
// updateListSize();
|
||||||
|
//}
|
||||||
|
|
||||||
|
//auto ms = crl::now();
|
||||||
|
//_historyDownShown.step(ms);
|
||||||
|
|
||||||
|
const auto clip = e->rect();
|
||||||
|
SectionWidget::PaintBackground(controller(), _inner->theme(), this, clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::onScroll()
|
||||||
|
{
|
||||||
|
int scrollTop = _scroll->scrollTop();
|
||||||
|
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::showAnimatedHook(
|
||||||
|
const Window::SectionSlideParams ¶ms)
|
||||||
|
{
|
||||||
|
_fixedBar->setAnimatingMode(true);
|
||||||
|
if (params.withTopBarShadow) _fixedBarShadow->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::showFinishedHook()
|
||||||
|
{
|
||||||
|
_fixedBar->setAnimatingMode(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Widget::floatPlayerHandleWheelEvent(QEvent *e)
|
||||||
|
{
|
||||||
|
return _scroll->viewportEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect Widget::floatPlayerAvailableRect()
|
||||||
|
{
|
||||||
|
return mapToGlobal(_scroll->geometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace EditedLog
|
||||||
|
|
159
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_section.h
Normal file
159
Telegram/SourceFiles/ayu/ui/sections/edited/edited_log_section.h
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "window/section_widget.h"
|
||||||
|
#include "window/section_memento.h"
|
||||||
|
#include "ayu/ui/sections/edited/edited_log_item.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class ScrollArea;
|
||||||
|
class PlainShadow;
|
||||||
|
class FlatButton;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Profile
|
||||||
|
{
|
||||||
|
class BackButton;
|
||||||
|
} // namespace Profile
|
||||||
|
|
||||||
|
namespace EditedLog
|
||||||
|
{
|
||||||
|
|
||||||
|
class FixedBar;
|
||||||
|
class InnerWidget;
|
||||||
|
class SectionMemento;
|
||||||
|
|
||||||
|
class Widget final : public Window::SectionWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Widget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
not_null<PeerData *> peer,
|
||||||
|
not_null<HistoryItem *> item);
|
||||||
|
|
||||||
|
not_null<PeerData *> channel() const;
|
||||||
|
Dialogs::RowDescriptor activeChat() const override;
|
||||||
|
|
||||||
|
bool hasTopBarShadow() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override;
|
||||||
|
|
||||||
|
bool showInternal(
|
||||||
|
not_null<Window::SectionMemento *> memento,
|
||||||
|
const Window::SectionShow ¶ms) override;
|
||||||
|
std::shared_ptr<Window::SectionMemento> createMemento() override;
|
||||||
|
|
||||||
|
void setInternalState(const QRect &geometry, not_null<SectionMemento *> memento);
|
||||||
|
|
||||||
|
// Float player interface.
|
||||||
|
bool floatPlayerHandleWheelEvent(QEvent *e) override;
|
||||||
|
QRect floatPlayerAvailableRect() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
void showAnimatedHook(
|
||||||
|
const Window::SectionSlideParams ¶ms) override;
|
||||||
|
void showFinishedHook() override;
|
||||||
|
void doSetInnerFocus() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onScroll();
|
||||||
|
void updateAdaptiveLayout();
|
||||||
|
void saveState(not_null<SectionMemento *> memento);
|
||||||
|
void restoreState(not_null<SectionMemento *> memento);
|
||||||
|
void setupShortcuts();
|
||||||
|
|
||||||
|
object_ptr<Ui::ScrollArea> _scroll;
|
||||||
|
QPointer<InnerWidget> _inner;
|
||||||
|
object_ptr<FixedBar> _fixedBar;
|
||||||
|
object_ptr<Ui::PlainShadow> _fixedBarShadow;
|
||||||
|
object_ptr<Ui::FlatButton> _whatIsThis;
|
||||||
|
not_null<HistoryItem *> _item;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SectionMemento : public Window::SectionMemento
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Element = HistoryView::Element;
|
||||||
|
|
||||||
|
SectionMemento(not_null<PeerData *> peer, not_null<HistoryItem *> item)
|
||||||
|
: _peer(peer),
|
||||||
|
_item(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Window::SectionWidget> createWidget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController *> controller,
|
||||||
|
Window::Column column,
|
||||||
|
const QRect &geometry) override;
|
||||||
|
|
||||||
|
not_null<PeerData *> getPeer() const
|
||||||
|
{
|
||||||
|
return _peer;
|
||||||
|
}
|
||||||
|
void setScrollTop(int scrollTop)
|
||||||
|
{
|
||||||
|
_scrollTop = scrollTop;
|
||||||
|
}
|
||||||
|
int getScrollTop() const
|
||||||
|
{
|
||||||
|
return _scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setItems(
|
||||||
|
std::vector<OwnedItem> &&items,
|
||||||
|
std::set<uint64> &&eventIds,
|
||||||
|
bool upLoaded,
|
||||||
|
bool downLoaded)
|
||||||
|
{
|
||||||
|
_items = std::move(items);
|
||||||
|
_eventIds = std::move(eventIds);
|
||||||
|
_upLoaded = upLoaded;
|
||||||
|
_downLoaded = downLoaded;
|
||||||
|
}
|
||||||
|
std::vector<OwnedItem> takeItems()
|
||||||
|
{
|
||||||
|
return std::move(_items);
|
||||||
|
}
|
||||||
|
std::set<uint64> takeEventIds()
|
||||||
|
{
|
||||||
|
return std::move(_eventIds);
|
||||||
|
}
|
||||||
|
bool upLoaded() const
|
||||||
|
{
|
||||||
|
return _upLoaded;
|
||||||
|
}
|
||||||
|
bool downLoaded() const
|
||||||
|
{
|
||||||
|
return _downLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
not_null<PeerData *> _peer;
|
||||||
|
not_null<HistoryItem *> _item;
|
||||||
|
int _scrollTop = 0;
|
||||||
|
std::vector<not_null<UserData *>> _admins;
|
||||||
|
std::vector<not_null<UserData *>> _adminsCanEdit;
|
||||||
|
std::vector<OwnedItem> _items;
|
||||||
|
std::set<uint64> _eventIds;
|
||||||
|
bool _upLoaded = false;
|
||||||
|
bool _downLoaded = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace EditedLog
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#include "icon_picker.h"
|
#include "icon_picker.h"
|
||||||
#include "ayu/ayu_settings.h"
|
#include "ayu/ayu_settings.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
@ -21,10 +20,9 @@
|
||||||
#include "ayu/utils/windows_utils.h"
|
#include "ayu/utils/windows_utils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void drawIcon(QPainter& p, const QImage& icon, int offset, bool selected)
|
void drawIcon(QPainter &p, const QImage &icon, int offset, bool selected)
|
||||||
{
|
{
|
||||||
if (selected)
|
if (selected) {
|
||||||
{
|
|
||||||
p.save();
|
p.save();
|
||||||
p.setPen(QPen(st::iconPreviewStroke, 2));
|
p.setPen(QPen(st::iconPreviewStroke, 2));
|
||||||
p.drawEllipse(offset + 2, 2, 68, 68);
|
p.drawEllipse(offset + 2, 2, 68, 68);
|
||||||
|
@ -35,12 +33,13 @@ void drawIcon(QPainter& p, const QImage& icon, int offset, bool selected)
|
||||||
p.drawImage(rect, icon);
|
p.drawImage(rect, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
IconPicker::IconPicker(QWidget* parent) : RpWidget(parent)
|
IconPicker::IconPicker(QWidget *parent)
|
||||||
|
: RpWidget(parent)
|
||||||
{
|
{
|
||||||
setMinimumSize(st::boxWidth, 72);
|
setMinimumSize(st::boxWidth, 72);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconPicker::paintEvent(QPaintEvent* e)
|
void IconPicker::paintEvent(QPaintEvent *e)
|
||||||
{
|
{
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
|
@ -55,30 +54,26 @@ void IconPicker::paintEvent(QPaintEvent* e)
|
||||||
drawIcon(p, icon3, 0 + 64 + 16 + 64 + 16, currentAppLogoName() == AyuSettings::NOTHING_ICON);
|
drawIcon(p, icon3, 0 + 64 + 16 + 64 + 16, currentAppLogoName() == AyuSettings::NOTHING_ICON);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconPicker::mousePressEvent(QMouseEvent* e)
|
void IconPicker::mousePressEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
auto settings = &AyuSettings::getInstance();
|
auto settings = &AyuSettings::getInstance();
|
||||||
auto changed = false;
|
auto changed = false;
|
||||||
|
|
||||||
auto x = e->pos().x();
|
auto x = e->pos().x();
|
||||||
if (x <= 64 && settings->appIcon != AyuSettings::DEFAULT_ICON)
|
if (x <= 64 && settings->appIcon != AyuSettings::DEFAULT_ICON) {
|
||||||
{
|
|
||||||
settings->set_appIcon(AyuSettings::DEFAULT_ICON);
|
settings->set_appIcon(AyuSettings::DEFAULT_ICON);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
else if (x >= 64 + 16 && x <= 64 + 16 + 64 && settings->appIcon != AyuSettings::ALT_ICON)
|
else if (x >= 64 + 16 && x <= 64 + 16 + 64 && settings->appIcon != AyuSettings::ALT_ICON) {
|
||||||
{
|
|
||||||
settings->set_appIcon(AyuSettings::ALT_ICON);
|
settings->set_appIcon(AyuSettings::ALT_ICON);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
else if (x >= 64 + 16 + 64 + 16 && x < 64 + 16 + 64 + 16 + 64 && settings->appIcon != AyuSettings::NOTHING_ICON)
|
else if (x >= 64 + 16 + 64 + 16 && x < 64 + 16 + 64 + 16 + 64 && settings->appIcon != AyuSettings::NOTHING_ICON) {
|
||||||
{
|
|
||||||
settings->set_appIcon(AyuSettings::NOTHING_ICON);
|
settings->set_appIcon(AyuSettings::NOTHING_ICON);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed) {
|
||||||
{
|
|
||||||
AyuSettings::save();
|
AyuSettings::save();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
@ -12,9 +11,9 @@
|
||||||
class IconPicker : public Ui::RpWidget
|
class IconPicker : public Ui::RpWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IconPicker(QWidget* parent);
|
IconPicker(QWidget *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent* e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void mousePressEvent(QMouseEvent* e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/options.h"
|
#include "base/options.h"
|
||||||
|
@ -14,54 +13,56 @@ class BoxContent;
|
||||||
|
|
||||||
namespace Window
|
namespace Window
|
||||||
{
|
{
|
||||||
class Controller;
|
class Controller;
|
||||||
|
class SessionController;
|
||||||
class SessionController;
|
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
extern const char kStreamerMode[];
|
extern const char kStreamerMode[];
|
||||||
|
|
||||||
extern base::options::toggle StreamerMode;
|
extern base::options::toggle StreamerMode;
|
||||||
|
|
||||||
namespace Settings
|
namespace Settings
|
||||||
{
|
{
|
||||||
class Ayu : public Section<Ayu>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ayu(QWidget* parent, not_null<Window::SessionController*> controller);
|
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<QString> title() override;
|
class Ayu : public Section<Ayu>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ayu(QWidget *parent, not_null<Window::SessionController *> controller);
|
||||||
|
|
||||||
private:
|
[[nodiscard]] rpl::producer<QString> title() override;
|
||||||
void AddPlatformOption(
|
|
||||||
not_null<Window::SessionController*> window,
|
|
||||||
not_null<Ui::VerticalLayout*> container,
|
|
||||||
base::options::option<bool>& option,
|
|
||||||
rpl::producer<> resetClicks);
|
|
||||||
|
|
||||||
void SetupGhostEssentials(not_null<Ui::VerticalLayout*> container);
|
private:
|
||||||
|
void AddPlatformOption(
|
||||||
|
not_null<Window::SessionController *> window,
|
||||||
|
not_null<Ui::VerticalLayout *> container,
|
||||||
|
base::options::option<bool> &option,
|
||||||
|
rpl::producer<> resetClicks);
|
||||||
|
|
||||||
void SetupSpyEssentials(not_null<Ui::VerticalLayout*> container);
|
void SetupGhostEssentials(not_null<Ui::VerticalLayout *> container);
|
||||||
|
|
||||||
void SetupQoLToggles(not_null<Ui::VerticalLayout*> container);
|
void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container);
|
||||||
|
|
||||||
void SetupAppIcon(not_null<Ui::VerticalLayout*> container);
|
void SetupQoLToggles(not_null<Ui::VerticalLayout *> container);
|
||||||
|
|
||||||
void SetupCustomization(not_null<Ui::VerticalLayout*> container,
|
void SetupAppIcon(not_null<Ui::VerticalLayout *> container);
|
||||||
not_null<Window::SessionController*> controller);
|
|
||||||
|
|
||||||
void SetupShowPeerId(not_null<Ui::VerticalLayout*> container, not_null<Window::SessionController*> controller);
|
void SetupCustomization(not_null<Ui::VerticalLayout *> container,
|
||||||
|
not_null<Window::SessionController *> controller);
|
||||||
|
|
||||||
void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout*> container);
|
void SetupShowPeerId(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> controller);
|
||||||
|
|
||||||
void SetupAyuSync(not_null<Ui::VerticalLayout*> container);
|
void SetupRecentStickersLimitSlider(not_null<Ui::VerticalLayout *> container);
|
||||||
|
|
||||||
void SetupSendConfirmations(not_null<Ui::VerticalLayout*> container);
|
void SetupAyuSync(not_null<Ui::VerticalLayout *> container);
|
||||||
|
|
||||||
void SetupExperimental(not_null<Ui::VerticalLayout*> container,
|
void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container);
|
||||||
not_null<Window::SessionController*> controller);
|
|
||||||
|
|
||||||
void SetupAyuGramSettings(not_null<Ui::VerticalLayout*> container, not_null<Window::SessionController*> null);
|
void SetupExperimental(not_null<Ui::VerticalLayout *> container,
|
||||||
|
not_null<Window::SessionController *> controller);
|
||||||
|
|
||||||
|
void SetupAyuGramSettings(not_null<Ui::VerticalLayout *> container, not_null<Window::SessionController *> null);
|
||||||
|
|
||||||
|
void setupContent(not_null<Window::SessionController *> controller);
|
||||||
|
};
|
||||||
|
|
||||||
void setupContent(not_null<Window::SessionController*> controller);
|
|
||||||
};
|
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
|
|
@ -13,26 +13,22 @@
|
||||||
|
|
||||||
constexpr auto kMaxChannelId = -1000000000000;
|
constexpr auto kMaxChannelId = -1000000000000;
|
||||||
|
|
||||||
|
QString IDString(not_null<PeerData *> peer)
|
||||||
QString IDString(not_null<PeerData*> peer)
|
|
||||||
{
|
{
|
||||||
auto resultId = QString::number(peerIsUser(peer->id)
|
auto resultId = QString::number(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);
|
||||||
|
|
||||||
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("-");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +43,7 @@ QString IDString(MsgId topic_root_id)
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// 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);
|
||||||
|
|
||||||
rpl::producer<TextWithEntities> IDValue(not_null<PeerData*> peer);
|
rpl::producer<TextWithEntities> IDValue(not_null<PeerData *> peer);
|
||||||
rpl::producer<TextWithEntities> IDValue(MsgId topicRootId);
|
rpl::producer<TextWithEntities> IDValue(MsgId topicRootId);
|
||||||
|
|
86
Telegram/SourceFiles/ayu/utils/ayu_mapper.cpp
Normal file
86
Telegram/SourceFiles/ayu/utils/ayu_mapper.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// 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_mapper.h"
|
||||||
|
|
||||||
|
#include "history/history_item.h"
|
||||||
|
#include "history/history_item_components.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace AyuMapper
|
||||||
|
{
|
||||||
|
|
||||||
|
int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item) {
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
const auto thread = item->topic()
|
||||||
|
? (Data::Thread*)item->topic()
|
||||||
|
: item->history();
|
||||||
|
const auto unseen = item->unread(thread);
|
||||||
|
if (unseen) {
|
||||||
|
flags |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->out()) {
|
||||||
|
flags |= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto reply = item->Get<HistoryMessageForwarded>()) {
|
||||||
|
flags |= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto reply = item->Get<HistoryMessageReply>()) {
|
||||||
|
flags |= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->mentionsMe()) {
|
||||||
|
flags |= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->isUnreadMedia()) {
|
||||||
|
flags |= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->isSilent()) {
|
||||||
|
flags |= 8192;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->isPost()) {
|
||||||
|
flags |= 16384;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->isScheduled()) {
|
||||||
|
flags |= 262144;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: legacy
|
||||||
|
// if (item->isLegacy()) {
|
||||||
|
// flags |= 524288;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (item->hideEditedBadge()) {
|
||||||
|
flags |= 2097152;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->isPinned()) {
|
||||||
|
flags |= 16777216;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->forbidsForward()) {
|
||||||
|
flags |= 67108864;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->topic() && item->topicRootId() == item->id) {
|
||||||
|
flags |= 134217728;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
Telegram/SourceFiles/ayu/utils/ayu_mapper.h
Normal file
14
Telegram/SourceFiles/ayu/utils/ayu_mapper.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
namespace AyuMapper
|
||||||
|
{
|
||||||
|
|
||||||
|
int mapItemFlagsToMTPFlags(not_null<HistoryItem *> item);
|
||||||
|
|
||||||
|
} // namespace AyuMapper
|
|
@ -20,14 +20,11 @@
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,62 +51,56 @@ void dispatchToMainThread(std::function<void()> callback)
|
||||||
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
|
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto history = session->data().history(peerFromChannel(abs(dialogId)));
|
auto history = session->data().history(peerFromChannel(abs(dialogId)));
|
||||||
if (history->folderKnown())
|
if (history->folderKnown()) {
|
||||||
{
|
|
||||||
return history;
|
return history;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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()) {
|
||||||
{
|
|
||||||
return std::make_pair(text, "");
|
return std::make_pair(text, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buff = mtpBuffer();
|
auto buff = mtpBuffer();
|
||||||
for (auto entity : entities.v)
|
for (auto entity : entities.v) {
|
||||||
{
|
|
||||||
entity.write(buff);
|
entity.write(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// but be respectful and credit the original author.
|
// but be respectful and credit the original author.
|
||||||
//
|
//
|
||||||
// Copyright @Radolyn, 2023
|
// Copyright @Radolyn, 2023
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ayu/sync/models.h"
|
#include "ayu/sync/models.h"
|
||||||
|
@ -14,9 +13,9 @@
|
||||||
#include "main/main_domain.h"
|
#include "main/main_domain.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
|
||||||
Main::Session* getSession(ID userId);
|
Main::Session *getSession(ID userId);
|
||||||
bool accountExists(ID userId);
|
bool accountExists(ID userId);
|
||||||
void dispatchToMainThread(std::function<void()> callback);
|
void dispatchToMainThread(std::function<void()> callback);
|
||||||
not_null<History*> getHistoryFromDialogId(ID dialogId, Main::Session* session);
|
not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session);
|
||||||
ID getDialogIdFromPeer(not_null<PeerData*> peer);
|
ID getDialogIdFromPeer(not_null<PeerData *> peer);
|
||||||
std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem*> item);
|
std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem *> item);
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
#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,9 +25,9 @@ void reloadAppIconFromTaskBar() {
|
||||||
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);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
WCHAR wszShortcutPath[MAX_PATH];
|
WCHAR wszShortcutPath[MAX_PATH];
|
||||||
shortcut.toWCharArray(wszShortcutPath);
|
shortcut.toWCharArray(wszShortcutPath);
|
||||||
|
|
|
@ -80,6 +80,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ayu/database/ayu_database.h"
|
#include "ayu/database/ayu_database.h"
|
||||||
#include "ayu/messages/ayu_messages_controller.h"
|
#include "ayu/messages/ayu_messages_controller.h"
|
||||||
#include "ayu/ui/boxes/message_history_box.h"
|
#include "ayu/ui/boxes/message_history_box.h"
|
||||||
|
#include "ayu/ui/sections/edited/edited_log_section.h"
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -1091,8 +1092,7 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||||
{
|
{
|
||||||
result->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=]
|
result->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=]
|
||||||
{
|
{
|
||||||
auto box = Box<AyuUi::MessageHistoryBox>(item);
|
item->history()->session().tryResolveWindow()->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item));
|
||||||
Ui::show(std::move(box));
|
|
||||||
}, &st::menuIconInfo);
|
}, &st::menuIconInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue