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

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

57
.clang-format Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -11,31 +11,24 @@
class CustomLangPack : public QObject
{
Q_OBJECT
Q_OBJECT
Q_DISABLE_COPY(CustomLangPack)
public:
static CustomLangPack *currentInstance();
static void initInstance();
static CustomLangPack *instance;
void fetchCustomLangPack(const QString &langPackId, const QString &langPackBaseId);
void loadDefaultLangFile();
void parseLangFile(QJsonDocument str);
public Q_SLOTS:
void fetchFinished();
void fetchError(QNetworkReply::NetworkError e);
private:
CustomLangPack();
~CustomLangPack() override = default;
QNetworkAccessManager networkManager;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,40 +6,26 @@
// Copyright @Radolyn, 2023
#include "edit_deleted_mark.h"
#include "base/random.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h"
#include "data/data_cloud_file.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "styles/style_widgets.h"
#include "ui/ui_utility.h"
#include "ui/unread_badge.h"
#include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/widgets/fields/special_fields.h"
#include <QtGui/QGuiApplication>
#include "storage/localstorage.h"
#include "ayu/ayu_settings.h"
EditDeletedMarkBox::EditDeletedMarkBox(QWidget *)
:
_text(
: _text(
this,
st::defaultInputField,
tr::ayu_DeletedMarkText(),
AyuSettings::getInstance().deletedMark)
{
AyuSettings::getInstance().deletedMark) {
}
void EditDeletedMarkBox::prepare()
{
void EditDeletedMarkBox::prepare() {
const auto defaultDeletedMark = "🧹";
auto newHeight = st::contactPadding.top() + _text->height();
@ -48,53 +34,59 @@ 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();
});
const auto submitted = [=]
{ submit(); };
{
submit();
};
_text->submits(
) | rpl::start_with_next(submitted, _text->lifetime());
}
void EditDeletedMarkBox::setInnerFocus()
{
void EditDeletedMarkBox::setInnerFocus() {
_text->setFocusFast();
}
void EditDeletedMarkBox::submit()
{
void EditDeletedMarkBox::submit() {
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();
_text->moveToLeft(left, st::contactPadding.top());
}
void EditDeletedMarkBox::save()
{
void EditDeletedMarkBox::save() {
const auto settings = &AyuSettings::getInstance();
settings->set_deletedMark(_text->getLastText());
AyuSettings::save();

View file

@ -8,7 +8,6 @@
#include "base/timer.h"
#include "boxes/abstract_box.h"
#include "mtproto/sender.h"
class EditDeletedMarkBox : public Ui::BoxContent
{
@ -17,14 +16,11 @@ public:
protected:
void setInnerFocus() override;
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private:
void submit();
void save();
object_ptr<Ui::InputField> _text;

View file

@ -6,40 +6,26 @@
// Copyright @Radolyn, 2023
#include "edit_edited_mark.h"
#include "base/random.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/premium_limits_box.h"
#include "data/data_cloud_file.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "styles/style_boxes.h"
#include "styles/style_layers.h"
#include "styles/style_widgets.h"
#include "ui/ui_utility.h"
#include "ui/unread_badge.h"
#include "ui/controls/userpic_button.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/fields/input_field.h"
#include "ui/widgets/fields/special_fields.h"
#include <QtGui/QGuiApplication>
#include "storage/localstorage.h"
#include "ayu/ayu_settings.h"
EditEditedMarkBox::EditEditedMarkBox(QWidget *)
:
_text(
: _text(
this,
st::defaultInputField,
tr::ayu_EditedMarkText(),
AyuSettings::getInstance().editedMark)
{
AyuSettings::getInstance().editedMark) {
}
void EditEditedMarkBox::prepare()
{
void EditEditedMarkBox::prepare() {
const auto defaultEditedMark = tr::lng_edited(tr::now);
auto newHeight = st::contactPadding.top() + _text->height();
@ -48,52 +34,58 @@ 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();
});
const auto submitted = [=]
{ submit(); };
{
submit();
};
_text->submits(
) | rpl::start_with_next(submitted, _text->lifetime());
}
void EditEditedMarkBox::setInnerFocus()
{
void EditEditedMarkBox::setInnerFocus() {
_text->setFocusFast();
}
void EditEditedMarkBox::submit()
{
void EditEditedMarkBox::submit() {
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();
_text->moveToLeft(left, st::contactPadding.top());
}
void EditEditedMarkBox::save()
{
void EditEditedMarkBox::save() {
const auto settings = &AyuSettings::getInstance();
settings->set_editedMark(_text->getLastText());
AyuSettings::save();

View file

@ -17,14 +17,11 @@ public:
protected:
void setInnerFocus() override;
void prepare() override;
void resizeEvent(QResizeEvent *e) override;
private:
void submit();
void save();
object_ptr<Ui::InputField> _text;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,8 +9,7 @@
#include "ui/layers/box_content.h"
#include "window/window_main_menu.h"
namespace AyuUi
{
namespace AyuUi {
class ServerReadConfirmationBox : public Ui::BoxContent
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,95 +6,17 @@
// Copyright @Radolyn, 2023
#pragma once
#include "mainwindow.h"
#include "base/call_delayed.h"
#include "base/unixtime.h"
#include "base/platform/base_platform_info.h"
#include "base/qt/qt_common_adapters.h"
#include "base/qt/qt_key_modifiers.h"
#include "boxes/about_sponsored_box.h"
#include "boxes/delete_messages_box.h"
#include "boxes/premium_preview_box.h"
#include "boxes/report_messages_box.h"
#include "boxes/sticker_set_box.h"
#include "boxes/translate_box.h"
#include "chat_helpers/emoji_interactions.h"
#include "chat_helpers/message_field.h"
#include "core/application.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_document.h"
#include "data/data_file_click_handler.h"
#include "data/data_file_origin.h"
#include "data/data_forum_topic.h"
#include "data/data_histories.h"
#include "data/data_media_types.h"
#include "data/data_message_reactions.h"
#include "data/data_peer_values.h"
#include "data/data_photo.h"
#include "data/data_photo_media.h"
#include "data/data_poll.h"
#include "data/data_session.h"
#include "data/data_sponsored_messages.h"
#include "data/data_user.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/ui/dialogs_video_userpic.h"
#include "history/history_inner_widget.h"
#include "history/history_widget.h"
#include "history/view/history_view_translate_tracker.h"
#include "lang/lang_keys.h"
#include "layout/layout_selection.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "main/session/send_as_peers.h"
#include "menu/menu_item_download_files.h"
#include "settings/settings_premium.h"
#include "styles/style_chat.h"
#include "styles/style_menu_icons.h"
#include "styles/style_window.h" // st::windowMinWidth
#include "ui/cached_round_corners.h"
#include "ui/inactive_press.h"
#include "ui/painter.h"
#include "ui/ui_utility.h"
#include "ui/boxes/report_box.h"
#include "ui/controls/delete_message_context_action.h"
#include "ui/controls/who_reacted_context_action.h"
#include "ui/effects/message_sending_animation_controller.h"
#include "ui/effects/path_shift_gradient.h"
#include "ui/effects/reaction_fly_animation.h"
#include "ui/image/image.h"
#include "ui/layers/generic_box.h"
#include "ui/text/text_entity.h"
#include "ui/text/text_options.h"
#include "ui/widgets/popup_menu.h"
#include "window/notifications_manager.h"
#include "window/window_adaptive.h"
#include "window/window_controller.h"
#include "window/window_controller.h"
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
#include "history/view/history_view_context_menu.h"
#include "ayu/ayu_settings.h"
#include "ayu/utils/qt_key_modifiers_extended.h"
#include "styles/style_info.h"
namespace AyuUi
{
namespace AyuUi {
bool needToShowItem(int state);
void AddHistoryAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddHideMessageAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddUserMessagesAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddMessageDetailsAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
void AddReadUntilAction(not_null<Ui::PopupMenu *> menu, HistoryItem *item);
}

View file

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

View file

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

View file

@ -6,25 +6,23 @@
// Copyright @Radolyn, 2023
#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 "base/timer.h"
#include "history/view/history_view_element.h"
#include "menu/menu_antispam_validator.h"
#include "mtproto/sender.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
{
namespace Main {
class Session;
} // namespace Main
namespace HistoryView
{
namespace HistoryView {
class Element;
struct TextState;
struct StateRequest;
@ -32,20 +30,17 @@ enum class CursorState : char;
enum class PointState : char;
} // namespace HistoryView
namespace Ui
{
namespace Ui {
class PopupMenu;
class ChatStyle;
struct PeerUserpicView;
} // namespace Ui
namespace Window
{
namespace Window {
class SessionController;
} // namespace Window
namespace EditedLog
{
namespace EditedLog {
class SectionMemento;
@ -60,23 +55,21 @@ public:
not_null<HistoryItem *> item);
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] not_null<Ui::ChatTheme *> theme() const
{
[[nodiscard]] not_null<Ui::ChatTheme *> theme() const {
return _theme.get();
}
[[nodiscard]] rpl::producer<int> scrollToSignal() const;
[[nodiscard]] not_null<PeerData *> channel() 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)
{
void resizeToWidth(int newWidth, int minHeight) {
_minHeight = minHeight;
return TWidget::resizeToWidth(newWidth);
}
@ -161,11 +154,13 @@ protected:
private:
using Element = HistoryView::Element;
enum class Direction
{
Up,
Down,
};
enum class MouseAction
{
None,
@ -173,11 +168,13 @@ private:
Dragging,
Selecting,
};
enum class EnumItemsDirection
{
TopToBottom,
BottomToTop,
};
using TextState = HistoryView::TextState;
using CursorState = HistoryView::CursorState;
using PointState = HistoryView::PointState;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,20 +6,17 @@
// Copyright @Radolyn, 2023
#pragma once
#include "base/options.h"
#include "settings/settings_common_session.h"
#include "settings/settings_common.h"
#include "settings/settings_common_session.h"
class BoxContent;
namespace Window
{
namespace Window {
class Controller;
class SessionController;
} // namespace Window
namespace Settings
{
namespace Settings {
class Ayu : public Section<Ayu>
{

View file

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

View file

@ -6,7 +6,6 @@
// Copyright @Radolyn, 2023
#pragma once
QString IDString(not_null<PeerData *> peer);
QString IDString(MsgId topic_root_id);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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