From 17cc5c13addcc02e3217a9bcc0efc5f4cb7c6644 Mon Sep 17 00:00:00 2001 From: y0usaf Date: Tue, 4 Feb 2025 09:37:09 -0500 Subject: [PATCH 1/5] feat: add directory wallpaper support and deferred preloading - Add support for selecting random wallpapers from directories - Add defer_preload option to reduce memory usage - Update README with new features - Improve path handling with tilde expansion --- README.md | 5 ++ src/Hyprpaper.cpp | 66 +++++++++++++++++----- src/config/ConfigManager.cpp | 99 +++++++++++++++++++++++---------- src/helpers/RandomGenerator.hpp | 34 +++++++++++ 4 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 src/helpers/RandomGenerator.hpp diff --git a/README.md b/README.md index 80e097a..d886dfa 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,8 @@ preload = /path/to/next_image.png wallpaper = monitor1,/path/to/image.png #if more than one monitor in use, can load a 2nd image wallpaper = monitor2,/path/to/next_image.png +# you can also specify a directory path to randomly select a wallpaper from +wallpaper = monitor3,/path/to/directory # .. more monitors #enable splash text rendering over the wallpaper @@ -88,6 +90,9 @@ splash = true #fully disable ipc # ipc = off +#enable deferred preloading (reduces memory usage but may cause slight delay when switching wallpapers) +# defer_preload = 1 + ``` diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 1825288..9c0e9b0 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -3,6 +3,7 @@ #include #include #include +#include CHyprpaper::CHyprpaper() = default; @@ -152,35 +153,74 @@ void CHyprpaper::unloadWallpaper(const std::string& path) { } void CHyprpaper::preloadAllWallpapersFromConfig() { + if (std::any_cast(g_pConfigManager->config->getConfigValue("defer_preload"))) { + g_pConfigManager->m_dRequestedPreloads.clear(); + return; + } + if (g_pConfigManager->m_dRequestedPreloads.empty()) return; for (auto& wp : g_pConfigManager->m_dRequestedPreloads) { + // For directory-based preloads, always reselect a random file. + // For files, we'll skip if already loaded. + bool shouldSkip = !std::filesystem::is_directory(wp); - // check if it doesnt exist - bool exists = false; - for (auto& [ewp, cls] : m_mWallpaperTargets) { - if (ewp == wp) { - Debug::log(LOG, "Ignoring request to preload {} as it already is preloaded!", ewp); - exists = true; - break; + if (std::filesystem::is_directory(wp)) { + // Always unload previous wallpaper from this directory + std::vector toUnload; + for (auto& [loadedPath, target] : m_mWallpaperTargets) { + std::filesystem::path pLoaded(loadedPath); + if (pLoaded.parent_path() == std::filesystem::path(wp)) { + toUnload.push_back(loadedPath); + break; // Only unload one wallpaper per directory + } + } + for (auto& path : toUnload) { + unloadWallpaper(path); + } + + std::vector images; + for (auto& entry : std::filesystem::directory_iterator(wp)) { + if (entry.is_regular_file()) { + auto ext = entry.path().extension().string(); + if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".jxl") + images.push_back(entry.path()); + } + } + if (!images.empty()) { + // Use CRandomGenerator instead + wp = images[CRandomGenerator::get().getRandomIndex(images.size())].string(); + } else { + Debug::log(LOG, "No valid images in directory {}", wp); + continue; } } - if (exists) - continue; + // For non-directory requests, skip if already loaded. + if (shouldSkip) { + bool exists = false; + for (auto& [ewp, cls] : m_mWallpaperTargets) { + if (ewp == wp) { + Debug::log(LOG, "Ignoring request to preload {} as it already is preloaded!", ewp); + exists = true; + break; + } + } + if (exists) + continue; + } m_mWallpaperTargets[wp] = CWallpaperTarget(); if (std::filesystem::is_symlink(wp)) { - auto real_wp = std::filesystem::read_symlink(wp); + auto real_wp = std::filesystem::read_symlink(wp); std::filesystem::path absolute_path = std::filesystem::path(wp).parent_path() / real_wp; - absolute_path = absolute_path.lexically_normal(); - m_mWallpaperTargets[wp].create(absolute_path); + absolute_path = absolute_path.lexically_normal(); + m_mWallpaperTargets[wp].create(absolute_path.string()); } else { m_mWallpaperTargets[wp].create(wp); } } - g_pConfigManager->m_dRequestedPreloads.clear(); } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 6e6901a..58762d8 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2,54 +2,101 @@ #include "../Hyprpaper.hpp" #include #include +#include + +// Utility function to safely expand a tilde at the beginning of a path. +static std::string expandTilde(const std::string& path) { + if (!path.empty() && path[0] == '~') { + if (const char* home = getenv("HOME")) + return std::string(home) + path.substr(1); + } + return path; +} static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { - const std::string COMMAND = C; - const std::string VALUE = V; + const std::string COMMAND = C; + const std::string VALUE = V; Hyprlang::CParseResult result; - if (VALUE.find_first_of(',') == std::string::npos) { + // Cache the position of the comma delimiter. + auto delimPos = VALUE.find_first_of(','); + if (delimPos == std::string::npos) { result.setError("wallpaper failed (syntax)"); return result; } - auto MONITOR = VALUE.substr(0, VALUE.find_first_of(',')); - auto WALLPAPER = g_pConfigManager->trimPath(VALUE.substr(VALUE.find_first_of(',') + 1)); + auto MONITOR = VALUE.substr(0, delimPos); + auto WALLPAPER = g_pConfigManager->trimPath(VALUE.substr(delimPos + 1)); bool contain = false; - if (WALLPAPER.find("contain:") == 0) { WALLPAPER = WALLPAPER.substr(8); contain = true; } bool tile = false; - if (WALLPAPER.find("tile:") == 0) { WALLPAPER = WALLPAPER.substr(5); tile = true; } - if (WALLPAPER[0] == '~') { - static const char* const ENVHOME = getenv("HOME"); - WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); - } + // Use the helper to expand '~' + WALLPAPER = expandTilde(WALLPAPER); std::error_code ec; - if (!std::filesystem::exists(WALLPAPER, ec)) { - result.setError((std::string{"wallpaper failed ("} + (ec ? ec.message() : std::string{"no such file"}) + std::string{": "} + WALLPAPER + std::string{")"}).c_str()); + result.setError(((ec ? ec.message() : std::string{"no such file"}) + std::string{": "} + WALLPAPER).c_str()); return result; } - if (std::find(g_pConfigManager->m_dRequestedPreloads.begin(), g_pConfigManager->m_dRequestedPreloads.end(), WALLPAPER) == g_pConfigManager->m_dRequestedPreloads.end() && - !g_pHyprpaper->isPreloaded(WALLPAPER)) { - result.setError("wallpaper failed (not preloaded)"); - return result; + // If it's a directory, always force a reload + if (std::filesystem::is_directory(WALLPAPER)) { + std::string currentWallpaper; + // First get the current wallpaper if it exists + for (auto& [loadedPath, target] : g_pHyprpaper->m_mWallpaperTargets) { + if (std::filesystem::path(loadedPath).parent_path() == std::filesystem::path(WALLPAPER)) { + currentWallpaper = loadedPath; + g_pHyprpaper->unloadWallpaper(loadedPath); + break; + } + } + + std::vector images; + for (auto& entry : std::filesystem::directory_iterator(WALLPAPER)) { + if (entry.is_regular_file()) { + auto ext = entry.path().extension().string(); + if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".jxl") { + if (entry.path().string() != currentWallpaper) { + images.push_back(entry.path()); + } + } + } + } + + if (images.empty()) { + if (!currentWallpaper.empty()) { + images.push_back(currentWallpaper); + } else { + result.setError("No valid images in directory"); + return result; + } + } + + WALLPAPER = images[CRandomGenerator::get().getRandomIndex(images.size())].string(); + } + + if (!g_pHyprpaper->isPreloaded(WALLPAPER)) { + if (std::any_cast(g_pConfigManager->config->getConfigValue("defer_preload"))) { + g_pHyprpaper->m_mWallpaperTargets[WALLPAPER] = CWallpaperTarget(); + g_pHyprpaper->m_mWallpaperTargets[WALLPAPER].create(WALLPAPER); + } else { + result.setError("wallpaper failed (not preloaded)"); + return result; + } } g_pHyprpaper->clearWallpaperFromMonitor(MONITOR); - g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER; + g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER; g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].contain = contain; g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].tile = tile; @@ -57,7 +104,7 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { for (auto& m : g_pHyprpaper->m_vMonitors) { if (!m->hasATarget || m->wildcard) { g_pHyprpaper->clearWallpaperFromMonitor(m->name); - g_pHyprpaper->m_mMonitorActiveWallpapers[m->name] = WALLPAPER; + g_pHyprpaper->m_mMonitorActiveWallpapers[m->name] = WALLPAPER; g_pHyprpaper->m_mMonitorWallpaperRenderData[m->name].contain = contain; g_pHyprpaper->m_mMonitorWallpaperRenderData[m->name].tile = tile; } @@ -76,13 +123,10 @@ static Hyprlang::CParseResult handlePreload(const char* C, const char* V) { const std::string VALUE = V; auto WALLPAPER = VALUE; - if (WALLPAPER[0] == '~') { - static const char* const ENVHOME = getenv("HOME"); - WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); - } + // Use the helper function for tilde expansion. + WALLPAPER = expandTilde(WALLPAPER); std::error_code ec; - if (!std::filesystem::exists(WALLPAPER, ec)) { Hyprlang::CParseResult result; result.setError(((ec ? ec.message() : std::string{"no such file"}) + std::string{": "} + WALLPAPER).c_str()); @@ -130,10 +174,8 @@ static Hyprlang::CParseResult handleUnload(const char* C, const char* V) { if (VALUE == "all" || VALUE == "unused") return handleUnloadAll(C, V); - if (WALLPAPER[0] == '~') { - static const char* const ENVHOME = getenv("HOME"); - WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1); - } + // Use the helper function for tilde expansion. + WALLPAPER = expandTilde(WALLPAPER); g_pHyprpaper->unloadWallpaper(WALLPAPER); @@ -189,6 +231,7 @@ CConfigManager::CConfigManager() { config->addConfigValue("splash", Hyprlang::INT{0L}); config->addConfigValue("splash_offset", Hyprlang::FLOAT{2.F}); config->addConfigValue("splash_color", Hyprlang::INT{0x55ffffff}); + config->addConfigValue("defer_preload", Hyprlang::INT{0L}); config->registerHandler(&handleWallpaper, "wallpaper", {.allowFlags = false}); config->registerHandler(&handleUnload, "unload", {.allowFlags = false}); diff --git a/src/helpers/RandomGenerator.hpp b/src/helpers/RandomGenerator.hpp new file mode 100644 index 0000000..f8fd8d4 --- /dev/null +++ b/src/helpers/RandomGenerator.hpp @@ -0,0 +1,34 @@ +#pragma once +#include + +class CRandomGenerator { +public: + static CRandomGenerator& get() { + static CRandomGenerator instance; + return instance; + } + + // Generate random index for vector size + size_t getRandomIndex(size_t size) { + if (size == 0) return 0; + std::uniform_int_distribution dis(0, size - 1); + return dis(m_Generator); + } + + // Get raw generator if needed + std::mt19937& getGenerator() { + return m_Generator; + } + +private: + CRandomGenerator() : m_Generator(m_RandomDevice()) {} + + std::random_device m_RandomDevice; + std::mt19937 m_Generator; + + // Delete copy/move to ensure singleton + CRandomGenerator(const CRandomGenerator&) = delete; + CRandomGenerator& operator=(const CRandomGenerator&) = delete; + CRandomGenerator(CRandomGenerator&&) = delete; + CRandomGenerator& operator=(CRandomGenerator&&) = delete; +}; \ No newline at end of file From 9f59bf577b175c78219b80d1775675e2dc8331bb Mon Sep 17 00:00:00 2001 From: y0usaf Date: Tue, 4 Feb 2025 10:40:42 -0500 Subject: [PATCH 2/5] refactor: use CRandomGenerator and improve buffer handling - Replace with helpers/RandomGenerator.hpp for consistent random number generation - Improve buffer target handling by using path directly instead of dereferencing wallpaper target - Simplify lambda capture in ensurePoolBuffersPresent() by using reference capture --- src/Hyprpaper.cpp | 12 ++++++------ src/config/ConfigManager.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 9c0e9b0..1247426 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include "helpers/RandomGenerator.hpp" CHyprpaper::CHyprpaper() = default; @@ -314,15 +314,15 @@ SMonitor* CHyprpaper::getMonitorFromName(const std::string& monname) { void CHyprpaper::ensurePoolBuffersPresent() { bool anyNewBuffers = false; - for (auto& [file, wt] : m_mWallpaperTargets) { + for (auto& [path, wt] : m_mWallpaperTargets) { for (auto& m : m_vMonitors) { if (m->size == Vector2D()) continue; - auto it = std::find_if(m_vBuffers.begin(), m_vBuffers.end(), [wt = &wt, &m](const std::unique_ptr& el) { + auto it = std::find_if(m_vBuffers.begin(), m_vBuffers.end(), [&](const std::unique_ptr& el) { auto scale = std::round((m->pCurrentLayerSurface && m->pCurrentLayerSurface->pFractionalScaleInfo ? m->pCurrentLayerSurface->fScale : m->scale) * 120.0) / 120.0; - return el->target == wt->m_szPath && vectorDeltaLessThan(el->pixelSize, m->size * scale, 1); + return el->target == path && vectorDeltaLessThan(el->pixelSize, m->size * scale, 1); }); if (it == m_vBuffers.end()) { @@ -331,9 +331,9 @@ void CHyprpaper::ensurePoolBuffersPresent() { auto scale = std::round((m->pCurrentLayerSurface && m->pCurrentLayerSurface->pFractionalScaleInfo ? m->pCurrentLayerSurface->fScale : m->scale) * 120.0) / 120.0; createBuffer(PBUFFER, m->size.x * scale, m->size.y * scale, WL_SHM_FORMAT_ARGB8888); - PBUFFER->target = wt.m_szPath; + PBUFFER->target = path; - Debug::log(LOG, "Buffer created for target {}, Shared Memory usage: {:.1f}MB", wt.m_szPath, PBUFFER->size / 1000000.f); + Debug::log(LOG, "Buffer created for target {}, Shared Memory usage: {:.1f}MB", path, PBUFFER->size / 1000000.f); anyNewBuffers = true; } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 58762d8..d6283c4 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2,7 +2,7 @@ #include "../Hyprpaper.hpp" #include #include -#include +#include "../helpers/RandomGenerator.hpp" // Utility function to safely expand a tilde at the beginning of a path. static std::string expandTilde(const std::string& path) { From f04fb592a1e26b7a95e76394bfcc3bfb3410a0ad Mon Sep 17 00:00:00 2001 From: y0usaf Date: Tue, 4 Feb 2025 16:11:01 -0500 Subject: [PATCH 3/5] refactor: extract image selection logic into dedicated helper Introduces a new ImagePicker helper that consolidates duplicate wallpaper selection logic from Hyprpaper.cpp and ConfigManager.cpp into a single reusable function. - Add new ImagePicker.{hpp,cpp} with getRandomImageFromDirectory() helper - Function handles directory scanning, file extension validation, and random selection - Supports excluding current wallpaper to avoid duplicate selections - Updates both wallpaper loading code paths to use the new helper - Uses std::shuffle instead of random index for better randomization This change improves code maintainability by removing duplicate logic and centralizing image selection behavior in a single location. --- src/Hyprpaper.cpp | 17 +++++------------ src/config/ConfigManager.cpp | 28 +++++++--------------------- src/helpers/ImagePicker.cpp | 30 ++++++++++++++++++++++++++++++ src/helpers/ImagePicker.hpp | 7 +++++++ 4 files changed, 49 insertions(+), 33 deletions(-) create mode 100644 src/helpers/ImagePicker.cpp create mode 100644 src/helpers/ImagePicker.hpp diff --git a/src/Hyprpaper.cpp b/src/Hyprpaper.cpp index 1247426..4f1ea86 100644 --- a/src/Hyprpaper.cpp +++ b/src/Hyprpaper.cpp @@ -4,6 +4,7 @@ #include #include #include "helpers/RandomGenerator.hpp" +#include "helpers/ImagePicker.hpp" CHyprpaper::CHyprpaper() = default; @@ -180,21 +181,13 @@ void CHyprpaper::preloadAllWallpapersFromConfig() { unloadWallpaper(path); } - std::vector images; - for (auto& entry : std::filesystem::directory_iterator(wp)) { - if (entry.is_regular_file()) { - auto ext = entry.path().extension().string(); - if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".jxl") - images.push_back(entry.path()); - } - } - if (!images.empty()) { - // Use CRandomGenerator instead - wp = images[CRandomGenerator::get().getRandomIndex(images.size())].string(); - } else { + // Use our helper to pick a random image. + std::string randomImage = getRandomImageFromDirectory(wp); + if (randomImage.empty()) { Debug::log(LOG, "No valid images in directory {}", wp); continue; } + wp = randomImage; } // For non-directory requests, skip if already loaded. diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index d6283c4..238c6ae 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -3,6 +3,7 @@ #include #include #include "../helpers/RandomGenerator.hpp" +#include "../helpers/ImagePicker.hpp" // Utility function to safely expand a tilde at the beginning of a path. static std::string expandTilde(const std::string& path) { @@ -61,28 +62,13 @@ static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) { } } - std::vector images; - for (auto& entry : std::filesystem::directory_iterator(WALLPAPER)) { - if (entry.is_regular_file()) { - auto ext = entry.path().extension().string(); - if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".webp" || ext == ".jxl") { - if (entry.path().string() != currentWallpaper) { - images.push_back(entry.path()); - } - } - } + // Use our helper with an exclusion to avoid reselecting the same image. + std::string randomImage = getRandomImageFromDirectory(WALLPAPER, currentWallpaper); + if (randomImage.empty()) { + result.setError("No valid images in directory"); + return result; } - - if (images.empty()) { - if (!currentWallpaper.empty()) { - images.push_back(currentWallpaper); - } else { - result.setError("No valid images in directory"); - return result; - } - } - - WALLPAPER = images[CRandomGenerator::get().getRandomIndex(images.size())].string(); + WALLPAPER = randomImage; } if (!g_pHyprpaper->isPreloaded(WALLPAPER)) { diff --git a/src/helpers/ImagePicker.cpp b/src/helpers/ImagePicker.cpp new file mode 100644 index 0000000..defe473 --- /dev/null +++ b/src/helpers/ImagePicker.cpp @@ -0,0 +1,30 @@ +#include "ImagePicker.hpp" +#include "RandomGenerator.hpp" +#include +#include +#include + +std::string getRandomImageFromDirectory(const std::string &dirPath, const std::string &ignore) { + std::vector images; + for (const auto &entry : std::filesystem::directory_iterator(dirPath)) { + if (entry.is_regular_file()) { + auto ext = entry.path().extension().string(); + if ((ext == ".png" || ext == ".jpg" || ext == ".jpeg" || + ext == ".webp" || ext == ".jxl")) { + if (ignore.empty() || entry.path().string() != ignore) { + images.push_back(entry.path()); + } + } + } + } + + if (images.empty()) { + // If no alternative was found but the ignored file exists, return it. + if (!ignore.empty() && std::filesystem::exists(ignore)) + return ignore; + return ""; + } + + std::shuffle(images.begin(), images.end(), CRandomGenerator::get().getGenerator()); + return images.front().string(); +} diff --git a/src/helpers/ImagePicker.hpp b/src/helpers/ImagePicker.hpp new file mode 100644 index 0000000..7df300f --- /dev/null +++ b/src/helpers/ImagePicker.hpp @@ -0,0 +1,7 @@ +#pragma once +#include + +// Returns a random image path from the given directory. +// If 'ignore' is provided, that file (if present) will be excluded from the selection. +// Returns an empty string if no valid image is found. +std::string getRandomImageFromDirectory(const std::string &dirPath, const std::string &ignore = ""); From 0d63570c899c235fd36e24f8c19baa334d27877e Mon Sep 17 00:00:00 2001 From: y0usaf Date: Wed, 5 Feb 2025 21:47:34 -0500 Subject: [PATCH 4/5] refactor: replace RandomGenerator singleton with global instance --- src/helpers/RandomGenerator.hpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/helpers/RandomGenerator.hpp b/src/helpers/RandomGenerator.hpp index f8fd8d4..89e855b 100644 --- a/src/helpers/RandomGenerator.hpp +++ b/src/helpers/RandomGenerator.hpp @@ -1,34 +1,27 @@ #pragma once #include +#include class CRandomGenerator { public: - static CRandomGenerator& get() { - static CRandomGenerator instance; - return instance; - } - + CRandomGenerator() : mGenerator(mRandomDevice()) {} + // Generate random index for vector size size_t getRandomIndex(size_t size) { if (size == 0) return 0; - std::uniform_int_distribution dis(0, size - 1); - return dis(m_Generator); + std::uniform_int_distribution distribution(0, size - 1); + return distribution(mGenerator); } // Get raw generator if needed std::mt19937& getGenerator() { - return m_Generator; + return mGenerator; } private: - CRandomGenerator() : m_Generator(m_RandomDevice()) {} - - std::random_device m_RandomDevice; - std::mt19937 m_Generator; + std::random_device mRandomDevice; + std::mt19937 mGenerator; +}; - // Delete copy/move to ensure singleton - CRandomGenerator(const CRandomGenerator&) = delete; - CRandomGenerator& operator=(const CRandomGenerator&) = delete; - CRandomGenerator(CRandomGenerator&&) = delete; - CRandomGenerator& operator=(CRandomGenerator&&) = delete; -}; \ No newline at end of file +// Global pointer to random generator +inline std::unique_ptr gRandomGenerator; \ No newline at end of file From bf38a169400eed81b605f1f54ed9590c295b895f Mon Sep 17 00:00:00 2001 From: y0usaf Date: Thu, 6 Feb 2025 08:03:11 -0500 Subject: [PATCH 5/5] refactor: simplify image filtering with guard clauses Flattened nested conditionals into guard clauses for better readability. --- src/helpers/ImagePicker.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/helpers/ImagePicker.cpp b/src/helpers/ImagePicker.cpp index defe473..3d1c74d 100644 --- a/src/helpers/ImagePicker.cpp +++ b/src/helpers/ImagePicker.cpp @@ -7,15 +7,18 @@ std::string getRandomImageFromDirectory(const std::string &dirPath, const std::string &ignore) { std::vector images; for (const auto &entry : std::filesystem::directory_iterator(dirPath)) { - if (entry.is_regular_file()) { - auto ext = entry.path().extension().string(); - if ((ext == ".png" || ext == ".jpg" || ext == ".jpeg" || - ext == ".webp" || ext == ".jxl")) { - if (ignore.empty() || entry.path().string() != ignore) { - images.push_back(entry.path()); - } - } - } + if (!entry.is_regular_file()) + continue; + + auto ext = entry.path().extension().string(); + if (ext != ".png" && ext != ".jpg" && ext != ".jpeg" && + ext != ".webp" && ext != ".jxl") + continue; + + if (!ignore.empty() && entry.path().string() == ignore) + continue; + + images.push_back(entry.path()); } if (images.empty()) {