Simplify SteamripScraper link/name extraction by using BeautifulSoup results directly (append absolute URLs and use link.get_text()) and avoid fragile regex; adjust scrape_steamrip_game_downloads to accept a full URL argument. Update context menu text: replace "Copy Magnet URI" with "Copy Download Link" in two places and rename "Download Item" to "Download" for clearer UI wording.
Introduce check_running(app) to create and check SingleInstance early in main(), store it on app._single_instance, and reuse that instance in run_gui() instead of constructing a new one. Move single-instance exit logic (print, closehelper, force_exit) into the new helper and wire single.on_raise to show_from_tray. Also replace the previous consoleLog call with print and add a comment indicating the check is for SoftwareManager already running. This centralizes startup single-instance handling and avoids creating multiple SingleInstance objects.
contextmenu.py: Harden context-menu handlers by validating row bounds against state.posts, avoid relying on selectedItems() in places where _context_menu_row is used, and handle directory paths when deleting downloads (os.path.isdir or isfile) before send2trash. Also streamline URL opening with exception handling. main.py: Update SERVER_NAME to "SoftwareManager_KeksPirates". These changes prevent out-of-range/selection errors and ensure directories are trashed safely; also update server identification.
Introduce an automated workflow to keep the README's Python Dependencies section in sync with requirements.txt. Adds .github/workflows/sync-readme-dependencies.yml which runs scripts/sync_readme_dependencies.py on changes to requirements.txt (or manually), then opens a PR via peter-evans/create-pull-request. Adds the sync_readme_dependencies.py script that parses requirements.txt and replaces a managed block in README.md delimited by <!-- python-dependencies:start --> / <!-- python-dependencies:end -->. Also updates README.md to include those markers and correct dependency names/formatting. Additionally, change create-release.yml to use RELEASE_TOKEN (secrets.RELEASE_TOKEN) for release uploads instead of the repository GITHUB_TOKEN.
Add a <meta name="darkreader-lock"> tag to prevent Dark Reader from altering the docs styling. Adjust client-side routing so only '/' is replaced with the 'start' tab; unknown paths now open the 'notfound' tab instead of being redirected to start.
Introduce _apply_layout_fast to update the image overlay quickly on window resize using the cached QImage and FastTransformation. Called from the Resize event handler before the resize timer, it handles wallpaper mode (fast scale, center-crop to parent) and non-wallpaper mode (positioning by state.image_position and state.image_offset) to provide immediate visual feedback without running the heavier _apply_layout.
Add a 100ms single-shot QTimer to debounce Resize events and avoid reloading/layout on every resize. Cache the loaded QImage in _cached_qimage/_cached_path and only reload from disk when the image path changes. Extract layout/apply logic into _apply_layout and clear cache in update_image_overlay when a new path is provided. These changes reduce disk I/O and repeated layout work during rapid resizes.
Improve thread-safety, logging, and various bug fixes across the app.
Key changes:
- Add and use state.downloads_lock around accesses to state.active_downloads in multiple modules (UI, libtorrent, misc, direct downloads) to prevent race conditions.
- Prevent concurrent dl_status_loop runs using a non-blocking _loop_lock and ensure proper iteration over a snapshot of downloads.
- Add metadata timeout when waiting for torrent metadata and fix free-space check logic to remove or reject downloads appropriately.
- Refactor download log persistence: add _load_downloads and _save_downloads helpers and centralize JSON read/write logic in utils/logging/logs.py.
- Optimize DirectDownloadStatus speed window by switching to deque and using popleft to trim older samples.
- Trim console log widget to 500 lines to avoid unbounded growth.
- Add small state fields for custom image positioning (x/y and enabled flag).
- Fix Steamrip scraper caching behavior and make Uztracker return an empty list on fetch failures.
- Add defensive checks in run_download to handle missing links.
These changes focus on stability and correctness for concurrent download handling and durable logging.