From 6f1d53eaeff11f05e6b0183da36a711c8eced4e9 Mon Sep 17 00:00:00 2001 From: so5iso4ka Date: Thu, 18 Dec 2025 13:32:06 +0300 Subject: [PATCH] refactor(screenshots): make ScreenshotsWatcher async Signed-off-by: so5iso4ka --- launcher/minecraft/ScreenshotsWatcher.cpp | 69 ++++++++++++++++------- launcher/minecraft/ScreenshotsWatcher.h | 22 +++++--- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/launcher/minecraft/ScreenshotsWatcher.cpp b/launcher/minecraft/ScreenshotsWatcher.cpp index 65b2795e6..8bdc55521 100644 --- a/launcher/minecraft/ScreenshotsWatcher.cpp +++ b/launcher/minecraft/ScreenshotsWatcher.cpp @@ -17,49 +17,78 @@ */ #include -#include #include -#include #include "Application.h" +#include "FileSystem.h" #include "MinecraftInstance.h" #include "ScreenshotsWatcher.h" -ScreenshotsWatcher::ScreenshotsWatcher(const QString& path) : QObject(), m_path(path) +ScreenshotsWatcher::ScreenshotsWatcher(const QString& path) : m_watcher(QStringList{ path }) { - auto watcher = new QFileSystemWatcher({ path }); - - connect(watcher, &QFileSystemWatcher::directoryChanged, this, &ScreenshotsWatcher::dirUpdated); - - m_watcher = std::make_unique(watcher); + m_retryTimer.setSingleShot(true); + m_retryTimer.setInterval(200); + connect(&m_retryTimer, &QTimer::timeout, this, &ScreenshotsWatcher::tryCopy); + connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &ScreenshotsWatcher::dirUpdated); } -void ScreenshotsWatcher::dirUpdated() +void ScreenshotsWatcher::dirUpdated(const QString& path) { - QDir d(m_path, "*.png", QDir::Time, QDir::Files); + QDir d(path, "*.png", QDir::Time, QDir::Files); if (!d.exists() || !d.count()) { qDebug() << "Invalid screenshots dir"; return; } - QString path = m_path + '/' + d[0]; - auto clipboard = Application::clipboard(); - if (clipboard == nullptr) { - qDebug() << "Clipboard ptr is null, aborting copying"; + QString file = FS::PathCombine(path, d[0]); + if (file == m_pendingPath) + return; + + m_pendingPath = file; + m_attempt = 0; + m_lastSize = QFileInfo(m_pendingPath).size(); + + scheduleRetry(); +} + +void ScreenshotsWatcher::tryCopy() +{ + const QFileInfo fileInfo(m_pendingPath); + if (!fileInfo.exists()) + return; + + if (m_lastSize == 0 || m_lastSize != fileInfo.size()) { + m_lastSize = fileInfo.size(); + scheduleRetry(); return; } + m_lastSize = fileInfo.size(); QImage img; - bool loaded = img.load(path); - for (int i = 0; i < 5 && !loaded; i++) { - QThread::msleep(200); - loaded = img.load(path); - } + bool loaded = img.load(m_pendingPath); + if (!loaded) { - qDebug() << "Image wasn't loaded in 1 sec, aborting copying"; + scheduleRetry(); + return; + } + + const auto clipboard = QApplication::clipboard(); + if (clipboard == nullptr) { + qDebug() << "Clipboard is null"; return; } clipboard->setImage(img); } + +void ScreenshotsWatcher::scheduleRetry() +{ + ++m_attempt; + if (m_attempt > 5) { + qDebug() << "Image wasn't loaded after 5 retries"; + return; + } + + m_retryTimer.start(); +} diff --git a/launcher/minecraft/ScreenshotsWatcher.h b/launcher/minecraft/ScreenshotsWatcher.h index 64a92ee2d..62704c28a 100644 --- a/launcher/minecraft/ScreenshotsWatcher.h +++ b/launcher/minecraft/ScreenshotsWatcher.h @@ -18,13 +18,11 @@ #pragma once +#include #include -#include - -class QFileSystemWatcher; -class QString; -class QObject; -class MinecraftInstance; +#include +#include +#include class ScreenshotsWatcher : public QObject { Q_OBJECT @@ -32,9 +30,15 @@ class ScreenshotsWatcher : public QObject { explicit ScreenshotsWatcher(const QString& path); private slots: - void dirUpdated(); + void dirUpdated(const QString& path); + void tryCopy(); private: - std::unique_ptr m_watcher; - const QString m_path; + void scheduleRetry(); + + QFileSystemWatcher m_watcher; + QString m_pendingPath; + std::size_t m_attempt{}; + std::size_t m_lastSize{}; + QTimer m_retryTimer; };