1use crate::config::scan_config_files;
2use inquire::{Confirm, Select, Text};
3use std::error::Error;
4use std::fs;
5use std::path::PathBuf;
6
7pub fn show_config_selector() -> Result<(PathBuf, bool), Box<dyn Error>> {
9 println!("🎮 Osynic Pad 配置选择\n");
10
11 let config_path = choose_config_source()?;
13
14 let debug = select_debug_mode()?;
16
17 Ok((config_path, debug))
18}
19
20pub fn choose_config_source() -> Result<PathBuf, Box<dyn Error>> {
22 let options = vec![
23 "📂 使用现有配置",
24 "📥 导入配置(从指定位置)",
25 "✨ 新建配置(交互式)",
26 ];
27
28 let choice = Select::new("请选择配置来源:", options)
29 .with_help_message("使用 ↑↓ 导航,Enter 确认")
30 .prompt()?;
31
32 match choice {
33 "📂 使用现有配置" => use_existing_config(),
34 "📥 导入配置(从指定位置)" => import_config_from_path(),
35 "✨ 新建配置(交互式)" => create_new_config(),
36 _ => Err("未知的选择".into()),
37 }
38}
39
40fn use_existing_config() -> Result<PathBuf, Box<dyn Error>> {
42 let configs = scan_config_files()?;
43
44 if configs.is_empty() {
45 eprintln!("❌ 错误:没有找到任何配置文件!");
46 eprintln!("📁 请在 configs 目录下放置 JSON 配置文件。");
47 std::process::exit(1);
48 }
49
50 let config_names: Vec<String> = configs
51 .iter()
52 .map(|p| {
53 p.file_name()
54 .and_then(|n| n.to_str())
55 .unwrap_or("Unknown")
56 .to_string()
57 })
58 .collect();
59
60 select_from_list(config_names, &configs)
61}
62
63fn import_config_from_path() -> Result<PathBuf, Box<dyn Error>> {
65 let path_str = Text::new("请输入配置文件的完整路径:")
66 .with_help_message("例如: C:\\path\\to\\config.json 或 /home/user/config.json")
67 .prompt()?;
68
69 let path = PathBuf::from(&path_str);
70
71 if !path.exists() {
73 eprintln!("❌ 错误:文件不存在: {}", path_str);
74 std::process::exit(1);
75 }
76
77 if path.extension().and_then(|s| s.to_str()) != Some("json") {
79 eprintln!("⚠️ 警告:文件似乎不是 JSON 格式");
80 }
81
82 let filename = path
84 .file_name()
85 .and_then(|n| n.to_str())
86 .unwrap_or("imported_config.json");
87
88 let configs_dir = PathBuf::from("configs");
89 if !configs_dir.exists() {
90 fs::create_dir_all(&configs_dir)?;
91 }
92
93 let dest_path = configs_dir.join(filename);
94
95 if dest_path.exists() {
97 let should_overwrite = Confirm::new(&format!("配置文件 {} 已存在。是否覆盖?", filename))
98 .with_default(false)
99 .prompt()?;
100
101 if !should_overwrite {
102 println!("✅ 使用现有文件: {}", dest_path.display());
103 return Ok(dest_path);
104 }
105 }
106
107 fs::copy(&path, &dest_path)?;
108 println!(
109 "✅ 已导入配置: {} -> {}",
110 path.display(),
111 dest_path.display()
112 );
113
114 Ok(dest_path)
115}
116
117fn create_new_config() -> Result<PathBuf, Box<dyn Error>> {
119 println!("\n📝 新建配置(交互式向导)\n");
120
121 let config_name = Text::new("请输入配置名称(不含 .json):")
122 .with_default("my_config")
123 .prompt()?;
124
125 let config_filename = format!("{}.json", config_name);
126 let configs_dir = PathBuf::from("configs");
127
128 if !configs_dir.exists() {
129 fs::create_dir_all(&configs_dir)?;
130 }
131
132 let config_path = configs_dir.join(&config_filename);
133
134 if config_path.exists() {
136 let should_overwrite =
137 Confirm::new(&format!("配置文件 {} 已存在。是否覆盖?", config_filename))
138 .with_default(false)
139 .prompt()?;
140
141 if !should_overwrite {
142 println!("✅ 使用现有文件: {}", config_path.display());
143 return Ok(config_path);
144 }
145 }
146
147 let default_config = r#"{
149 "default_mode": "Default",
150 "mappings": {
151 "Default": {
152 "A": "Space",
153 "B": "Escape",
154 "X": "w",
155 "Y": "s"
156 }
157 }
158}
159"#;
160
161 fs::write(&config_path, default_config)?;
162 println!("✅ 已创建新配置: {}", config_path.display());
163 println!("💡 你可以编辑此文件来自定义按键映射。\n");
164
165 Ok(config_path)
166}
167
168pub fn select_from_list(
170 names: Vec<String>,
171 configs: &[PathBuf],
172) -> Result<PathBuf, Box<dyn Error>> {
173 let answer = Select::new("请选择配置文件:", names)
174 .with_page_size(10)
175 .with_help_message("使用 ↑↓ 导航,Enter 确认")
176 .prompt()?;
177
178 let selected_idx = configs
180 .iter()
181 .position(|p| p.file_name().and_then(|n| n.to_str()).unwrap_or("") == answer)
182 .ok_or("Configuration not found")?;
183
184 Ok(configs[selected_idx].clone())
185}
186
187pub fn select_debug_mode() -> Result<bool, Box<dyn Error>> {
189 let confirm = Confirm::new("🐛 启用 Debug 模式?")
190 .with_default(false)
191 .with_help_message("y/n")
192 .prompt()?;
193
194 Ok(confirm)
195}
196
197pub fn show_welcome_screen() -> Result<(), Box<dyn Error>> {
199 println!("\n ✨ 欢迎使用 Osynic Pad 手柄映射工具!\n");
200 Ok(())
201}
202
203pub fn show_startup_info(config_filename: &str, mode_str: &str, debug: bool) {
205 println!("\n╔═══════════════════════════════════════╗");
206 println!("║ 🎮 Osynic Pad 正在运行 ║");
207 println!("╠═══════════════════════════════════════╣");
208 println!("║ 配置文件: {:<26} ║", config_filename);
209 println!("║ 映射模式: {:<26} ║", mode_str);
210 println!(
211 "║ Debug 模式: {:<24} ║",
212 if debug { "启用 ✓" } else { "关闭" }
213 );
214 println!("╚═══════════════════════════════════════╝\n");
215}
216
217pub fn show_gamepads(gilrs: &gilrs::Gilrs) -> bool {
219 println!("可用的手柄:");
220 let mut found = false;
221 for (id, gamepad) in gilrs.gamepads() {
222 found = true;
223 println!(" {} 【{}】", id, gamepad.name());
224 }
225
226 if !found {
227 println!("❌ 没有检测到任何手柄!");
228 println!(" 请检查:");
229 println!(" 1. 手柄是否已正确连接");
230 println!(" 2. 系统是否识别到手柄");
231 println!(" 3. 驱动是否正确安装");
232 }
233
234 found
235}