Skip to main content

game_manager_lib/commands/
launcher.rs

1use crate::commands::games::get_game_by_id;
2use crate::database::AppState;
3use crate::errors::AppError;
4use crate::utils::launcher::{resolve_launch, LaunchResolution};
5use serde::Serialize;
6use std::process::Command;
7use tauri::{AppHandle, Manager};
8use tauri_plugin_opener::OpenerExt;
9
10#[derive(Debug, Serialize)]
11#[serde(tag = "kind", rename_all = "camelCase")]
12pub enum LaunchOutcome {
13    Launched,
14    OpenedLauncher { installed: bool },
15    OpenedStore,
16    Unavailable,
17}
18
19#[tauri::command]
20pub async fn launch_game(
21    app: AppHandle,
22    game_id: String,
23    launcher_path_override: Option<String>,
24) -> Result<LaunchOutcome, AppError> {
25    let state = app.state::<AppState>();
26    let game = get_game_by_id(state, game_id.clone())?
27        .ok_or_else(|| AppError::NotFound(format!("Jogo não encontrado: {game_id}")))?;
28
29    match resolve_launch(&game, launcher_path_override.as_deref()) {
30        LaunchResolution::Protocol(url) => {
31            app.opener()
32                .open_url(url, None::<&str>)
33                .map_err(|e| AppError::LaunchError(e.to_string()))?;
34            Ok(LaunchOutcome::Launched)
35        }
36        LaunchResolution::Executable(path) => {
37            Command::new(&path).spawn()?; // AppError::IoError via From, sem wrapper manual
38            Ok(LaunchOutcome::Launched)
39        }
40        LaunchResolution::Launcher(path) => {
41            Command::new(&path).spawn()?;
42            Ok(LaunchOutcome::OpenedLauncher {
43                installed: game.installed,
44            })
45        }
46        LaunchResolution::Store(url) => {
47            app.opener()
48                .open_url(url, None::<&str>)
49                .map_err(|e| AppError::LaunchError(e.to_string()))?;
50            Ok(LaunchOutcome::OpenedStore)
51        }
52        LaunchResolution::Unavailable => Ok(LaunchOutcome::Unavailable),
53    }
54}