mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 21:27:07 +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.h
|
||||
ayu/ayu_constants.h
|
||||
ayu/utils/ayu_mapper.cpp
|
||||
ayu/utils/ayu_mapper.h
|
||||
ayu/utils/telegram_helpers.cpp
|
||||
ayu/utils/telegram_helpers.h
|
||||
ayu/utils/windows_utils.cpp
|
||||
|
@ -118,6 +120,12 @@ PRIVATE
|
|||
ayu/ui/settings/settings_ayu.h
|
||||
ayu/ui/context_menu/context_menu.cpp
|
||||
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.h
|
||||
ayu/ui/boxes/message_history_box.cpp
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#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_PHOTO = 1;
|
||||
|
||||
constexpr int DOCUMENT_TYPE_STICKER = 2;
|
||||
|
||||
constexpr int DOCUMENT_TYPE_FILE = 3;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "core/core_settings.h"
|
||||
#include "lang/lang_instance.h"
|
||||
|
||||
CustomLangPack* CustomLangPack::instance = nullptr;
|
||||
CustomLangPack *CustomLangPack::instance = nullptr;
|
||||
|
||||
CustomLangPack::CustomLangPack() = default;
|
||||
|
||||
|
@ -22,39 +22,35 @@ void CustomLangPack::initInstance()
|
|||
instance = new CustomLangPack;
|
||||
}
|
||||
|
||||
CustomLangPack* CustomLangPack::currentInstance()
|
||||
CustomLangPack *CustomLangPack::currentInstance()
|
||||
{
|
||||
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));
|
||||
|
||||
auto finalLangPackId = langPackId;
|
||||
if (finalLangPackId == qsl("pt-br"))
|
||||
{
|
||||
if (finalLangPackId == qsl("pt-br")) {
|
||||
// meh
|
||||
finalLangPackId = qsl("pt");
|
||||
}
|
||||
|
||||
const auto proxy = Core::App().settings().proxy().isEnabled()
|
||||
? Core::App().settings().proxy().selected()
|
||||
: MTP::ProxyData();
|
||||
if (proxy.type == MTP::ProxyData::Type::Socks5 || proxy.type == MTP::ProxyData::Type::Http)
|
||||
{
|
||||
? Core::App().settings().proxy().selected()
|
||||
: MTP::ProxyData();
|
||||
if (proxy.type == MTP::ProxyData::Type::Socks5 || proxy.type == MTP::ProxyData::Type::Http) {
|
||||
QNetworkProxy LocaleProxy = ToNetworkProxy(ToDirectIpProxy(proxy));
|
||||
networkManager.setProxy(LocaleProxy);
|
||||
}
|
||||
|
||||
QUrl url;
|
||||
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
|
||||
{
|
||||
if (!finalLangPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
|
||||
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
|
||||
finalLangPackId));
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
url.setUrl(qsl("https://raw.githubusercontent.com/AyuGram/Languages/l10n_main/values/langs/%1/Shared.json").arg(
|
||||
needFallback ? langPackBaseId : finalLangPackId));
|
||||
}
|
||||
|
@ -73,24 +69,20 @@ void CustomLangPack::fetchFinished()
|
|||
QString langPackId = Lang::GetInstance().id();
|
||||
auto statusCode = _chkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (statusCode == 404 && !langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
|
||||
{
|
||||
if (statusCode == 404 && !langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
|
||||
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
|
||||
needFallback = true;
|
||||
_chkReply->disconnect();
|
||||
fetchCustomLangPack("", langPackBaseId);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
QByteArray result = _chkReply->readAll().trimmed();
|
||||
QJsonParseError error{};
|
||||
QJsonDocument str = QJsonDocument::fromJson(result, &error);
|
||||
if (error.error == QJsonParseError::NoError)
|
||||
{
|
||||
if (error.error == QJsonParseError::NoError) {
|
||||
parseLangFile(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
LOG(("Incorrect JSON File. Fallback to default language: English..."));
|
||||
loadDefaultLangFile();
|
||||
}
|
||||
|
@ -103,20 +95,17 @@ void CustomLangPack::fetchError(QNetworkReply::NetworkError e)
|
|||
{
|
||||
LOG(("Network error: %1").arg(e));
|
||||
|
||||
if (e == QNetworkReply::NetworkError::ContentNotFoundError)
|
||||
{
|
||||
if (e == QNetworkReply::NetworkError::ContentNotFoundError) {
|
||||
QString langPackBaseId = Lang::GetInstance().baseId();
|
||||
QString langPackId = Lang::GetInstance().id();
|
||||
|
||||
if (!langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback)
|
||||
{
|
||||
if (!langPackId.isEmpty() && !langPackBaseId.isEmpty() && !needFallback) {
|
||||
LOG(("AyuGram Language pack not found! Fallback to main language: %1...").arg(langPackBaseId));
|
||||
needFallback = true;
|
||||
_chkReply->disconnect();
|
||||
fetchCustomLangPack("", langPackBaseId);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
LOG(("AyuGram Language pack not found! Fallback to default language: English..."));
|
||||
loadDefaultLangFile();
|
||||
_chkReply = nullptr;
|
||||
|
@ -127,12 +116,10 @@ void CustomLangPack::fetchError(QNetworkReply::NetworkError e)
|
|||
void CustomLangPack::loadDefaultLangFile()
|
||||
{
|
||||
QFile file(":/localization/en.json");
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QJsonDocument str = QJsonDocument::fromJson(file.readAll());
|
||||
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().updatePluralRules();
|
||||
|
@ -143,15 +130,13 @@ void CustomLangPack::loadDefaultLangFile()
|
|||
void CustomLangPack::parseLangFile(QJsonDocument str)
|
||||
{
|
||||
QJsonObject json = str.object();
|
||||
for (const QString& brokenKey : json.keys())
|
||||
{
|
||||
for (const QString &brokenKey : json.keys()) {
|
||||
auto key = qsl("ayu_") + brokenKey;
|
||||
auto val = json.value(brokenKey).toString().replace(qsl("&"), qsl("&")).toUtf8();
|
||||
|
||||
Lang::GetInstance().resetValue(key.toUtf8());
|
||||
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().applyValue(key.toUtf8().replace("#other", "#few"), val);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
@ -12,18 +11,18 @@
|
|||
|
||||
class CustomLangPack : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_DISABLE_COPY(CustomLangPack)
|
||||
|
||||
public:
|
||||
static CustomLangPack* currentInstance();
|
||||
static CustomLangPack *currentInstance();
|
||||
|
||||
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();
|
||||
|
||||
|
@ -40,6 +39,6 @@ private:
|
|||
~CustomLangPack() override = default;
|
||||
|
||||
QNetworkAccessManager networkManager;
|
||||
QNetworkReply* _chkReply = nullptr;
|
||||
QNetworkReply *_chkReply = nullptr;
|
||||
bool needFallback = false;
|
||||
};
|
||||
|
|
|
@ -14,301 +14,315 @@ using json = nlohmann::json;
|
|||
|
||||
namespace AyuSettings
|
||||
{
|
||||
const QString filename = "tdata/ayu_settings.json";
|
||||
std::optional<AyuGramSettings> settings = std::nullopt;
|
||||
|
||||
rpl::variable<bool> sendReadMessagesReactive;
|
||||
rpl::variable<bool> sendReadStoriesReactive;
|
||||
rpl::variable<bool> sendOnlinePacketsReactive;
|
||||
rpl::variable<bool> sendUploadProgressReactive;
|
||||
rpl::variable<bool> sendOfflinePacketAfterOnlineReactive;
|
||||
const QString filename = "tdata/ayu_settings.json";
|
||||
|
||||
rpl::variable<QString> deletedMarkReactive;
|
||||
rpl::variable<QString> editedMarkReactive;
|
||||
rpl::variable<int> showPeerIdReactive;
|
||||
std::optional<AyuGramSettings> settings = std::nullopt;
|
||||
|
||||
rpl::variable<bool> ghostModeEnabled;
|
||||
rpl::variable<bool> sendReadMessagesReactive;
|
||||
|
||||
rpl::lifetime lifetime = rpl::lifetime();
|
||||
rpl::variable<bool> sendReadStoriesReactive;
|
||||
|
||||
bool ghostModeEnabled_util(AyuGramSettings& settingsUtil)
|
||||
{
|
||||
return
|
||||
!settingsUtil.sendReadMessages
|
||||
rpl::variable<bool> sendOnlinePacketsReactive;
|
||||
|
||||
rpl::variable<bool> sendUploadProgressReactive;
|
||||
|
||||
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.sendOnlinePackets
|
||||
&& !settingsUtil.sendUploadProgress
|
||||
&& settingsUtil.sendOfflinePacketAfterOnline;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
if (settings.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
settings = AyuGramSettings();
|
||||
|
||||
sendReadMessagesReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendReadMessages);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendReadStoriesReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendReadStories);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendOnlinePacketsReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendOnlinePackets);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendUploadProgressReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendUploadProgress);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendOfflinePacketAfterOnline);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
}
|
||||
|
||||
void postinitialize()
|
||||
{
|
||||
sendReadMessagesReactive = settings->sendReadMessages;
|
||||
sendReadStoriesReactive = settings->sendReadStories;
|
||||
sendUploadProgressReactive = settings->sendUploadProgress;
|
||||
sendOfflinePacketAfterOnlineReactive = settings->sendOfflinePacketAfterOnline;
|
||||
sendOnlinePacketsReactive = settings->sendOnlinePackets;
|
||||
|
||||
deletedMarkReactive = settings->deletedMark;
|
||||
editedMarkReactive = settings->editedMark;
|
||||
showPeerIdReactive = settings->showPeerId;
|
||||
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}
|
||||
|
||||
AyuGramSettings& getInstance()
|
||||
{
|
||||
initialize();
|
||||
return settings.value();
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
QFile file(filename);
|
||||
if (!file.exists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
|
||||
initialize();
|
||||
json p = json::parse(data);
|
||||
try
|
||||
{
|
||||
settings = p.get<AyuGramSettings>();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG(("AyuGramSettings: failed to parse settings file"));
|
||||
}
|
||||
postinitialize();
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
initialize();
|
||||
|
||||
json p = settings.value();
|
||||
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(p.dump().c_str());
|
||||
file.close();
|
||||
|
||||
postinitialize();
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendReadMessages(bool val)
|
||||
{
|
||||
sendReadMessages = val;
|
||||
sendReadMessagesReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendReadStories(bool val)
|
||||
{
|
||||
sendReadStories = val;
|
||||
sendReadStoriesReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendOnlinePackets(bool val)
|
||||
{
|
||||
sendOnlinePackets = val;
|
||||
sendOnlinePacketsReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendUploadProgress(bool val)
|
||||
{
|
||||
sendUploadProgress = val;
|
||||
sendUploadProgressReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val)
|
||||
{
|
||||
sendOfflinePacketAfterOnline = val;
|
||||
sendOfflinePacketAfterOnlineReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_ghostModeEnabled(bool val)
|
||||
{
|
||||
set_sendReadMessages(!val);
|
||||
set_sendReadStories(!val);
|
||||
set_sendOnlinePackets(!val);
|
||||
set_sendUploadProgress(!val);
|
||||
set_sendOfflinePacketAfterOnline(val);
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_markReadAfterSend(bool val)
|
||||
{
|
||||
markReadAfterSend = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_useScheduledMessages(bool val)
|
||||
{
|
||||
useScheduledMessages = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_keepDeletedMessages(bool val)
|
||||
{
|
||||
saveDeletedMessages = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_keepMessagesHistory(bool val)
|
||||
{
|
||||
saveMessagesHistory = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_disableAds(bool val)
|
||||
{
|
||||
disableAds = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_disableStories(bool val)
|
||||
{
|
||||
disableStories = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_localPremium(bool val)
|
||||
{
|
||||
localPremium = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_copyUsernameAsLink(bool val)
|
||||
{
|
||||
copyUsernameAsLink = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_appIcon(QString val)
|
||||
{
|
||||
appIcon = std::move(val);
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_deletedMark(QString val)
|
||||
{
|
||||
deletedMark = std::move(val);
|
||||
deletedMarkReactive = deletedMark;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_editedMark(QString val)
|
||||
{
|
||||
editedMark = std::move(val);
|
||||
editedMarkReactive = editedMark;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_recentStickersCount(int val)
|
||||
{
|
||||
recentStickersCount = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_showGhostToggleInDrawer(bool val)
|
||||
{
|
||||
showGhostToggleInDrawer = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_showPeerId(int val)
|
||||
{
|
||||
showPeerId = val;
|
||||
showPeerIdReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_showMessageSeconds(bool val)
|
||||
{
|
||||
showMessageSeconds = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_hideAllChatsFolder(bool val)
|
||||
{
|
||||
hideAllChatsFolder = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_stickerConfirmation(bool val)
|
||||
{
|
||||
stickerConfirmation = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_gifConfirmation(bool val)
|
||||
{
|
||||
gifConfirmation = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_voiceConfirmation(bool val)
|
||||
{
|
||||
voiceConfirmation = val;
|
||||
}
|
||||
|
||||
bool get_ghostModeEnabled()
|
||||
{
|
||||
return ghostModeEnabled.current();
|
||||
}
|
||||
|
||||
rpl::producer<QString> get_deletedMarkReactive()
|
||||
{
|
||||
return deletedMarkReactive.value();
|
||||
}
|
||||
|
||||
rpl::producer<QString> get_editedMarkReactive()
|
||||
{
|
||||
return editedMarkReactive.value();
|
||||
}
|
||||
|
||||
rpl::producer<int> get_showPeerIdReactive()
|
||||
{
|
||||
return showPeerIdReactive.value();
|
||||
}
|
||||
|
||||
rpl::producer<bool> get_ghostModeEnabledReactive()
|
||||
{
|
||||
return ghostModeEnabled.value();
|
||||
}
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
if (settings.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings = AyuGramSettings();
|
||||
|
||||
sendReadMessagesReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendReadMessages);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled =
|
||||
ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendReadStoriesReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendReadStories);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled =
|
||||
ghostModeEnabled_util(settings.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendOnlinePacketsReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendOnlinePackets);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled =
|
||||
ghostModeEnabled_util(settings
|
||||
.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendUploadProgressReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val != settings->sendUploadProgress);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled =
|
||||
ghostModeEnabled_util(settings
|
||||
.value());
|
||||
}, lifetime);
|
||||
// ..
|
||||
sendOfflinePacketAfterOnlineReactive.value() | rpl::filter([=](bool val)
|
||||
{
|
||||
return (val
|
||||
!= settings->sendOfflinePacketAfterOnline);
|
||||
}) | start_with_next([=](bool val)
|
||||
{
|
||||
ghostModeEnabled =
|
||||
ghostModeEnabled_util(
|
||||
settings.value());
|
||||
}, lifetime);
|
||||
}
|
||||
|
||||
void postinitialize()
|
||||
{
|
||||
sendReadMessagesReactive = settings->sendReadMessages;
|
||||
sendReadStoriesReactive = settings->sendReadStories;
|
||||
sendUploadProgressReactive = settings->sendUploadProgress;
|
||||
sendOfflinePacketAfterOnlineReactive = settings->sendOfflinePacketAfterOnline;
|
||||
sendOnlinePacketsReactive = settings->sendOnlinePackets;
|
||||
|
||||
deletedMarkReactive = settings->deletedMark;
|
||||
editedMarkReactive = settings->editedMark;
|
||||
showPeerIdReactive = settings->showPeerId;
|
||||
|
||||
ghostModeEnabled = ghostModeEnabled_util(settings.value());
|
||||
}
|
||||
|
||||
AyuGramSettings &getInstance()
|
||||
{
|
||||
initialize();
|
||||
return settings.value();
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
QFile file(filename);
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
|
||||
initialize();
|
||||
json p = json::parse(data);
|
||||
try {
|
||||
settings = p.get<AyuGramSettings>();
|
||||
}
|
||||
catch (...) {
|
||||
LOG(("AyuGramSettings: failed to parse settings file"));
|
||||
}
|
||||
postinitialize();
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
initialize();
|
||||
|
||||
json p = settings.value();
|
||||
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(p.dump().c_str());
|
||||
file.close();
|
||||
|
||||
postinitialize();
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendReadMessages(bool val)
|
||||
{
|
||||
sendReadMessages = val;
|
||||
sendReadMessagesReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendReadStories(bool val)
|
||||
{
|
||||
sendReadStories = val;
|
||||
sendReadStoriesReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendOnlinePackets(bool val)
|
||||
{
|
||||
sendOnlinePackets = val;
|
||||
sendOnlinePacketsReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendUploadProgress(bool val)
|
||||
{
|
||||
sendUploadProgress = val;
|
||||
sendUploadProgressReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_sendOfflinePacketAfterOnline(bool val)
|
||||
{
|
||||
sendOfflinePacketAfterOnline = val;
|
||||
sendOfflinePacketAfterOnlineReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_ghostModeEnabled(bool val)
|
||||
{
|
||||
set_sendReadMessages(!val);
|
||||
set_sendReadStories(!val);
|
||||
set_sendOnlinePackets(!val);
|
||||
set_sendUploadProgress(!val);
|
||||
set_sendOfflinePacketAfterOnline(val);
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_markReadAfterSend(bool val)
|
||||
{
|
||||
markReadAfterSend = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_useScheduledMessages(bool val)
|
||||
{
|
||||
useScheduledMessages = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_keepDeletedMessages(bool val)
|
||||
{
|
||||
saveDeletedMessages = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_keepMessagesHistory(bool val)
|
||||
{
|
||||
saveMessagesHistory = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_disableAds(bool val)
|
||||
{
|
||||
disableAds = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_disableStories(bool val)
|
||||
{
|
||||
disableStories = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_localPremium(bool val)
|
||||
{
|
||||
localPremium = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_copyUsernameAsLink(bool val)
|
||||
{
|
||||
copyUsernameAsLink = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_appIcon(QString val)
|
||||
{
|
||||
appIcon = std::move(val);
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_deletedMark(QString val)
|
||||
{
|
||||
deletedMark = std::move(val);
|
||||
deletedMarkReactive = deletedMark;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_editedMark(QString val)
|
||||
{
|
||||
editedMark = std::move(val);
|
||||
editedMarkReactive = editedMark;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_recentStickersCount(int val)
|
||||
{
|
||||
recentStickersCount = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_showGhostToggleInDrawer(bool val)
|
||||
{
|
||||
showGhostToggleInDrawer = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_showPeerId(int val)
|
||||
{
|
||||
showPeerId = val;
|
||||
showPeerIdReactive = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_showMessageSeconds(bool val)
|
||||
{
|
||||
showMessageSeconds = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_hideAllChatsFolder(bool val)
|
||||
{
|
||||
hideAllChatsFolder = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_stickerConfirmation(bool val)
|
||||
{
|
||||
stickerConfirmation = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_gifConfirmation(bool val)
|
||||
{
|
||||
gifConfirmation = val;
|
||||
}
|
||||
|
||||
void AyuGramSettings::set_voiceConfirmation(bool val)
|
||||
{
|
||||
voiceConfirmation = val;
|
||||
}
|
||||
|
||||
bool get_ghostModeEnabled()
|
||||
{
|
||||
return ghostModeEnabled.current();
|
||||
}
|
||||
|
||||
rpl::producer<QString> get_deletedMarkReactive()
|
||||
{
|
||||
return deletedMarkReactive.value();
|
||||
}
|
||||
|
||||
rpl::producer<QString> get_editedMarkReactive()
|
||||
{
|
||||
return editedMarkReactive.value();
|
||||
}
|
||||
|
||||
rpl::producer<int> get_showPeerIdReactive()
|
||||
{
|
||||
return showPeerIdReactive.value();
|
||||
}
|
||||
|
||||
rpl::producer<bool> get_ghostModeEnabledReactive()
|
||||
{
|
||||
return ghostModeEnabled.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lang_auto.h"
|
||||
|
@ -14,176 +13,180 @@
|
|||
|
||||
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:
|
||||
AyuGramSettings()
|
||||
{
|
||||
// ~ Ghost essentials
|
||||
sendReadMessages = true;
|
||||
sendReadStories = true;
|
||||
sendOnlinePackets = true;
|
||||
sendUploadProgress = true;
|
||||
sendOfflinePacketAfterOnline = false;
|
||||
// ~ Ghost essentials
|
||||
sendReadMessages = true;
|
||||
sendReadStories = true;
|
||||
sendOnlinePackets = true;
|
||||
sendUploadProgress = true;
|
||||
sendOfflinePacketAfterOnline = false;
|
||||
|
||||
markReadAfterSend = true;
|
||||
useScheduledMessages = false;
|
||||
markReadAfterSend = true;
|
||||
useScheduledMessages = false;
|
||||
|
||||
// ~ Message edits & deletion history
|
||||
saveDeletedMessages = true;
|
||||
saveMessagesHistory = true;
|
||||
// ~ Message edits & deletion history
|
||||
saveDeletedMessages = true;
|
||||
saveMessagesHistory = true;
|
||||
|
||||
// ~ QoL toggles
|
||||
disableAds = true;
|
||||
disableStories = false;
|
||||
localPremium = false;
|
||||
copyUsernameAsLink = true;
|
||||
// ~ QoL toggles
|
||||
disableAds = true;
|
||||
disableStories = false;
|
||||
localPremium = false;
|
||||
copyUsernameAsLink = true;
|
||||
|
||||
// ~ Customization
|
||||
appIcon = DEFAULT_ICON;
|
||||
deletedMark = "🧹";
|
||||
editedMark = tr::lng_edited(tr::now);
|
||||
recentStickersCount = 20;
|
||||
showGhostToggleInDrawer = true;
|
||||
// ~ Customization
|
||||
appIcon = DEFAULT_ICON;
|
||||
deletedMark = "🧹";
|
||||
editedMark = tr::lng_edited(tr::now);
|
||||
recentStickersCount = 20;
|
||||
showGhostToggleInDrawer = true;
|
||||
|
||||
/*
|
||||
* showPeerId = 0 means no ID shown
|
||||
* showPeerId = 1 means ID shown as for Telegram API devs
|
||||
* showPeerId = 2 means ID shown as for Bot API devs (-100)
|
||||
*/
|
||||
showPeerId = 2;
|
||||
/*
|
||||
* showPeerId = 0 means no ID shown
|
||||
* showPeerId = 1 means ID shown as for Telegram API devs
|
||||
* showPeerId = 2 means ID shown as for Bot API devs (-100)
|
||||
*/
|
||||
showPeerId = 2;
|
||||
|
||||
hideAllChatsFolder = false;
|
||||
showMessageSeconds = false;
|
||||
hideAllChatsFolder = false;
|
||||
showMessageSeconds = false;
|
||||
|
||||
// ~ Confirmations
|
||||
stickerConfirmation = false;
|
||||
gifConfirmation = false;
|
||||
voiceConfirmation = false;
|
||||
}
|
||||
// ~ Confirmations
|
||||
stickerConfirmation = false;
|
||||
gifConfirmation = false;
|
||||
voiceConfirmation = false;
|
||||
}
|
||||
|
||||
bool sendReadMessages;
|
||||
bool sendReadStories;
|
||||
bool sendOnlinePackets;
|
||||
bool sendUploadProgress;
|
||||
bool sendOfflinePacketAfterOnline;
|
||||
bool markReadAfterSend;
|
||||
bool useScheduledMessages;
|
||||
bool saveDeletedMessages;
|
||||
bool saveMessagesHistory;
|
||||
bool disableAds;
|
||||
bool disableStories;
|
||||
bool localPremium;
|
||||
bool copyUsernameAsLink;
|
||||
QString appIcon;
|
||||
QString deletedMark;
|
||||
QString editedMark;
|
||||
int recentStickersCount;
|
||||
bool showGhostToggleInDrawer;
|
||||
int showPeerId;
|
||||
bool hideAllChatsFolder;
|
||||
bool showMessageSeconds;
|
||||
bool stickerConfirmation;
|
||||
bool gifConfirmation;
|
||||
bool voiceConfirmation;
|
||||
bool sendReadMessages;
|
||||
bool sendReadStories;
|
||||
bool sendOnlinePackets;
|
||||
bool sendUploadProgress;
|
||||
bool sendOfflinePacketAfterOnline;
|
||||
bool markReadAfterSend;
|
||||
bool useScheduledMessages;
|
||||
bool saveDeletedMessages;
|
||||
bool saveMessagesHistory;
|
||||
bool disableAds;
|
||||
bool disableStories;
|
||||
bool localPremium;
|
||||
bool copyUsernameAsLink;
|
||||
QString appIcon;
|
||||
QString deletedMark;
|
||||
QString editedMark;
|
||||
int recentStickersCount;
|
||||
bool showGhostToggleInDrawer;
|
||||
int showPeerId;
|
||||
bool hideAllChatsFolder;
|
||||
bool showMessageSeconds;
|
||||
bool stickerConfirmation;
|
||||
bool gifConfirmation;
|
||||
bool voiceConfirmation;
|
||||
|
||||
public:
|
||||
void set_sendReadMessages(bool val);
|
||||
public:
|
||||
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(
|
||||
AyuGramSettings,
|
||||
sendReadMessages,
|
||||
sendReadStories,
|
||||
sendOnlinePackets,
|
||||
sendUploadProgress,
|
||||
sendOfflinePacketAfterOnline,
|
||||
markReadAfterSend,
|
||||
useScheduledMessages,
|
||||
saveDeletedMessages,
|
||||
saveMessagesHistory,
|
||||
disableAds,
|
||||
disableStories,
|
||||
localPremium,
|
||||
copyUsernameAsLink,
|
||||
appIcon,
|
||||
deletedMark,
|
||||
editedMark,
|
||||
recentStickersCount,
|
||||
showGhostToggleInDrawer,
|
||||
showPeerId,
|
||||
showMessageSeconds,
|
||||
hideAllChatsFolder,
|
||||
stickerConfirmation,
|
||||
gifConfirmation,
|
||||
voiceConfirmation
|
||||
);
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
|
||||
AyuGramSettings,
|
||||
sendReadMessages,
|
||||
sendReadStories,
|
||||
sendOnlinePackets,
|
||||
sendUploadProgress,
|
||||
sendOfflinePacketAfterOnline,
|
||||
markReadAfterSend,
|
||||
useScheduledMessages,
|
||||
saveDeletedMessages,
|
||||
saveMessagesHistory,
|
||||
disableAds,
|
||||
disableStories,
|
||||
localPremium,
|
||||
copyUsernameAsLink,
|
||||
appIcon,
|
||||
deletedMark,
|
||||
editedMark,
|
||||
recentStickersCount,
|
||||
showGhostToggleInDrawer,
|
||||
showPeerId,
|
||||
showMessageSeconds,
|
||||
hideAllChatsFolder,
|
||||
stickerConfirmation,
|
||||
gifConfirmation,
|
||||
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
|
||||
{
|
||||
void setAllowSendReadPacket(bool val, int resetAfter)
|
||||
{
|
||||
allowSendReadPacket.val = val;
|
||||
allowSendReadPacket.resetAfter = resetAfter;
|
||||
}
|
||||
|
||||
bool getAllowSendPacket()
|
||||
{
|
||||
auto settings = &AyuSettings::getInstance();
|
||||
return settings->sendReadMessages || processVariable(allowSendReadPacket);
|
||||
}
|
||||
void setAllowSendReadPacket(bool val, int resetAfter)
|
||||
{
|
||||
allowSendReadPacket.val = val;
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ayu_settings.h"
|
||||
|
||||
namespace AyuState
|
||||
{
|
||||
namespace
|
||||
{
|
||||
class AyuStateVariable
|
||||
{
|
||||
public:
|
||||
bool val;
|
||||
int resetAfter;
|
||||
};
|
||||
|
||||
AyuStateVariable allowSendReadPacket;
|
||||
namespace
|
||||
{
|
||||
|
||||
bool processVariable(AyuStateVariable& variable)
|
||||
{
|
||||
if (variable.resetAfter == -1)
|
||||
{
|
||||
return variable.val;
|
||||
}
|
||||
class AyuStateVariable
|
||||
{
|
||||
public:
|
||||
bool val;
|
||||
int resetAfter;
|
||||
};
|
||||
|
||||
variable.resetAfter -= 1;
|
||||
auto val = variable.val;
|
||||
AyuStateVariable allowSendReadPacket;
|
||||
|
||||
if (variable.resetAfter == 0)
|
||||
{
|
||||
variable.val = false;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
bool processVariable(AyuStateVariable &variable)
|
||||
{
|
||||
if (variable.resetAfter == -1) {
|
||||
return variable.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 "ayu/libs/sqlite/sqlite_orm.h"
|
||||
#include "ayu/utils/telegram_helpers.h"
|
||||
|
||||
using namespace sqlite_orm;
|
||||
auto storage = make_storage(
|
||||
"ayugram.db",
|
||||
make_table(
|
||||
"editedmessage",
|
||||
make_column("userId", &EditedMessage::get_user_id, &EditedMessage::set_user_id),
|
||||
make_column("dialogId", &EditedMessage::get_dialog_id, &EditedMessage::set_dialog_id),
|
||||
make_column("groupedId", &EditedMessage::get_grouped_id, &EditedMessage::set_grouped_id),
|
||||
make_column("peerId", &EditedMessage::get_peer_id, &EditedMessage::set_peer_id),
|
||||
make_column("fromId", &EditedMessage::get_from_id, &EditedMessage::set_from_id),
|
||||
make_column("topicId", &EditedMessage::get_topic_id, &EditedMessage::set_topic_id),
|
||||
make_column("messageId", &EditedMessage::get_message_id, &EditedMessage::set_message_id),
|
||||
make_column("date", &EditedMessage::get_date, &EditedMessage::set_date),
|
||||
make_column("flags", &EditedMessage::get_flags, &EditedMessage::set_flags),
|
||||
make_column("editDate", &EditedMessage::get_edit_date, &EditedMessage::set_edit_date),
|
||||
make_column("editHide", &EditedMessage::is_edit_hide, &EditedMessage::set_edit_hide),
|
||||
make_column("out", &EditedMessage::is_out, &EditedMessage::set_out),
|
||||
make_column("entityCreateDate", &EditedMessage::get_entity_create_date, &EditedMessage::set_entity_create_date),
|
||||
make_column("text", &EditedMessage::get_text, &EditedMessage::set_text),
|
||||
make_column("textEntities", &EditedMessage::get_text_entities, &EditedMessage::set_text_entities),
|
||||
make_column("mediaPath", &EditedMessage::get_media_path, &EditedMessage::set_media_path),
|
||||
make_column("documentType", &EditedMessage::get_document_type, &EditedMessage::set_document_type),
|
||||
make_column("documentSerialized", &EditedMessage::get_document_serialized,
|
||||
&EditedMessage::set_document_serialized),
|
||||
make_column("thumbsSerialized", &EditedMessage::get_thumbs_serialized, &EditedMessage::set_thumbs_serialized),
|
||||
make_column("documentAttributesSerialized", &EditedMessage::get_document_attributes_serialized,
|
||||
&EditedMessage::set_document_attributes_serialized),
|
||||
make_column("mimeType", &EditedMessage::get_mime_type, &EditedMessage::set_mime_type)
|
||||
),
|
||||
make_table(
|
||||
"deletedmessage",
|
||||
make_column("userId", &DeletedMessage::get_user_id, &DeletedMessage::set_user_id),
|
||||
make_column("dialogId", &DeletedMessage::get_dialog_id, &DeletedMessage::set_dialog_id),
|
||||
make_column("groupedId", &DeletedMessage::get_grouped_id, &DeletedMessage::set_grouped_id),
|
||||
make_column("peerId", &DeletedMessage::get_peer_id, &DeletedMessage::set_peer_id),
|
||||
make_column("fromId", &DeletedMessage::get_from_id, &DeletedMessage::set_from_id),
|
||||
make_column("topicId", &DeletedMessage::get_topic_id, &DeletedMessage::set_topic_id),
|
||||
make_column("messageId", &DeletedMessage::get_message_id, &DeletedMessage::set_message_id),
|
||||
make_column("date", &DeletedMessage::get_date, &DeletedMessage::set_date),
|
||||
make_column("flags", &DeletedMessage::get_flags, &DeletedMessage::set_flags),
|
||||
make_column("editDate", &DeletedMessage::get_edit_date, &DeletedMessage::set_edit_date),
|
||||
make_column("editHide", &DeletedMessage::is_edit_hide, &DeletedMessage::set_edit_hide),
|
||||
make_column("out", &DeletedMessage::is_out, &DeletedMessage::set_out),
|
||||
make_column("entityCreateDate", &DeletedMessage::get_entity_create_date,
|
||||
&DeletedMessage::set_entity_create_date),
|
||||
make_column("text", &DeletedMessage::get_text, &DeletedMessage::set_text),
|
||||
make_column("textEntities", &DeletedMessage::get_text_entities, &DeletedMessage::set_text_entities),
|
||||
make_column("mediaPath", &DeletedMessage::get_media_path, &DeletedMessage::set_media_path),
|
||||
make_column("documentType", &DeletedMessage::get_document_type, &DeletedMessage::set_document_type),
|
||||
make_column("documentSerialized", &DeletedMessage::get_document_serialized,
|
||||
&DeletedMessage::set_document_serialized),
|
||||
make_column("thumbsSerialized", &DeletedMessage::get_thumbs_serialized, &DeletedMessage::set_thumbs_serialized),
|
||||
make_column("documentAttributesSerialized", &DeletedMessage::get_document_attributes_serialized,
|
||||
&DeletedMessage::set_document_attributes_serialized),
|
||||
make_column("mimeType", &DeletedMessage::get_mime_type, &DeletedMessage::set_mime_type)
|
||||
)
|
||||
|
||||
auto storage = make_storage("ayugram.db",
|
||||
make_table("DeletedMessage",
|
||||
make_column("userId", &DeletedMessage::userId),
|
||||
make_column("dialogId", &DeletedMessage::dialogId),
|
||||
make_column("groupedId", &DeletedMessage::groupedId),
|
||||
make_column("peerId", &DeletedMessage::peerId),
|
||||
make_column("fromId", &DeletedMessage::fromId),
|
||||
make_column("topicId", &DeletedMessage::topicId),
|
||||
make_column("messageId", &DeletedMessage::messageId),
|
||||
make_column("date", &DeletedMessage::date),
|
||||
make_column("flags", &DeletedMessage::flags),
|
||||
make_column("editDate", &DeletedMessage::editDate),
|
||||
make_column("views", &DeletedMessage::views),
|
||||
make_column("fwdFlags", &DeletedMessage::fwdFlags),
|
||||
make_column("fwdFromId", &DeletedMessage::fwdFromId),
|
||||
make_column("fwdName", &DeletedMessage::fwdName),
|
||||
make_column("fwdDate", &DeletedMessage::fwdDate),
|
||||
make_column("fwdPostAuthor", &DeletedMessage::fwdPostAuthor),
|
||||
make_column("replyFlags", &DeletedMessage::replyFlags),
|
||||
make_column("replyMessageId", &DeletedMessage::replyMessageId),
|
||||
make_column("replyPeerId", &DeletedMessage::replyPeerId),
|
||||
make_column("replyTopId", &DeletedMessage::replyTopId),
|
||||
make_column("replyForumTopic", &DeletedMessage::replyForumTopic),
|
||||
make_column("entityCreateDate", &DeletedMessage::entityCreateDate),
|
||||
make_column("text", &DeletedMessage::text),
|
||||
make_column("textEntities", &DeletedMessage::textEntities),
|
||||
make_column("mediaPath", &DeletedMessage::mediaPath),
|
||||
make_column("hqThumbPath", &DeletedMessage::hqThumbPath),
|
||||
make_column("documentType", &DeletedMessage::documentType),
|
||||
make_column("documentSerialized", &DeletedMessage::documentSerialized),
|
||||
make_column("thumbsSerialized", &DeletedMessage::thumbsSerialized),
|
||||
make_column("documentAttributesSerialized",
|
||||
&DeletedMessage::documentAttributesSerialized),
|
||||
make_column("mimeType", &DeletedMessage::mimeType)
|
||||
),
|
||||
make_table("EditedMessage",
|
||||
make_column("userId", &EditedMessage::userId),
|
||||
make_column("dialogId", &EditedMessage::dialogId),
|
||||
make_column("groupedId", &EditedMessage::groupedId),
|
||||
make_column("peerId", &EditedMessage::peerId),
|
||||
make_column("fromId", &EditedMessage::fromId),
|
||||
make_column("topicId", &EditedMessage::topicId),
|
||||
make_column("messageId", &EditedMessage::messageId),
|
||||
make_column("date", &EditedMessage::date),
|
||||
make_column("flags", &EditedMessage::flags),
|
||||
make_column("editDate", &EditedMessage::editDate),
|
||||
make_column("views", &EditedMessage::views),
|
||||
make_column("fwdFlags", &EditedMessage::fwdFlags),
|
||||
make_column("fwdFromId", &EditedMessage::fwdFromId),
|
||||
make_column("fwdName", &EditedMessage::fwdName),
|
||||
make_column("fwdDate", &EditedMessage::fwdDate),
|
||||
make_column("fwdPostAuthor", &EditedMessage::fwdPostAuthor),
|
||||
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
|
||||
{
|
||||
void initialize()
|
||||
{
|
||||
storage.sync_schema();
|
||||
|
||||
storage.begin_transaction();
|
||||
storage.commit();
|
||||
}
|
||||
void initialize()
|
||||
{
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "entities.h"
|
||||
|
@ -13,9 +12,11 @@
|
|||
|
||||
namespace AyuDatabase
|
||||
{
|
||||
void initialize();
|
||||
|
||||
void addEditedMessage(const EditedMessage& message);
|
||||
std::vector<EditedMessage> getEditedMessages(ID userId, ID dialogId, ID messageId);
|
||||
bool hasRevisions(ID userId, ID dialogId, ID messageId);
|
||||
void initialize();
|
||||
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
{
|
||||
public:
|
||||
ID fakeId;
|
||||
ID userId;
|
||||
ID dialogId;
|
||||
ID groupedId;
|
||||
|
@ -24,449 +23,43 @@ public:
|
|||
ID topicId;
|
||||
int messageId;
|
||||
int date;
|
||||
|
||||
int flags;
|
||||
|
||||
int editDate;
|
||||
bool editHide;
|
||||
bool out;
|
||||
|
||||
int views;
|
||||
int fwdFlags;
|
||||
ID fwdFromId;
|
||||
std::string fwdName;
|
||||
int fwdDate;
|
||||
std::string fwdPostAuthor;
|
||||
int replyFlags;
|
||||
int replyMessageId;
|
||||
ID replyPeerId;
|
||||
int replyTopId;
|
||||
bool replyForumTopic;
|
||||
int entityCreateDate;
|
||||
|
||||
std::string text; // plain text
|
||||
std::string textEntities; // TL serialized
|
||||
std::string mediaPath; // full path
|
||||
int documentType; // see DOCUMENT_TYPE_*
|
||||
std::string documentSerialized; // for sticker; TL serialized
|
||||
std::string thumbsSerialized; // for video/etc.; TL serialized
|
||||
std::string documentAttributesSerialized; // for video/voice/etc.; TL serialized
|
||||
std::string text;
|
||||
std::vector<char> textEntities;
|
||||
std::string mediaPath;
|
||||
std::string hqThumbPath;
|
||||
int documentType;
|
||||
std::vector<char> documentSerialized;
|
||||
std::vector<char> thumbsSerialized;
|
||||
std::vector<char> documentAttributesSerialized;
|
||||
std::string mimeType;
|
||||
};
|
||||
|
||||
class DeletedMessage : public AyuMessageBase
|
||||
using DeletedMessage = AyuMessageBase<struct DeletedMessageTag>;
|
||||
using EditedMessage = AyuMessageBase<struct EditedMessageTag>;
|
||||
|
||||
class DeletedDialog
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
ID fakeId;
|
||||
ID userId;
|
||||
ID dialogId;
|
||||
ID peerId;
|
||||
int topMessage;
|
||||
int lastMessageDate;
|
||||
int flags;
|
||||
int entityCreateDate;
|
||||
};
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace AyuFeatures::StreamerMode
|
||||
{
|
||||
bool isEnabled();
|
||||
void enable();
|
||||
void disable();
|
||||
void hideWidgetWindow(QWidget* widget);
|
||||
void showWidgetWindow(QWidget* widget);
|
||||
|
||||
bool isEnabled();
|
||||
void enable();
|
||||
void disable();
|
||||
void hideWidgetWindow(QWidget *widget);
|
||||
void showWidgetWindow(QWidget *widget);
|
||||
|
||||
}
|
||||
|
|
|
@ -14,30 +14,34 @@
|
|||
|
||||
namespace AyuFeatures::StreamerMode
|
||||
{
|
||||
bool isEnabledVal;
|
||||
|
||||
bool isEnabled()
|
||||
{
|
||||
return isEnabledVal;
|
||||
}
|
||||
bool isEnabledVal;
|
||||
|
||||
void enable()
|
||||
{
|
||||
isEnabledVal = true;
|
||||
}
|
||||
bool isEnabled()
|
||||
{
|
||||
return isEnabledVal;
|
||||
}
|
||||
|
||||
void disable()
|
||||
{
|
||||
isEnabledVal = false;
|
||||
}
|
||||
void enable()
|
||||
{
|
||||
isEnabledVal = true;
|
||||
}
|
||||
|
||||
void hideWidgetWindow(QWidget* widget) {
|
||||
void disable()
|
||||
{
|
||||
isEnabledVal = false;
|
||||
}
|
||||
|
||||
}
|
||||
void hideWidgetWindow(QWidget *widget)
|
||||
{
|
||||
|
||||
void showWidgetWindow(QWidget* widget) {
|
||||
}
|
||||
|
||||
void showWidgetWindow(QWidget *widget)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,40 +14,42 @@
|
|||
|
||||
namespace AyuFeatures::StreamerMode
|
||||
{
|
||||
bool isEnabledVal;
|
||||
|
||||
bool isEnabled()
|
||||
{
|
||||
return isEnabledVal;
|
||||
}
|
||||
bool isEnabledVal;
|
||||
|
||||
void enable()
|
||||
{
|
||||
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
||||
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
||||
bool isEnabled()
|
||||
{
|
||||
return isEnabledVal;
|
||||
}
|
||||
|
||||
isEnabledVal = true;
|
||||
}
|
||||
void enable()
|
||||
{
|
||||
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
||||
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
||||
|
||||
void disable()
|
||||
{
|
||||
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
||||
SetWindowDisplayAffinity(handle, WDA_NONE);
|
||||
isEnabledVal = true;
|
||||
}
|
||||
|
||||
isEnabledVal = false;
|
||||
}
|
||||
void disable()
|
||||
{
|
||||
auto handle = Core::App().activeWindow()->widget()->psHwnd();
|
||||
SetWindowDisplayAffinity(handle, WDA_NONE);
|
||||
|
||||
void hideWidgetWindow(QWidget* widget)
|
||||
{
|
||||
auto handle = reinterpret_cast<HWND>(widget->window()->winId());
|
||||
SetWindowDisplayAffinity(handle, WDA_EXCLUDEFROMCAPTURE);
|
||||
}
|
||||
isEnabledVal = false;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "ayu/ayu_constants.h"
|
||||
#include "ayu/database/ayu_database.h"
|
||||
#include "ayu/utils/ayu_mapper.h"
|
||||
#include "ayu/utils/telegram_helpers.h"
|
||||
|
||||
#include "base/unixtime.h"
|
||||
|
@ -18,87 +19,91 @@
|
|||
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "history/history_item_components.h"
|
||||
|
||||
#include "main/main_session.h"
|
||||
|
||||
namespace AyuMessages
|
||||
{
|
||||
std::optional<ayu_messages_controller> controller = std::nullopt;
|
||||
|
||||
void initialize()
|
||||
{
|
||||
if (controller.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::optional<ayu_messages_controller> controller = std::nullopt;
|
||||
|
||||
controller = ayu_messages_controller();
|
||||
void initialize()
|
||||
{
|
||||
if (controller.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ayu_messages_controller& getInstance()
|
||||
{
|
||||
initialize();
|
||||
return controller.value();
|
||||
}
|
||||
|
||||
void map(HistoryMessageEdition& edition, not_null<HistoryItem*> item, AyuMessageBase& message)
|
||||
{
|
||||
message.userId = item->history()->owner().session().userId().bare;
|
||||
message.dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||
message.groupedId = item->groupId().value;
|
||||
message.peerId = item->from()->id.value; // todo: ???
|
||||
message.fromId = item->from()->id.value;
|
||||
if (auto topic = item->history()->asTopic())
|
||||
{
|
||||
message.topicId = topic->rootId().bare;
|
||||
}
|
||||
message.messageId = item->id.bare;
|
||||
message.date = item->date();
|
||||
|
||||
// message.flags = todo:
|
||||
|
||||
message.editDate = edition.editDate;
|
||||
message.editHide = item->hideEditedBadge();
|
||||
message.out = item->out();
|
||||
message.entityCreateDate = base::unixtime::now(); // todo: rework
|
||||
|
||||
auto serializedText = serializeTextWithEntities(item);
|
||||
message.text = serializedText.first;
|
||||
message.textEntities = serializedText.second;
|
||||
|
||||
// todo:
|
||||
message.mediaPath = "/";
|
||||
message.documentType = DOCUMENT_TYPE_NONE;
|
||||
|
||||
// message.documentSerialized;
|
||||
// message.thumbsSerialized;
|
||||
// message.documentAttributesSerialized;
|
||||
// message.mimeType;
|
||||
}
|
||||
|
||||
void ayu_messages_controller::addEditedMessage(HistoryMessageEdition& edition, not_null<HistoryItem*> item)
|
||||
{
|
||||
EditedMessage message;
|
||||
map(edition, item, message);
|
||||
|
||||
AyuDatabase::addEditedMessage(message);
|
||||
}
|
||||
|
||||
std::vector<EditedMessage> ayu_messages_controller::getEditedMessages(HistoryItem* item)
|
||||
{
|
||||
auto userId = item->history()->owner().session().userId().bare;
|
||||
auto dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||
auto msgId = item->id.bare;
|
||||
|
||||
return AyuDatabase::getEditedMessages(userId, dialogId, msgId);
|
||||
}
|
||||
|
||||
bool ayu_messages_controller::hasRevisions(not_null<HistoryItem*> item)
|
||||
{
|
||||
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);
|
||||
}
|
||||
controller = ayu_messages_controller();
|
||||
}
|
||||
|
||||
ayu_messages_controller &getInstance()
|
||||
{
|
||||
initialize();
|
||||
return controller.value();
|
||||
}
|
||||
|
||||
void map(HistoryMessageEdition &edition, not_null<HistoryItem *> item, EditedMessage &message)
|
||||
{
|
||||
message.userId = item->history()->owner().session().userId().bare;
|
||||
message.dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||
message.groupedId = item->groupId().value;
|
||||
message.peerId = item->from()->id.value; // todo: ???
|
||||
message.fromId = item->from()->id.value;
|
||||
if (auto topic = item->history()->asTopic()) {
|
||||
message.topicId = topic->rootId().bare;
|
||||
}
|
||||
message.messageId = item->id.bare;
|
||||
message.date = item->date();
|
||||
message.flags = AyuMapper::mapItemFlagsToMTPFlags(item);
|
||||
|
||||
if (auto edited = item->Get<HistoryMessageEdited>()) {
|
||||
message.editDate = edited->date;
|
||||
} else {
|
||||
message.editDate = base::unixtime::now();
|
||||
}
|
||||
|
||||
message.views = item->viewsCount();
|
||||
message.entityCreateDate = base::unixtime::now(); // todo: rework
|
||||
|
||||
auto serializedText = serializeTextWithEntities(item);
|
||||
message.text = serializedText.first;
|
||||
// message.textEntities = serializedText.second;
|
||||
|
||||
// todo:
|
||||
message.mediaPath = "/";
|
||||
message.documentType = DOCUMENT_TYPE_NONE;
|
||||
|
||||
// message.documentSerialized;
|
||||
// message.thumbsSerialized;
|
||||
// message.documentAttributesSerialized;
|
||||
// message.mimeType;
|
||||
}
|
||||
|
||||
void ayu_messages_controller::addEditedMessage(HistoryMessageEdition &edition, not_null<HistoryItem *> item)
|
||||
{
|
||||
EditedMessage message;
|
||||
map(edition, item, message);
|
||||
|
||||
AyuDatabase::addEditedMessage(message);
|
||||
}
|
||||
|
||||
std::vector<EditedMessage> ayu_messages_controller::getEditedMessages(HistoryItem *item)
|
||||
{
|
||||
auto userId = item->history()->owner().session().userId().bare;
|
||||
auto dialogId = getDialogIdFromPeer(item->history()->peer);
|
||||
auto msgId = item->id.bare;
|
||||
|
||||
return AyuDatabase::getEditedMessages(userId, dialogId, msgId);
|
||||
}
|
||||
|
||||
bool ayu_messages_controller::hasRevisions(not_null<HistoryItem *> item)
|
||||
{
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ayu/database/entities.h"
|
||||
|
@ -13,13 +12,15 @@
|
|||
|
||||
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
|
||||
{
|
||||
std::optional<ayu_sync_controller> controller = std::nullopt;
|
||||
|
||||
bool isAgentDownloaded()
|
||||
{
|
||||
return std::filesystem::exists(AgentPath);
|
||||
std::optional<ayu_sync_controller> controller = std::nullopt;
|
||||
|
||||
bool isAgentDownloaded()
|
||||
{
|
||||
return std::filesystem::exists(AgentPath);
|
||||
}
|
||||
|
||||
bool isAgentRunning()
|
||||
{
|
||||
return isProcessRunning(AgentFilename);
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
if (controller.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool isAgentRunning()
|
||||
{
|
||||
return isProcessRunning(AgentFilename);
|
||||
controller = ayu_sync_controller();
|
||||
}
|
||||
|
||||
ayu_sync_controller &getInstance()
|
||||
{
|
||||
initialize();
|
||||
return controller.value();
|
||||
}
|
||||
|
||||
void ayu_sync_controller::initializeAgent()
|
||||
{
|
||||
if (!isAgentDownloaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
if (controller.has_value())
|
||||
{
|
||||
return;
|
||||
if (isAgentRunning()) {
|
||||
killProcess(AgentFilename);
|
||||
}
|
||||
|
||||
auto configPath = std::filesystem::absolute("./tdata/sync_preferences.json");
|
||||
auto process = nes::process{AgentPath, {configPath.string(), ""}, nes::process_options::none};
|
||||
process.detach();
|
||||
|
||||
std::thread receiverThread(&ayu_sync_controller::receiver, this);
|
||||
receiverThread.detach();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void ayu_sync_controller::syncRead(not_null<History *> history, MsgId untilId)
|
||||
{
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
SyncRead ev;
|
||||
ev.userId = history->owner().session().userId().bare;
|
||||
|
||||
ev.args.dialogId = getDialogIdFromPeer(history->peer);
|
||||
ev.args.untilId = untilId.bare;
|
||||
ev.args.unread = history->unreadCount();
|
||||
|
||||
pipe->send(ev);
|
||||
}
|
||||
|
||||
void ayu_sync_controller::receiver()
|
||||
{
|
||||
pipe = std::make_unique<ayu_pipe_wrapper>();
|
||||
pipe->connect();
|
||||
|
||||
LOG(("Pipe created"));
|
||||
|
||||
while (true) {
|
||||
auto p = pipe->receive();
|
||||
if (p == std::nullopt) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
initialize();
|
||||
return controller.value();
|
||||
if (type == "sync_force") {
|
||||
auto ev = p.get<SyncForce>();
|
||||
onSyncForce(ev);
|
||||
}
|
||||
|
||||
void ayu_sync_controller::initializeAgent()
|
||||
{
|
||||
if (!isAgentDownloaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAgentRunning())
|
||||
{
|
||||
killProcess(AgentFilename);
|
||||
}
|
||||
|
||||
auto configPath = std::filesystem::absolute("./tdata/sync_preferences.json");
|
||||
auto process = nes::process{AgentPath, {configPath.string(), ""}, nes::process_options::none};
|
||||
process.detach();
|
||||
|
||||
std::thread receiverThread(&ayu_sync_controller::receiver, this);
|
||||
receiverThread.detach();
|
||||
|
||||
initialized = true;
|
||||
else if (type == "sync_batch") {
|
||||
onSyncBatch(p);
|
||||
}
|
||||
|
||||
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);
|
||||
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::receiver()
|
||||
{
|
||||
pipe = std::make_unique<ayu_pipe_wrapper>();
|
||||
pipe->connect();
|
||||
void ayu_sync_controller::onSyncForce(SyncForce ev)
|
||||
{
|
||||
auto session = getSession(ev.userId);
|
||||
auto histories = session->data().chatsList();
|
||||
|
||||
LOG(("Pipe created"));
|
||||
SyncBatch readsBatchEvent;
|
||||
readsBatchEvent.userId = ev.userId;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto p = pipe->receive();
|
||||
if (p == std::nullopt)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
std::string s = p->dump();
|
||||
LOG(("[AyuSync] Received message: %1").arg(QString::fromStdString(s)));
|
||||
auto untilId = unreadElement ? unreadElement->data()->id.bare : history->lastMessage()->id.bare;
|
||||
|
||||
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)
|
||||
{
|
||||
LOG(("Invoking handler on %1").arg(p.dump().c_str()));
|
||||
pipe->send(readsBatchEvent);
|
||||
|
||||
auto userId = p["userId"].get<long>();
|
||||
auto type = p["type"].get<std::string>();
|
||||
// send finish event
|
||||
SyncForceFinish newEv;
|
||||
newEv.userId = ev.userId;
|
||||
|
||||
LOG(("userId: %1, type: %2").arg(userId).arg(type.c_str()));
|
||||
pipe->send(newEv);
|
||||
}
|
||||
|
||||
if (!accountExists(userId))
|
||||
{
|
||||
LOG(("Sync for unknown account: %1").arg(userId));
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == "sync_force")
|
||||
{
|
||||
auto ev = p.get<SyncForce>();
|
||||
onSyncForce(ev);
|
||||
}
|
||||
else if (type == "sync_batch")
|
||||
{
|
||||
onSyncBatch(p);
|
||||
}
|
||||
else if (type == "sync_read")
|
||||
{
|
||||
auto ev = p.get<SyncRead>();
|
||||
onSyncRead(ev);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(("Unknown sync type: %1").arg(type.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void ayu_sync_controller::onSyncForce(SyncForce ev)
|
||||
{
|
||||
auto session = getSession(ev.userId);
|
||||
auto histories = session->data().chatsList();
|
||||
|
||||
SyncBatch readsBatchEvent;
|
||||
readsBatchEvent.userId = ev.userId;
|
||||
|
||||
for (const auto& row : histories->indexed()->all())
|
||||
{
|
||||
if (const auto history = row->history())
|
||||
{
|
||||
auto dialogId = getDialogIdFromPeer(history->peer);
|
||||
|
||||
SyncRead readEv;
|
||||
readEv.userId = ev.userId;
|
||||
|
||||
history->calculateFirstUnreadMessage();
|
||||
auto unreadElement = history->firstUnreadMessage();
|
||||
|
||||
if (!unreadElement && history->unreadCount())
|
||||
{
|
||||
LOG(("No unread can be calculated for %1").arg(dialogId));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto untilId = unreadElement ? unreadElement->data()->id.bare : history->lastMessage()->id.bare;
|
||||
|
||||
readEv.args.dialogId = dialogId;
|
||||
readEv.args.untilId = untilId;
|
||||
readEv.args.unread = history->unreadCount();
|
||||
|
||||
readsBatchEvent.args.events.emplace_back(readEv);
|
||||
}
|
||||
}
|
||||
|
||||
pipe->send(readsBatchEvent);
|
||||
|
||||
// send finish event
|
||||
SyncForceFinish newEv;
|
||||
newEv.userId = ev.userId;
|
||||
|
||||
pipe->send(newEv);
|
||||
}
|
||||
|
||||
void ayu_sync_controller::onSyncBatch(json ev)
|
||||
{
|
||||
for (auto& item : ev["args"]["events"])
|
||||
{
|
||||
invokeHandler(item);
|
||||
}
|
||||
}
|
||||
|
||||
void ayu_sync_controller::onSyncRead(SyncRead ev)
|
||||
{
|
||||
dispatchToMainThread([=]
|
||||
{
|
||||
auto session = getSession(ev.userId);
|
||||
auto history = getHistoryFromDialogId(ev.args.dialogId, session);
|
||||
|
||||
if (history->folderKnown())
|
||||
{
|
||||
history->inboxRead(ev.args.untilId, ev.args.unread);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(("Unknown dialog %1").arg(ev.args.dialogId));
|
||||
}
|
||||
});
|
||||
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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "models.h"
|
||||
|
@ -16,39 +15,44 @@
|
|||
|
||||
using json = nlohmann::json;
|
||||
|
||||
const std::string AgentFilename =
|
||||
#ifdef _WIN32
|
||||
"AyuSync.Agent.exe";
|
||||
|
||||
const std::string AgentFilename = "AyuSync.Agent.exe";
|
||||
|
||||
#else
|
||||
"AyuSync.Agent";
|
||||
|
||||
const std::string AgentFilename = "AyuSync.Agent";
|
||||
|
||||
#endif
|
||||
|
||||
const std::string AgentPath = "./AyuSync/" + AgentFilename;
|
||||
|
||||
namespace AyuSync
|
||||
{
|
||||
class ayu_sync_controller
|
||||
{
|
||||
public:
|
||||
void initializeAgent();
|
||||
|
||||
void syncRead(not_null<History*> history, MsgId untilId);
|
||||
class ayu_sync_controller
|
||||
{
|
||||
public:
|
||||
void initializeAgent();
|
||||
|
||||
void onSyncForce(SyncForce ev);
|
||||
void onSyncBatch(json ev);
|
||||
void onSyncRead(SyncRead ev);
|
||||
void syncRead(not_null<History *> history, MsgId untilId);
|
||||
|
||||
void invokeHandler(json p);
|
||||
void onSyncForce(SyncForce ev);
|
||||
void onSyncBatch(json ev);
|
||||
void onSyncRead(SyncRead ev);
|
||||
|
||||
private:
|
||||
void receiver();
|
||||
void invokeHandler(json p);
|
||||
|
||||
std::unique_ptr<ayu_pipe_wrapper> pipe;
|
||||
bool initialized;
|
||||
};
|
||||
private:
|
||||
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
|
||||
|
||||
#include "ayu/libs/json.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ayu/libs/json.hpp"
|
||||
#include "ayu/database/entities.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
@ -30,7 +35,41 @@ public:
|
|||
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
|
||||
|
@ -49,50 +88,53 @@ public:
|
|||
int unread;
|
||||
};
|
||||
|
||||
SyncReadArgs args;
|
||||
SyncReadArgs args{};
|
||||
};
|
||||
|
||||
class SyncForce : public SyncEvent
|
||||
class SyncDeletedMessage : public SyncEvent
|
||||
{
|
||||
public:
|
||||
explicit SyncForce()
|
||||
explicit SyncDeletedMessage()
|
||||
{
|
||||
type = "sync_force";
|
||||
type = "sync_deleted_message";
|
||||
}
|
||||
|
||||
class SyncForceArgs
|
||||
class SyncDeletedMessageArgs
|
||||
{
|
||||
public:
|
||||
int fromDate;
|
||||
json message;
|
||||
};
|
||||
|
||||
SyncForceArgs args;
|
||||
SyncDeletedMessageArgs args{};
|
||||
};
|
||||
|
||||
class SyncForceFinish : public SyncEvent
|
||||
class SyncEditedMessage : public SyncEvent
|
||||
{
|
||||
public:
|
||||
explicit SyncForceFinish()
|
||||
explicit SyncEditedMessage()
|
||||
{
|
||||
type = "sync_force_finish";
|
||||
type = "sync_edited_message";
|
||||
}
|
||||
|
||||
class SyncForceFinishArgs
|
||||
class SyncEditedMessageArgs
|
||||
{
|
||||
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(SyncBatch::SyncBatchArgs, events)
|
||||
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, type, userId, args)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish::SyncForceFinishArgs, dummy)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncForceFinish, type, userId, args)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncRead::SyncReadArgs, dialogId, untilId, unread)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncRead, type, userId, args)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncDeletedMessage::SyncDeletedMessageArgs, message)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncDeletedMessage, type, userId, args)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEditedMessage::SyncEditedMessageArgs, message)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(SyncEditedMessage, type, userId, args)
|
||||
|
|
|
@ -26,14 +26,13 @@ void ayu_pipe_wrapper::send(json p)
|
|||
bit_converter::i32_to_bytes(length, false, lengthBuff);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
std::optional<json> ayu_pipe_wrapper::receive()
|
||||
{
|
||||
if (!is->is_open())
|
||||
{
|
||||
if (!is->is_open()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
@ -44,16 +43,14 @@ std::optional<json> ayu_pipe_wrapper::receive()
|
|||
|
||||
LOG(("ayu_pipe_wrapper::receive() length: %1").arg(length));
|
||||
|
||||
if (length <= 0)
|
||||
{
|
||||
if (length <= 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto sb = stringbuf();
|
||||
unsigned char buff[4096];
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
while (length > 0) {
|
||||
auto readSize = std::min(length, static_cast<int>(sizeof(buff)));
|
||||
is->read(buff, readSize);
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#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 <iostream>
|
||||
#include <locale>
|
||||
|
@ -12,31 +19,27 @@
|
|||
|
||||
// A function to check if a process is running by its name
|
||||
// Bing AI generated
|
||||
inline bool isProcessRunning(const std::string& name)
|
||||
inline bool isProcessRunning(const std::string &name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Create a snapshot of all processes
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (snapshot == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (snapshot == INVALID_HANDLE_VALUE) {
|
||||
std::cerr << "Failed to create snapshot\n";
|
||||
return false;
|
||||
}
|
||||
// Iterate over the processes and compare the names
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(entry);
|
||||
if (!Process32First(snapshot, &entry))
|
||||
{
|
||||
if (!Process32First(snapshot, &entry)) {
|
||||
std::cerr << "Failed to get first process\n";
|
||||
CloseHandle(snapshot);
|
||||
return false;
|
||||
}
|
||||
do
|
||||
{
|
||||
do {
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::string entry_name = converter.to_bytes(entry.szExeFile);
|
||||
if (name == entry_name)
|
||||
{
|
||||
if (name == entry_name) {
|
||||
// Found a match
|
||||
CloseHandle(snapshot);
|
||||
return true;
|
||||
|
@ -52,34 +55,29 @@ inline bool isProcessRunning(const std::string& name)
|
|||
}
|
||||
|
||||
// Copilot generated
|
||||
void killProcess(const std::string& name)
|
||||
void killProcess(const std::string &name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (snapshot == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (snapshot == INVALID_HANDLE_VALUE) {
|
||||
std::cerr << "Failed to create snapshot\n";
|
||||
return;
|
||||
}
|
||||
// Iterate over the processes and compare the names
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(entry);
|
||||
if (!Process32First(snapshot, &entry))
|
||||
{
|
||||
if (!Process32First(snapshot, &entry)) {
|
||||
std::cerr << "Failed to get first process\n";
|
||||
CloseHandle(snapshot);
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
do {
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::string entry_name = converter.to_bytes(entry.szExeFile);
|
||||
if (name == entry_name)
|
||||
{
|
||||
if (name == entry_name) {
|
||||
// Found a match
|
||||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
|
||||
if (hProcess != nullptr)
|
||||
{
|
||||
if (hProcess != nullptr) {
|
||||
TerminateProcess(hProcess, 9);
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
#include "ayu/ayu_settings.h"
|
||||
|
||||
static QString LAST_LOADED_NAME;
|
||||
|
||||
static QImage LAST_LOADED;
|
||||
|
||||
static QImage LAST_LOADED_NO_MARGIN;
|
||||
|
||||
void loadAppIco() {
|
||||
void loadAppIco()
|
||||
{
|
||||
auto settings = &AyuSettings::getInstance();
|
||||
|
||||
QString appDataPath = QDir::fromNativeSeparators(qgetenv("APPDATA"));
|
||||
|
@ -31,8 +34,7 @@ void loadAppIco() {
|
|||
void loadIcons()
|
||||
{
|
||||
auto settings = &AyuSettings::getInstance();
|
||||
if (LAST_LOADED_NAME != settings->appIcon)
|
||||
{
|
||||
if (LAST_LOADED_NAME != settings->appIcon) {
|
||||
LAST_LOADED_NAME = 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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
void loadAppIco();
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
|
||||
namespace AyuUi
|
||||
{
|
||||
std::unique_ptr<Lottie::Icon> getLottie(const QString& text)
|
||||
{
|
||||
// todo: some kind of mapping
|
||||
// Lottie::MakeIcon({.json = QString(), .sizeOverride = {24, 24}});
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Lottie::Icon> getLottie(const QString &text)
|
||||
{
|
||||
// todo: some kind of mapping
|
||||
// Lottie::MakeIcon({.json = QString(), .sizeOverride = {24, 24}});
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lottie/lottie_icon.h"
|
||||
|
||||
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
|
||||
{
|
||||
ConfirmationBox::ConfirmationBox(
|
||||
QWidget*,
|
||||
not_null<Window::SessionController*> controller) : _controller(controller)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void ConfirmationBox::prepare()
|
||||
{
|
||||
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
|
||||
|
||||
auto fullHeight = st::boxPadding.top()
|
||||
+ _text->height()
|
||||
+ st::boxPadding.bottom();
|
||||
|
||||
setDimensions(st::boxWidth, fullHeight);
|
||||
|
||||
addButton(tr::ayu_ReadConfirmationBoxActionText(), [=, this]
|
||||
{
|
||||
ReadAllPeers();
|
||||
closeBox();
|
||||
});
|
||||
addButton(tr::lng_cancel(), [=, this] { closeBox(); });
|
||||
}
|
||||
|
||||
void ConfirmationBox::resizeEvent(QResizeEvent* e)
|
||||
{
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
const auto& padding = st::boxPadding;
|
||||
_text->moveToLeft(padding.left(), padding.top());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
ConfirmationBox::ConfirmationBox(
|
||||
QWidget *,
|
||||
not_null<Window::SessionController *> controller)
|
||||
: _controller(controller)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void ConfirmationBox::prepare()
|
||||
{
|
||||
_text.create(this, tr::ayu_ReadConfirmationBoxQuestion(), st::boxLabel);
|
||||
|
||||
auto fullHeight = st::boxPadding.top()
|
||||
+ _text->height()
|
||||
+ st::boxPadding.bottom();
|
||||
|
||||
setDimensions(st::boxWidth, fullHeight);
|
||||
|
||||
addButton(tr::ayu_ReadConfirmationBoxActionText(), [=, this]
|
||||
{
|
||||
ReadAllPeers();
|
||||
closeBox();
|
||||
});
|
||||
addButton(tr::lng_cancel(), [=, this]
|
||||
{ closeBox(); });
|
||||
}
|
||||
|
||||
void ConfirmationBox::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
const auto &padding = st::boxPadding;
|
||||
_text->moveToLeft(padding.left(), padding.top());
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
#pragma once
|
||||
|
||||
#include "ui/layers/box_content.h"
|
||||
#include "window/window_main_menu.h"
|
||||
|
||||
namespace AyuUi
|
||||
{
|
||||
class ConfirmationBox : public Ui::BoxContent
|
||||
{
|
||||
public:
|
||||
ConfirmationBox(QWidget*, not_null<Window::SessionController*> controller);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
class ConfirmationBox : public Ui::BoxContent
|
||||
{
|
||||
public:
|
||||
ConfirmationBox(QWidget *, not_null<Window::SessionController *> controller);
|
||||
|
||||
void resizeEvent(QResizeEvent* e) override;
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
void ReadAllPeers();
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
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"
|
||||
|
||||
EditDeletedMarkBox::EditDeletedMarkBox(QWidget*) :
|
||||
EditDeletedMarkBox::EditDeletedMarkBox(QWidget *)
|
||||
:
|
||||
_text(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
|
@ -47,12 +48,16 @@ void EditDeletedMarkBox::prepare()
|
|||
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
|
||||
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_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 EditDeletedMarkBox::setInnerFocus()
|
||||
|
@ -62,26 +67,24 @@ void EditDeletedMarkBox::setInnerFocus()
|
|||
|
||||
void EditDeletedMarkBox::submit()
|
||||
{
|
||||
if (_text->getLastText().trimmed().isEmpty())
|
||||
{
|
||||
if (_text->getLastText().trimmed().isEmpty()) {
|
||||
_text->setFocus();
|
||||
_text->showError();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
void EditDeletedMarkBox::resizeEvent(QResizeEvent* e)
|
||||
void EditDeletedMarkBox::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_text->resize(
|
||||
width()
|
||||
- st::boxPadding.left()
|
||||
- st::newGroupInfoPadding.left()
|
||||
- st::boxPadding.right(),
|
||||
- st::boxPadding.left()
|
||||
- st::newGroupInfoPadding.left()
|
||||
- st::boxPadding.right(),
|
||||
_text->height());
|
||||
|
||||
const auto left = st::boxPadding.left() + st::newGroupInfoPadding.left();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/timer.h"
|
||||
|
@ -14,14 +13,14 @@
|
|||
class EditDeletedMarkBox : public Ui::BoxContent
|
||||
{
|
||||
public:
|
||||
EditDeletedMarkBox(QWidget*);
|
||||
EditDeletedMarkBox(QWidget *);
|
||||
|
||||
protected:
|
||||
void setInnerFocus() override;
|
||||
|
||||
void prepare() override;
|
||||
|
||||
void resizeEvent(QResizeEvent* e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void submit();
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
#include "ayu/ayu_settings.h"
|
||||
|
||||
EditEditedMarkBox::EditEditedMarkBox(QWidget*) :
|
||||
EditEditedMarkBox::EditEditedMarkBox(QWidget *)
|
||||
:
|
||||
_text(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
|
@ -37,7 +38,6 @@ EditEditedMarkBox::EditEditedMarkBox(QWidget*) :
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
void EditEditedMarkBox::prepare()
|
||||
{
|
||||
const auto defaultEditedMark = tr::lng_edited(tr::now);
|
||||
|
@ -48,14 +48,17 @@ void EditEditedMarkBox::prepare()
|
|||
newHeight += st::boxPadding.bottom() + st::contactPadding.bottom();
|
||||
setDimensions(st::boxWidth, newHeight);
|
||||
|
||||
addLeftButton(tr::ayu_BoxActionReset(), [=] { _text->setText(defaultEditedMark); });
|
||||
addButton(tr::lng_settings_save(), [=] { save(); });
|
||||
addButton(tr::lng_cancel(), [=] { closeBox(); });
|
||||
addLeftButton(tr::ayu_BoxActionReset(), [=]
|
||||
{ _text->setText(defaultEditedMark); });
|
||||
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()
|
||||
{
|
||||
_text->setFocusFast();
|
||||
|
@ -63,26 +66,24 @@ void EditEditedMarkBox::setInnerFocus()
|
|||
|
||||
void EditEditedMarkBox::submit()
|
||||
{
|
||||
if (_text->getLastText().trimmed().isEmpty())
|
||||
{
|
||||
if (_text->getLastText().trimmed().isEmpty()) {
|
||||
_text->setFocus();
|
||||
_text->showError();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
void EditEditedMarkBox::resizeEvent(QResizeEvent* e)
|
||||
void EditEditedMarkBox::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
BoxContent::resizeEvent(e);
|
||||
|
||||
_text->resize(
|
||||
width()
|
||||
- st::boxPadding.left()
|
||||
- st::newGroupInfoPadding.left()
|
||||
- st::boxPadding.right(),
|
||||
- st::boxPadding.left()
|
||||
- st::newGroupInfoPadding.left()
|
||||
- st::boxPadding.right(),
|
||||
_text->height());
|
||||
|
||||
const auto left = st::boxPadding.left() + st::newGroupInfoPadding.left();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/timer.h"
|
||||
|
@ -14,14 +13,14 @@
|
|||
class EditEditedMarkBox : public Ui::BoxContent
|
||||
{
|
||||
public:
|
||||
EditEditedMarkBox(QWidget*);
|
||||
EditEditedMarkBox(QWidget *);
|
||||
|
||||
protected:
|
||||
void setInnerFocus() override;
|
||||
|
||||
void prepare() override;
|
||||
|
||||
void resizeEvent(QResizeEvent* e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void submit();
|
||||
|
|
|
@ -20,59 +20,58 @@ using namespace Settings;
|
|||
|
||||
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()
|
||||
{
|
||||
_content.create(this);
|
||||
MessageHistoryBox::MessageHistoryBox(QWidget *, HistoryItem *item)
|
||||
: _content(this), _scroll(base::make_unique_q<Ui::ScrollArea>(this, st::boxScroll))
|
||||
{
|
||||
setupControls();
|
||||
addEditedMessagesToLayout(item);
|
||||
}
|
||||
|
||||
_content->resizeToWidth(st::boxWideWidth);
|
||||
_content->moveToLeft(0, 0);
|
||||
void MessageHistoryBox::setupControls()
|
||||
{
|
||||
_content.create(this);
|
||||
|
||||
_content->heightValue(
|
||||
) | start_to_stream(_contentHeight, _content->lifetime());
|
||||
_content->resizeToWidth(st::boxWideWidth);
|
||||
_content->moveToLeft(0, 0);
|
||||
|
||||
_scroll->setOwnedWidget(
|
||||
object_ptr<RpWidget>::fromRaw(_content));
|
||||
}
|
||||
_content->heightValue(
|
||||
) | start_to_stream(_contentHeight, _content->lifetime());
|
||||
|
||||
void MessageHistoryBox::resizeEvent(QResizeEvent* e)
|
||||
{
|
||||
_scroll->resize(width(), height() - st::boxPhotoPadding.top() - st::boxPadding.bottom());
|
||||
_scroll->move(0, st::boxPadding.top());
|
||||
_scroll->setOwnedWidget(
|
||||
object_ptr<RpWidget>::fromRaw(_content));
|
||||
}
|
||||
|
||||
if (_content)
|
||||
{
|
||||
_content->resize(_scroll->width(), _content->height());
|
||||
}
|
||||
}
|
||||
void MessageHistoryBox::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
_scroll->resize(width(), height() - st::boxPhotoPadding.top() - st::boxPadding.bottom());
|
||||
_scroll->move(0, st::boxPadding.top());
|
||||
|
||||
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);
|
||||
}
|
||||
if (_content) {
|
||||
_content->resize(_scroll->width(), _content->height());
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "history/history_item.h"
|
||||
|
@ -14,24 +13,26 @@
|
|||
|
||||
namespace AyuUi
|
||||
{
|
||||
class MessageHistoryBox : public Ui::BoxContent
|
||||
{
|
||||
public:
|
||||
MessageHistoryBox(QWidget*, HistoryItem* item);
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
class MessageHistoryBox : public Ui::BoxContent
|
||||
{
|
||||
public:
|
||||
MessageHistoryBox(QWidget *, HistoryItem *item);
|
||||
|
||||
void resizeEvent(QResizeEvent* e) override;
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
||||
private:
|
||||
void setupControls();
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
void addEditedMessagesToLayout(HistoryItem* item);
|
||||
private:
|
||||
void setupControls();
|
||||
|
||||
object_ptr<Ui::VerticalLayout> _content;
|
||||
const base::unique_qptr<Ui::ScrollArea> _scroll;
|
||||
void addEditedMessagesToLayout(HistoryItem *item);
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
const auto lifetime = box->lifetime().make_state<rpl::lifetime>();
|
||||
}, [&](auto &&)
|
||||
{
|
||||
const auto label = box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box.get(),
|
||||
v::text::take_marked(std::move(args.text)),
|
||||
args.labelStyle ? *args.labelStyle : st::boxLabel),
|
||||
st::boxPadding);
|
||||
if (args.labelFilter) {
|
||||
label->setClickHandlerFilter(std::move(args.labelFilter));
|
||||
}
|
||||
});
|
||||
|
||||
v::match(args.text, [](v::null_t)
|
||||
{
|
||||
}, [&](auto&&)
|
||||
{
|
||||
const auto label = box->addRow(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
box.get(),
|
||||
v::text::take_marked(std::move(args.text)),
|
||||
args.labelStyle ? *args.labelStyle : st::boxLabel),
|
||||
st::boxPadding);
|
||||
if (args.labelFilter)
|
||||
{
|
||||
label->setClickHandlerFilter(std::move(args.labelFilter));
|
||||
}
|
||||
});
|
||||
|
||||
const auto prepareCallback = [&](Ui::ConfirmBoxArgs::Callback& callback)
|
||||
const auto prepareCallback = [&](Ui::ConfirmBoxArgs::Callback &callback)
|
||||
{
|
||||
return [=, confirmed = std::move(callback)]()
|
||||
{
|
||||
return [=, confirmed = std::move(callback)]()
|
||||
{
|
||||
if (const auto callbackPtr = std::get_if<1>(&confirmed))
|
||||
{
|
||||
if (auto callback = (*callbackPtr))
|
||||
{
|
||||
callback();
|
||||
}
|
||||
if (const auto callbackPtr = std::get_if<1>(&confirmed)) {
|
||||
if (auto callback = (*callbackPtr)) {
|
||||
callback();
|
||||
}
|
||||
else if (const auto callbackPtr = std::get_if<2>(&confirmed))
|
||||
{
|
||||
if (auto callback = (*callbackPtr))
|
||||
{
|
||||
callback(crl::guard(weak, [=] { weak->closeBox(); }));
|
||||
}
|
||||
}
|
||||
else if (const auto callbackPtr = std::get_if<2>(&confirmed)) {
|
||||
if (auto callback = (*callbackPtr)) {
|
||||
callback(crl::guard(weak, [=]
|
||||
{ weak->closeBox(); }));
|
||||
}
|
||||
else if (weak)
|
||||
{
|
||||
weak->closeBox();
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (weak) {
|
||||
weak->closeBox();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const auto& defaultButtonStyle = box->getDelegate()->style().button;
|
||||
const auto &defaultButtonStyle = box->getDelegate()->style().button;
|
||||
|
||||
const auto confirmButton = box->addButton(
|
||||
v::text::take_plain(std::move(args.confirmText), tr::lng_box_ok()),
|
||||
[=, c = prepareCallback(args.confirmed)]()
|
||||
const auto confirmButton = box->addButton(
|
||||
v::text::take_plain(std::move(args.confirmText), tr::lng_box_ok()),
|
||||
[=, 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();
|
||||
c();
|
||||
}),
|
||||
args.cancelStyle ? *args.cancelStyle : defaultButtonStyle);
|
||||
|
||||
weak->closeBox();
|
||||
},
|
||||
args.confirmStyle ? *args.confirmStyle : defaultButtonStyle);
|
||||
box->events(
|
||||
) | start_with_next([=](not_null<QEvent*> e)
|
||||
box->boxClosing(
|
||||
) | start_with_next(crl::guard(cancelButton, [=]
|
||||
{
|
||||
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();
|
||||
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();
|
||||
}
|
||||
cancelButton->clicked(Qt::KeyboardModifiers(), Qt::LeftButton);
|
||||
}), *lifetime);
|
||||
}
|
||||
|
||||
object_ptr<Ui::GenericBox> MakeConfirmBox(Ui::ConfirmBoxArgs&& args)
|
||||
{
|
||||
return Box(VoiceConfirmBox, std::move(args));
|
||||
if (args.strictCancel) {
|
||||
lifetime->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
|
@ -13,10 +12,12 @@
|
|||
|
||||
namespace AyuUi
|
||||
{
|
||||
void VoiceConfirmBox(not_null<Ui::GenericBox*> box, Ui::ConfirmBoxArgs&& args);
|
||||
|
||||
[[nodiscard]] object_ptr<Ui::GenericBox> MakeConfirmBox(
|
||||
Ui::ConfirmBoxArgs&& args);
|
||||
void VoiceConfirmBox(not_null<Ui::GenericBox *> box, 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
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#include "context_menu.h"
|
||||
#include "ayu/ui/context_menu/context_menu.h"
|
||||
#include "lang_auto.h"
|
||||
#include "ayu/ayu_state.h"
|
||||
#include "ayu/database/ayu_database.h"
|
||||
#include "ayu/messages/ayu_messages_controller.h"
|
||||
#include "ayu/ui/boxes/message_history_box.h"
|
||||
|
||||
|
@ -17,46 +15,49 @@
|
|||
#include "styles/style_chat.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
|
||||
#include "ayu/ui/sections/edited/edited_log_section.h"
|
||||
|
||||
|
||||
namespace AyuUi
|
||||
{
|
||||
AyuPopupMenu::AyuPopupMenu(HistoryInner* parent)
|
||||
{
|
||||
_ayuSubMenu = std::make_unique<Ui::PopupMenu>(parent, st::popupMenuWithIcons);
|
||||
}
|
||||
|
||||
void AyuPopupMenu::addHistoryAction(HistoryItem* item)
|
||||
{
|
||||
if (AyuMessages::getInstance().hasRevisions(item))
|
||||
AyuPopupMenu::AyuPopupMenu(HistoryInner *parent)
|
||||
{
|
||||
_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), [=]
|
||||
{
|
||||
auto box = Box<MessageHistoryBox>(item);
|
||||
show(std::move(box));
|
||||
}, &st::menuIconInfo);
|
||||
}
|
||||
item->history()->session().tryResolveWindow()->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item));
|
||||
}, &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 history = item->history();
|
||||
_ayuSubMenu->addAction(tr::ayu_ContextHideMessage(tr::now), [=]()
|
||||
{
|
||||
const auto initSaveDeleted = settings->saveDeletedMessages;
|
||||
const auto initSaveDeleted = settings->saveDeletedMessages;
|
||||
|
||||
settings->set_keepDeletedMessages(false);
|
||||
history->destroyMessage(item);
|
||||
settings->set_keepDeletedMessages(initSaveDeleted);
|
||||
}, &st::menuIconClear);
|
||||
}
|
||||
settings->set_keepDeletedMessages(false);
|
||||
history->destroyMessage(item);
|
||||
settings->set_keepDeletedMessages(initSaveDeleted);
|
||||
}, &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();
|
||||
_ayuSubMenu->addAction(tr::ayu_ReadUntilMenuText(tr::now), [=]()
|
||||
{
|
||||
AyuState::setAllowSendReadPacket(true);
|
||||
history->session().data().histories().readInboxOnNewMessage(item);
|
||||
}, &st::menuIconShowInChat);
|
||||
}
|
||||
AyuState::setAllowSendReadPacket(true);
|
||||
history->session().data().histories().readInboxOnNewMessage(item);
|
||||
}, &st::menuIconShowInChat);
|
||||
}
|
||||
|
||||
} // namespace AyuUi
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
@ -78,22 +77,24 @@
|
|||
|
||||
#include "history/view/history_view_context_menu.h"
|
||||
|
||||
#include <ayu/ayu_settings.h>
|
||||
#include <styles/style_info.h>
|
||||
#include "ayu/ayu_settings.h"
|
||||
#include "styles/style_info.h"
|
||||
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#include "icon_picker.h"
|
||||
#include "ayu/ayu_settings.h"
|
||||
#include "core/application.h"
|
||||
|
@ -21,10 +20,9 @@
|
|||
#include "ayu/utils/windows_utils.h"
|
||||
#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.setPen(QPen(st::iconPreviewStroke, 2));
|
||||
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);
|
||||
}
|
||||
|
||||
IconPicker::IconPicker(QWidget* parent) : RpWidget(parent)
|
||||
IconPicker::IconPicker(QWidget *parent)
|
||||
: RpWidget(parent)
|
||||
{
|
||||
setMinimumSize(st::boxWidth, 72);
|
||||
}
|
||||
|
||||
void IconPicker::paintEvent(QPaintEvent* e)
|
||||
void IconPicker::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
Painter p(this);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
@ -55,30 +54,26 @@ void IconPicker::paintEvent(QPaintEvent* e)
|
|||
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 changed = false;
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (changed) {
|
||||
AyuSettings::save();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
|
@ -12,9 +11,9 @@
|
|||
class IconPicker : public Ui::RpWidget
|
||||
{
|
||||
public:
|
||||
IconPicker(QWidget* parent);
|
||||
IconPicker(QWidget *parent);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* e) override;
|
||||
void mousePressEvent(QMouseEvent* e) override;
|
||||
void paintEvent(QPaintEvent *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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/options.h"
|
||||
|
@ -14,54 +13,56 @@ class BoxContent;
|
|||
|
||||
namespace Window
|
||||
{
|
||||
class Controller;
|
||||
|
||||
class SessionController;
|
||||
class Controller;
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
extern const char kStreamerMode[];
|
||||
|
||||
extern base::options::toggle StreamerMode;
|
||||
|
||||
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:
|
||||
void AddPlatformOption(
|
||||
not_null<Window::SessionController*> window,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
base::options::option<bool>& option,
|
||||
rpl::producer<> resetClicks);
|
||||
[[nodiscard]] rpl::producer<QString> title() override;
|
||||
|
||||
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,
|
||||
not_null<Window::SessionController*> controller);
|
||||
void SetupAppIcon(not_null<Ui::VerticalLayout *> container);
|
||||
|
||||
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,
|
||||
not_null<Window::SessionController*> controller);
|
||||
void SetupSendConfirmations(not_null<Ui::VerticalLayout *> container);
|
||||
|
||||
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
|
||||
|
|
|
@ -13,26 +13,22 @@
|
|||
|
||||
constexpr auto kMaxChannelId = -1000000000000;
|
||||
|
||||
|
||||
QString IDString(not_null<PeerData*> peer)
|
||||
QString IDString(not_null<PeerData *> peer)
|
||||
{
|
||||
auto resultId = QString::number(peerIsUser(peer->id)
|
||||
? peerToUser(peer->id).bare
|
||||
: peerIsChat(peer->id)
|
||||
? peerToChat(peer->id).bare
|
||||
: peerIsChannel(peer->id)
|
||||
? peerToChannel(peer->id).bare
|
||||
: peer->id.value);
|
||||
? peerToUser(peer->id).bare
|
||||
: peerIsChat(peer->id)
|
||||
? peerToChat(peer->id).bare
|
||||
: peerIsChannel(peer->id)
|
||||
? peerToChannel(peer->id).bare
|
||||
: peer->id.value);
|
||||
|
||||
const auto settings = &AyuSettings::getInstance();
|
||||
if (settings->showPeerId == 2)
|
||||
{
|
||||
if (peer->isChannel())
|
||||
{
|
||||
if (settings->showPeerId == 2) {
|
||||
if (peer->isChannel()) {
|
||||
resultId = QString::number(peerToChannel(peer->id).bare - kMaxChannelId).prepend("-");
|
||||
}
|
||||
else if (peer->isChat())
|
||||
{
|
||||
else if (peer->isChat()) {
|
||||
resultId = resultId.prepend("-");
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +43,7 @@ QString IDString(MsgId topic_root_id)
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
// but be respectful and credit the original author.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
QString IDString(not_null<PeerData*> peer);
|
||||
QString IDString(not_null<PeerData *> peer);
|
||||
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);
|
||||
|
|
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"
|
||||
|
||||
|
||||
Main::Session* getSession(ID userId)
|
||||
Main::Session *getSession(ID userId)
|
||||
{
|
||||
for (const auto& [index, account] : Core::App().domain().accounts())
|
||||
{
|
||||
if (const auto session = account->maybeSession())
|
||||
{
|
||||
if (session->userId().bare == userId)
|
||||
{
|
||||
for (const auto &[index, account] : Core::App().domain().accounts()) {
|
||||
if (const auto session = account->maybeSession()) {
|
||||
if (session->userId().bare == userId) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
@ -54,62 +51,56 @@ void dispatchToMainThread(std::function<void()> callback)
|
|||
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));
|
||||
}
|
||||
|
||||
auto history = session->data().history(peerFromChannel(abs(dialogId)));
|
||||
if (history->folderKnown())
|
||||
{
|
||||
if (history->folderKnown()) {
|
||||
return history;
|
||||
}
|
||||
|
||||
return session->data().history(peerFromChat(abs(dialogId)));
|
||||
}
|
||||
|
||||
ID getDialogIdFromPeer(not_null<PeerData*> peer)
|
||||
ID getDialogIdFromPeer(not_null<PeerData *> peer)
|
||||
{
|
||||
auto peerId = peerIsUser(peer->id)
|
||||
? peerToUser(peer->id).bare
|
||||
: peerIsChat(peer->id)
|
||||
? peerToChat(peer->id).bare
|
||||
: peerIsChannel(peer->id)
|
||||
? peerToChannel(peer->id).bare
|
||||
: peer->id.value;
|
||||
? peerToUser(peer->id).bare
|
||||
: peerIsChat(peer->id)
|
||||
? peerToChat(peer->id).bare
|
||||
: peerIsChannel(peer->id)
|
||||
? peerToChannel(peer->id).bare
|
||||
: peer->id.value;
|
||||
|
||||
if (peer->isChannel() || peer->isChat())
|
||||
{
|
||||
if (peer->isChannel() || peer->isChat()) {
|
||||
peerId = -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("", "");
|
||||
}
|
||||
|
||||
auto textWithEntities = item->originalText();
|
||||
auto text = textWithEntities.text.toStdString();
|
||||
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, "");
|
||||
}
|
||||
|
||||
auto buff = mtpBuffer();
|
||||
for (auto entity : entities.v)
|
||||
{
|
||||
for (auto entity : entities.v) {
|
||||
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.
|
||||
//
|
||||
// Copyright @Radolyn, 2023
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ayu/sync/models.h"
|
||||
|
@ -14,9 +13,9 @@
|
|||
#include "main/main_domain.h"
|
||||
#include "main/main_session.h"
|
||||
|
||||
Main::Session* getSession(ID userId);
|
||||
Main::Session *getSession(ID userId);
|
||||
bool accountExists(ID userId);
|
||||
void dispatchToMainThread(std::function<void()> callback);
|
||||
not_null<History*> getHistoryFromDialogId(ID dialogId, Main::Session* session);
|
||||
ID getDialogIdFromPeer(not_null<PeerData*> peer);
|
||||
std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem*> item);
|
||||
not_null<History *> getHistoryFromDialogId(ID dialogId, Main::Session *session);
|
||||
ID getDialogIdFromPeer(not_null<PeerData *> peer);
|
||||
std::pair<std::string, std::string> serializeTextWithEntities(not_null<HistoryItem *> item);
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
#include <ShlObj_core.h>
|
||||
|
||||
void reloadAppIconFromTaskBar() {
|
||||
void reloadAppIconFromTaskBar()
|
||||
{
|
||||
QString appdata = QDir::fromNativeSeparators(qgetenv("APPDATA"));
|
||||
QString ayugramIconPath = appdata + "/AyuGram.ico";
|
||||
|
||||
|
@ -24,9 +25,9 @@ void reloadAppIconFromTaskBar() {
|
|||
IPersistFile *pPersistFile = NULL;
|
||||
|
||||
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
|
||||
(void **) &pShellLink);
|
||||
(void **)&pShellLink);
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = pShellLink->QueryInterface(IID_IPersistFile, (void **) &pPersistFile);
|
||||
hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
|
||||
if (SUCCEEDED(hr)) {
|
||||
WCHAR wszShortcutPath[MAX_PATH];
|
||||
shortcut.toWCharArray(wszShortcutPath);
|
||||
|
|
|
@ -80,6 +80,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ayu/database/ayu_database.h"
|
||||
#include "ayu/messages/ayu_messages_controller.h"
|
||||
#include "ayu/ui/boxes/message_history_box.h"
|
||||
#include "ayu/ui/sections/edited/edited_log_section.h"
|
||||
|
||||
namespace HistoryView {
|
||||
namespace {
|
||||
|
@ -1091,8 +1092,7 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
|||
{
|
||||
result->addAction(tr::ayu_EditsHistoryMenuText(tr::now), [=]
|
||||
{
|
||||
auto box = Box<AyuUi::MessageHistoryBox>(item);
|
||||
Ui::show(std::move(box));
|
||||
item->history()->session().tryResolveWindow()->showSection(std::make_shared<EditedLog::SectionMemento>(item->history()->peer, item));
|
||||
}, &st::menuIconInfo);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue