1pub mod app;
14pub mod keyboard_help;
15pub mod openapi_sync;
16pub mod path_picker;
17pub mod screens;
18pub mod text_search;
19pub mod utils;
20
21use anyhow::Result;
22use std::time::Duration;
23
24use crate::client::RommClient;
25use crate::config::{openapi_cache_path, should_check_updates, Config};
26
27use self::app::App;
28use self::openapi_sync::sync_openapi_registry;
29use self::screens::connected_splash::StartupSplash;
30use self::screens::setup_wizard::SetupWizard;
31
32fn install_panic_hook() {
33 let original_hook = std::panic::take_hook();
34 std::panic::set_hook(Box::new(move |panic| {
35 let _ = crossterm::terminal::disable_raw_mode();
36 let _ = crossterm::execute!(
37 std::io::stdout(),
38 crossterm::terminal::LeaveAlternateScreen,
39 crossterm::event::DisableMouseCapture
40 );
41 original_hook(panic);
42 }));
43}
44
45fn startup_splash_for(
46 from_setup_wizard: bool,
47 config: &Config,
48 server_version: &Option<String>,
49) -> Option<StartupSplash> {
50 if from_setup_wizard {
51 return Some(StartupSplash::new(
52 config.base_url.clone(),
53 server_version.clone(),
54 ));
55 }
56 if server_version.is_some() {
57 return Some(StartupSplash::new(
58 config.base_url.clone(),
59 server_version.clone(),
60 ));
61 }
62 None
63}
64
65fn startup_splash_for_launch(
67 from_setup_wizard: bool,
68 config: &Config,
69 server_version: &Option<String>,
70 update_pending: bool,
71) -> Option<StartupSplash> {
72 if update_pending {
73 return None;
74 }
75 startup_splash_for(from_setup_wizard, config, server_version)
76}
77
78async fn run_started(
79 client: RommClient,
80 config: Config,
81 from_setup_wizard: bool,
82 mock_update: bool,
83) -> Result<()> {
84 install_panic_hook();
85 let cache_path = openapi_cache_path()?;
86 let (registry, server_version) = sync_openapi_registry(&client, &cache_path).await?;
87
88 let startup_update = if mock_update {
89 Some(crate::update::UpdateStatus {
90 current_version: format!("{} (dev)", env!("CARGO_PKG_VERSION")),
91 latest_version: "9.9.9-mock".into(),
92 release_tag: "v9.9.9-mock".into(),
93 should_update: true,
94 release_url: "https://github.com/patricksmill/romm-cli".into(),
95 changelog_url: crate::update::changelog_url().to_string(),
96 })
97 } else if should_check_updates() {
98 match tokio::time::timeout(Duration::from_secs(2), crate::update::check_for_update()).await
99 {
100 Ok(Ok(status)) if status.should_update => Some(status),
101 _ => None,
102 }
103 } else {
104 None
105 };
106
107 let splash = startup_splash_for_launch(
108 from_setup_wizard,
109 &config,
110 &server_version,
111 startup_update.is_some(),
112 );
113 let mut app = App::new(
114 client,
115 config,
116 registry,
117 server_version,
118 splash,
119 startup_update,
120 );
121 app.run().await
122}
123
124pub async fn run(client: RommClient, config: Config, mock_update: bool) -> Result<()> {
126 run_started(client, config, false, mock_update).await
127}
128
129pub async fn run_interactive(verbose: bool, mock_update: bool) -> Result<()> {
131 let (from_wizard, config) = match crate::config::load_config() {
132 Ok(c) => (false, c),
133 Err(_) => (true, SetupWizard::new().run(verbose).await?),
134 };
135 let client = RommClient::new(&config, verbose)?;
136 run_started(client, config, from_wizard, mock_update).await
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use crate::config::ExtrasDefaults;
143
144 fn test_config() -> Config {
145 Config {
146 base_url: "http://127.0.0.1:9".into(),
147 download_dir: "/tmp".into(),
148 use_https: false,
149 auth: None,
150 extras_defaults: ExtrasDefaults::default(),
151 save_sync: Default::default(),
152 roms_layout: Default::default(),
153 }
154 }
155
156 #[test]
157 fn startup_splash_for_launch_skips_splash_when_update_pending() {
158 let config = test_config();
159 let version = Some("4.0.0".into());
160 assert!(startup_splash_for_launch(false, &config, &version, true).is_none());
161 }
162
163 #[test]
164 fn startup_splash_for_launch_shows_splash_when_no_update() {
165 let config = test_config();
166 let version = Some("4.0.0".into());
167 assert!(startup_splash_for_launch(false, &config, &version, false).is_some());
168 }
169}