1
use std::{path::Path, time::Duration};
2

            
3
use notify::{RecursiveMode, Watcher};
4
use notify_debouncer_full::new_debouncer;
5

            
6
use crate::utils::steam::Steam;
7

            
8
pub async fn command() -> Result<(), String> {
9
    trace!("Running 'watch' command.");
10
    let (tx, rx) = std::sync::mpsc::channel();
11
    let steam = Steam::new();
12

            
13
    trace!("Detected localconfig @ {}.", &steam.localconfig);
14
    trace!("Updating launch options for startup.");
15
    let app_ids = steam.app_ids().unwrap_or_default();
16
    steam.update_all_launch_options(app_ids, map_launch_options());
17

            
18
    trace!("Starting the watch service...");
19
    let mut debouncer =
20
        new_debouncer(Duration::from_secs(2), None, tx).map_err(|e| e.to_string())?;
21

            
22
    debouncer
23
        .watcher()
24
        .watch(Path::new(&steam.localconfig), RecursiveMode::NonRecursive)
25
        .unwrap();
26

            
27
    // print all events, non returning
28
    let mut previous_hash = steam.get_hash();
29

            
30
    trace!("Launch service started!");
31
    for result in rx {
32
        match result {
33
            Ok(_) => {
34
                info!("Checking for changes...");
35
                let current_hash = steam.get_hash();
36

            
37
                if previous_hash == current_hash {
38
                    info!("No changes detected, skipping...");
39
                } else {
40
                    info!("Changes detected!");
41
                    previous_hash = current_hash;
42

            
43
                    info!("Verifying all apps contain the launch options...");
44
                    let app_ids = steam.app_ids().unwrap_or_default();
45
                    steam.update_all_launch_options(app_ids, map_launch_options());
46
                    info!("All apps were updated successfully!");
47
                }
48
            }
49
            Err(error) => log::info!("Error {error:?}"),
50
        }
51
    }
52

            
53
    Ok(())
54
}
55

            
56
fn map_launch_options() -> Box<dyn Fn(Option<String>) -> String> {
57
    return Box::new(move |launch_options| {
58
        let launch_options = launch_options.unwrap_or_default();
59

            
60
        let command = "protontweaks %command%";
61

            
62
        // If our command has already been added then just return the original value
63
        if launch_options.contains(command) {
64
            return launch_options;
65
        }
66

            
67
        // If %command% has already been added, but protontweaks hasn't prefix it with protontweaks
68
        if launch_options.contains("%command%") {
69
            return launch_options.replace("%command%", command);
70
        }
71

            
72
        // If launch options is empty then just return our command
73
        if launch_options.trim() == "" {
74
            return command.to_string();
75
        }
76

            
77
        // Otherwise append our command as a fallback
78
        launch_options + " " + command
79
    });
80
}