Commit Graph

13 Commits

Author SHA1 Message Date
funman300 2f4f1c64d2 refactor: idiomatic Rust cleanup and quality improvements
- Replace .map().unwrap_or(false) with .is_some_and()/.is_ok_and()
- Use path.display() instead of {:?} for user-facing messages
- Replace Option<Option<Vec<String>>> with GamescopeUpdate enum
- Replace manual parent-walking loops with .ancestors() iterators
- Simplify kill()/kill_all() signatures to return () instead of Result
- Use tokio::task::spawn_blocking instead of hand-rolled thread+oneshot
- Read /proc/self/status for UID instead of spawning id subprocess
- Build Exec= line directly in render_desktop instead of string-replace
- Bump PKGBUILD pkgrel to 6
2026-04-19 11:29:42 -07:00
funman300 8447581fe6 detect: fix SKIP_DIRS blocking game discovery for Epic, Ubisoft, Rockstar
SKIP_DIRS contained parent directories that also contain game installs,
which prevented those games from ever being scanned:
  - "epic games"     → all Epic games live inside this dir
  - "ubisoft"        → Ubisoft games at Ubisoft/Ubisoft Game Launcher/games/
  - "rockstar games" → Rockstar games live directly inside this dir
  - "electronic arts" → some EA games live here

SKIP_EXES already filters the individual launcher executables, so the
directory-level blocks are redundant and harmful. Trim SKIP_DIRS to only
directories that genuinely contain no game executables (battle.net,
ea desktop, gog galaxy, Wine infrastructure).

Add missing launcher path patterns to name_from_launcher_path:
  - "ea games"              → EA Games/<GameName>/
  - "ubisoft game launcher" → Ubisoft Game Launcher/games/<GameName>/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:56:42 -07:00
funman300 a0ee01cd5d detect: read Legendary/Heroic installed.json, remove name generation
Add stage 2: read Legendary and Heroic's installed.json files from all
known locations (native + Flatpak) to build a install-path → title map.
This covers Epic games (via Legendary) and GOG games (via Heroic's GOG
store) before any fallback is needed.

Remove CamelCase/digit-boundary splitting from the fallback entirely.
If stages 2-4 all miss, nearest_dir_name() returns the closest
non-generic parent directory name, or the raw exe stem as-is. No names
are fabricated from the exe filename.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:52:55 -07:00
funman300 2b538a286a detect: resolve game names from install directory structure, not guesswork
Remove the hardcoded EXE_OVERRIDES lookup table and the unreliable PE
byte scanner. Game names are already present in the install directory —
we just need to read them from the right place.

Resolution pipeline (first hit wins):
1. Explicit name supplied by the caller
2. Manifest walk: traverse up from the exe to the game root looking for
   GOG goggame-*.info (gameName) and Epic .egstore/*.item (DisplayName)
3. Launcher path: read the game name from known directory conventions
   laid down by the launcher itself:
   - Epic Games/<GameName>/…
   - GOG Games/<GameName>/…
   - steamapps/common/<GameName>/…
   - Rockstar Games/<GameName>/…
4. Heuristic: nearest non-generic parent directory name, or CamelCase
   stem split (unchanged, for truly custom/manual installs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:40:09 -07:00
funman300 e213377a95 detect: replace exe-name heuristic with multi-stage resolution pipeline
Introduce resolve_game_name() as the single entry point for deriving a
display name from a game executable. Resolution order:
  1. Explicit name (caller-supplied)
  2. Static override table for known bad stems (FactoryGame, bg3, etc.)
  3. GOG goggame-*.info and Epic .egstore/*.item manifest JSON files
  4. PE VERSIONINFO scan (ProductName / FileDescription, first 8 MB)
  5. Heuristic fallback: parent directory name or CamelCase stem split

Remove prettify_game_name and humanise_stem; expose prettify_exe_name
as the public heuristic-only fallback. Resolved names are cached in a
process-wide LazyLock<Mutex<HashMap>> so repeated scans are free.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:31:43 -07:00
funman300 f3f5046265 chore: cleanup for push to main
- Remove CLAUDE.md, TODO.md (dev-only task trackers)
- Remove umutray.service (unused systemd unit)
- Remove .vscode/settings.json (stale Makefile ref)
- Add src/theme.rs (shared palette/styling module)
- Update .gitignore: exclude .vscode/, packaging build artifacts
- Fix README: add gui command, correct service description
- Delete ~1.3GB packaging build artifacts from working tree

Code changes from prior session (already committed locally):
- Tray icon launches alongside GUI, close dialog with minimize-to-tray
- Theme module extraction, button shadow fixes, UI polish
- Game detection filtering, prettify_game_name, Battle.net fix
2026-04-19 02:05:10 -07:00
funman300 4e204d4bf7 detect: filter blizzard tools, error/repair/diagnostic exes 2026-04-19 01:08:24 -07:00
funman300 b81c7fd863 detect: filter out launcher tools and non-game exes from game scan 2026-04-19 00:53:36 -07:00
funman300 9134d3bab0 feat(gui): auto-detect games in Wine prefix and browse for exe
- detect::scan_games_in_prefix() walks drive_c/Program Files and
  Program Files (x86) up to depth 4, skipping Windows system dirs,
  the launcher's own exe, and already-configured games
- Empty game list now shows "No games added yet." with two actions:
    · Scan for games — async scan of the Wine prefix, results appear
      as a clickable list with + buttons to add each found exe
    · Browse exe… — native file picker (zenity/kdialog) opening in
      drive_c/, computes the relative path automatically
- Add-game form gains a Browse… button to pick exe from the prefix
- util::pick_file() added alongside pick_folder()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 19:50:48 -07:00
funman300 9b7e474e80 refactor: apply CLAUDE.md code quality improvements and add packaging
- Add #![forbid(unsafe_code)] to main.rs (issue #3)
- Replace raw ANSI escape codes with owo-colors crate (issue #2)
- Replace manual HOME path construction with dirs::home_dir() (issue #5)
- Ship umutray.service as a static file; service::install() substitutes
  the binary path at install time instead of generating the unit at runtime
- Add packaging/PKGBUILD following Arch Rust package guidelines
- Add CLAUDE.md tracking refactor tasks
- setup.rs: clean up downloaded temp files on abort/back, save launcher
  to config only after successful install, auto-start download when a
  preset has an installer_url
- util.rs: add pick_folder() using zenity/kdialog subprocesses (no rfd)
- config.rs: populate installer_url for all 6 built-in presets with
  official download URLs
- Document the Option<Option<Vec<String>>> gamescope pattern at main.rs:307

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 19:28:10 -07:00
funman300 f2f584febf new file: Makefile
new file:   TODO.md
	modified:   src/config.rs
	modified:   src/detect.rs
	modified:   src/diagnose.rs
	new file:   src/gui.rs
	modified:   src/main.rs
	modified:   src/service.rs
	modified:   src/setup.rs
	modified:   src/tray.rs
	new file:   src/util.rs
	new file:   umutray.desktop
2026-04-17 23:12:47 -07:00
funman300 1bacf345f0 Apply rustfmt pass across all modules
Pure whitespace normalization — no logic changes. Mostly:
- collapsing multi-line match/if arms rustfmt prefers inline
- inlining short `with_context`/`ok_or_else` closures
- reformatting nested method chains for consistency

Build and clippy stay clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-17 21:35:27 -07:00
funman300 e72ee69c14 Add detect command to find installed launchers on disk
Scans common Wine prefix locations (~/Games, ~/.wine, Lutris, Bottles,
Heroic) plus any user-supplied --dir paths for each configured
launcher's exe. Reports matches with four markers:

  ✓ already configured at that prefix
  → detected at a different prefix (--apply to update)
  ⚠ multiple prefixes match (ambiguous)
  · not found

--apply writes the new prefix_dir back to config.toml for unambiguous
cases; ambiguous ones are skipped with a note to resolve via
`config edit`. The Setup doc comment is also refreshed since the iced
wizard landed in an earlier commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-17 21:33:48 -07:00