mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Improve error handling for shortcut saving (#462)
Errors from saving shortcuts were silently swallowed, leaving users with no feedback when writes failed (e.g., due to Steam running or permission issues). Changes: - Make save_shortcuts() return Result<(), String> with user-friendly error messages suggesting to check Steam is not running - Add SyncProgress::Error variant to surface errors through the UI - Display sync errors in red text in both the Import and Images tabs - Propagate save errors in disconnect_shortcut() - Continue processing other users when one fails in sync_shortcuts() and fix_all_shortcut_icons() Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
04feb0b52c
commit
80695c2b95
+29
-13
@@ -27,6 +27,8 @@ pub enum SyncProgress {
|
|||||||
FindingImages,
|
FindingImages,
|
||||||
DownloadingImages { to_download: usize },
|
DownloadingImages { to_download: usize },
|
||||||
Done,
|
Done,
|
||||||
|
/// Error occurred during sync - contains user-friendly error message
|
||||||
|
Error { message: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disconnect_shortcut(settings: &Settings, app_id: u32) -> Result<(), String> {
|
pub fn disconnect_shortcut(settings: &Settings, app_id: u32) -> Result<(), String> {
|
||||||
@@ -42,7 +44,9 @@ pub fn disconnect_shortcut(settings: &Settings, app_id: u32) -> Result<(), Strin
|
|||||||
shortcut.tags.retain(|s| s != BOILR_TAG);
|
shortcut.tags.retain(|s| s != BOILR_TAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
if let Err(e) = save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path)) {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +109,13 @@ pub fn sync_shortcuts(
|
|||||||
|
|
||||||
shortcut_info.shortcuts.extend(all_shortcuts.clone());
|
shortcut_info.shortcuts.extend(all_shortcuts.clone());
|
||||||
|
|
||||||
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
if let Err(e) = save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path)) {
|
||||||
|
eprintln!("Failed to save shortcuts for user {}: {}", user.user_id, e);
|
||||||
|
if let Some(sender) = sender {
|
||||||
|
let _ = sender.send(SyncProgress::Error { message: e });
|
||||||
|
}
|
||||||
|
// Continue with other users even if one fails
|
||||||
|
}
|
||||||
|
|
||||||
if settings.steam.create_collections {
|
if settings.steam.create_collections {
|
||||||
match write_shortcut_collections(&user.user_id, platform_shortcuts) {
|
match write_shortcut_collections(&user.user_id, platform_shortcuts) {
|
||||||
@@ -174,7 +184,10 @@ pub fn fix_all_shortcut_icons(settings: &Settings) -> eyre::Result<()> {
|
|||||||
settings.steam.optimize_for_big_picture,
|
settings.steam.optimize_for_big_picture,
|
||||||
);
|
);
|
||||||
if changes {
|
if changes {
|
||||||
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
if let Err(e) = save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path)) {
|
||||||
|
eprintln!("Failed to save shortcut icons for user {}: {}", user.user_id, e);
|
||||||
|
// Continue with other users
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,7 +252,7 @@ pub fn get_platform_shortcuts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) {
|
fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) -> Result<(), String> {
|
||||||
let mut shortcuts_refs = vec![];
|
let mut shortcuts_refs = vec![];
|
||||||
for shortcut in shortcuts {
|
for shortcut in shortcuts {
|
||||||
shortcuts_refs.push(shortcut.borrow());
|
shortcuts_refs.push(shortcut.borrow());
|
||||||
@@ -248,20 +261,23 @@ fn save_shortcuts(shortcuts: &[ShortcutOwned], path: &Path) {
|
|||||||
match File::create(path) {
|
match File::create(path) {
|
||||||
Ok(mut file) => match file.write_all(new_content.as_slice()) {
|
Ok(mut file) => match file.write_all(new_content.as_slice()) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("Saved {} shortcuts", shortcuts.len())
|
println!("Saved {} shortcuts", shortcuts.len());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => println!(
|
Err(e) => {
|
||||||
"Failed to save shortcuts to {} error: {}",
|
Err(format!(
|
||||||
path.to_string_lossy(),
|
"Failed to write shortcuts to {}: {}. Check that Steam is not running and you have write permissions to the Steam folder.",
|
||||||
|
path.display(),
|
||||||
e
|
e
|
||||||
),
|
))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!(
|
Err(format!(
|
||||||
"Failed to save shortcuts to {} error: {}",
|
"Failed to create shortcuts file at {}: {}. Check that Steam is not running and you have write permissions to the Steam folder.",
|
||||||
path.to_string_lossy(),
|
path.display(),
|
||||||
e
|
e
|
||||||
);
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ impl MyEguiApp {
|
|||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
return Some(UserAction::RefreshImages);
|
return Some(UserAction::RefreshImages);
|
||||||
}
|
}
|
||||||
|
crate::sync::SyncProgress::Error { ref message } => {
|
||||||
|
ui.colored_label(egui::Color32::RED, format!("Error: {}", message));
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if ui.button("Download images for all games").clicked() {
|
if ui.button("Download images for all games").clicked() {
|
||||||
return Some(UserAction::DownloadAllImages);
|
return Some(UserAction::DownloadAllImages);
|
||||||
|
|||||||
+13
-8
@@ -88,23 +88,28 @@ impl MyEguiApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_import_button(&mut self, ui: &mut egui::Ui) {
|
fn render_import_button(&mut self, ui: &mut egui::Ui) {
|
||||||
let (status_string, syncing) = match &*self.status_reciever.borrow() {
|
let (status_string, syncing, is_error) = match &*self.status_reciever.borrow() {
|
||||||
SyncProgress::NotStarted => ("".to_string(), false),
|
SyncProgress::NotStarted => ("".to_string(), false, false),
|
||||||
SyncProgress::Starting => ("Starting Import".to_string(), true),
|
SyncProgress::Starting => ("Starting Import".to_string(), true, false),
|
||||||
SyncProgress::FoundGames { games_found } => {
|
SyncProgress::FoundGames { games_found } => {
|
||||||
(format!("Found {games_found} games to import"), true)
|
(format!("Found {games_found} games to import"), true, false)
|
||||||
}
|
}
|
||||||
SyncProgress::FindingImages => ("Searching for images".to_string(), true),
|
SyncProgress::FindingImages => ("Searching for images".to_string(), true, false),
|
||||||
SyncProgress::DownloadingImages { to_download } => {
|
SyncProgress::DownloadingImages { to_download } => {
|
||||||
(format!("Downloading {to_download} images "), true)
|
(format!("Downloading {to_download} images"), true, false)
|
||||||
|
}
|
||||||
|
SyncProgress::Done => ("Done importing games".to_string(), false, false),
|
||||||
|
SyncProgress::Error { message } => {
|
||||||
|
(format!("Error: {}", message), false, true)
|
||||||
}
|
}
|
||||||
SyncProgress::Done => ("Done importing games".to_string(), false),
|
|
||||||
};
|
};
|
||||||
if syncing {
|
if syncing {
|
||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
}
|
}
|
||||||
if !status_string.is_empty() {
|
if !status_string.is_empty() {
|
||||||
if syncing {
|
if is_error {
|
||||||
|
ui.colored_label(egui::Color32::RED, &status_string);
|
||||||
|
} else if syncing {
|
||||||
ui.horizontal(|c| {
|
ui.horizontal(|c| {
|
||||||
c.spinner();
|
c.spinner();
|
||||||
c.label(&status_string);
|
c.label(&status_string);
|
||||||
|
|||||||
Reference in New Issue
Block a user