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::services::playtime::{has_official_playtime_source, watch_game};
5use crate::utils::launcher::{resolve_launch, LaunchResolution};
6use serde::Serialize;
7use std::path::PathBuf;
8use std::process::Command;
9use tauri::{AppHandle, Manager};
10use tauri_plugin_opener::OpenerExt;
11
12#[derive(Debug, Serialize)]
13#[serde(tag = "kind", rename_all = "camelCase")]
14pub enum LaunchOutcome {
15    Launched,
16    OpenedLauncher { installed: bool },
17    OpenedStore,
18    Unavailable,
19}
20
21#[tauri::command]
22pub async fn launch_game(
23    app: AppHandle,
24    game_id: String,
25    launcher_path_override: Option<String>,
26) -> Result<LaunchOutcome, AppError> {
27    let state = app.state::<AppState>();
28    let game = get_game_by_id(state, game_id.clone())?
29        .ok_or_else(|| AppError::NotFound(format!("Jogo não encontrado: {game_id}")))?;
30
31    let outcome = match resolve_launch(&game, launcher_path_override.as_deref()) {
32        LaunchResolution::Protocol(url) => {
33            app.opener()
34                .open_url(url, None::<&str>)
35                .map_err(|e| AppError::LaunchError(e.to_string()))?;
36            LaunchOutcome::Launched
37        }
38        LaunchResolution::Executable(path) => {
39            Command::new(&path).spawn()?;
40            LaunchOutcome::Launched
41        }
42        LaunchResolution::Launcher(path) => {
43            Command::new(&path).spawn()?;
44            LaunchOutcome::OpenedLauncher {
45                installed: game.installed,
46            }
47        }
48        LaunchResolution::Store(url) => {
49            app.opener()
50                .open_url(url, None::<&str>)
51                .map_err(|e| AppError::LaunchError(e.to_string()))?;
52            LaunchOutcome::OpenedStore
53        }
54        LaunchResolution::Unavailable => LaunchOutcome::Unavailable,
55    };
56
57    let should_track = matches!(
58        outcome,
59        LaunchOutcome::Launched | LaunchOutcome::OpenedLauncher { installed: true }
60    ) && !has_official_playtime_source(&game.platform);
61
62    if should_track {
63        if let Some(exe_path) = game.executable_path.as_ref().map(PathBuf::from) {
64            let install_path = game.install_path.as_ref().map(PathBuf::from);
65            watch_game(app.clone(), game.id.clone(), exe_path, install_path);
66        }
67    }
68
69    Ok(outcome)
70}