mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Backup shortcuts (#144)
* Add initial option to back up shortcuts * Show list of backups * Reload backups on change * Restore backups * Improve UX of backup ui * Reorganize ui * Update version in cargo.toml * Update flatpak description * Update cargo-lock.json
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
mod defines;
|
||||
mod ui_backup;
|
||||
mod ui_image_download;
|
||||
mod ui_import_games;
|
||||
mod ui_settings;
|
||||
mod uiapp;
|
||||
|
||||
pub use defines::*;
|
||||
pub use ui_backup::*;
|
||||
pub use ui_image_download::*;
|
||||
pub use ui_import_games::*;
|
||||
pub use ui_settings::*;
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use chrono::Local;
|
||||
use egui::ScrollArea;
|
||||
|
||||
use crate::{
|
||||
config::get_backups_flder,
|
||||
steam::{get_shortcuts_paths, SteamSettings},
|
||||
};
|
||||
|
||||
use super::MyEguiApp;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct BackupState {
|
||||
pub available_backups: Option<Vec<PathBuf>>,
|
||||
pub last_restore: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl MyEguiApp {
|
||||
pub fn render_backup(&mut self, ui: &mut egui::Ui) {
|
||||
ui.heading("Backups");
|
||||
ui.label("Here you can restore backed up shortcuts files");
|
||||
ui.label("Click a backup to restore it, your current shortcuts will be backed up first");
|
||||
ui.add_space(15.0);
|
||||
|
||||
if let Some(last_restore) = self.backup_state.last_restore.as_ref() {
|
||||
ui.heading(format!("Last restored {:?}", last_restore));
|
||||
}
|
||||
|
||||
if ui.button("Click here to create a new backup").clicked() {
|
||||
backup_shortcuts(&self.settings.steam);
|
||||
self.backup_state.available_backups = None;
|
||||
}
|
||||
|
||||
let available_backups = self
|
||||
.backup_state
|
||||
.available_backups
|
||||
.get_or_insert_with(|| load_backups());
|
||||
|
||||
if available_backups.is_empty() {
|
||||
ui.label("No backups found, they will be created every time you run import");
|
||||
} else {
|
||||
ScrollArea::vertical()
|
||||
.stick_to_right()
|
||||
.auto_shrink([false, true])
|
||||
.show(ui, |ui| {
|
||||
for backup_path in available_backups {
|
||||
if ui
|
||||
.button(backup_path.to_string_lossy().to_string())
|
||||
.clicked()
|
||||
{
|
||||
//Restore
|
||||
backup_shortcuts(&self.settings.steam);
|
||||
if restore_backup(&self.settings.steam, backup_path.as_path()) {
|
||||
self.backup_state.last_restore = Some(backup_path.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restore_backup(steam_settings: &SteamSettings, shortcut_path: &Path) -> bool {
|
||||
let file_name = shortcut_path.file_name().unwrap();
|
||||
let paths = get_shortcuts_paths(steam_settings);
|
||||
if let Ok(paths) = paths {
|
||||
for user in paths {
|
||||
if let Some(user_shortcut_path) = user.shortcut_path {
|
||||
if file_name.to_string_lossy().starts_with(&user.user_id) {
|
||||
std::fs::copy(shortcut_path, Path::new(&user_shortcut_path)).unwrap();
|
||||
println!("Restored shortcut to path : {}", user_shortcut_path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn load_backups() -> Vec<PathBuf> {
|
||||
let backup_folder = get_backups_flder();
|
||||
let files = std::fs::read_dir(&backup_folder);
|
||||
let mut result = vec![];
|
||||
if let Ok(files) = files {
|
||||
for file in files {
|
||||
if let Ok(file) = file {
|
||||
if file
|
||||
.path()
|
||||
.extension()
|
||||
.unwrap_or_default()
|
||||
.to_string_lossy()
|
||||
== "vdf"
|
||||
{
|
||||
result.push(file.path().to_path_buf());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.sort();
|
||||
result.reverse();
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn backup_shortcuts(steam_settings: &SteamSettings) {
|
||||
let backup_folder = get_backups_flder();
|
||||
let paths = get_shortcuts_paths(&steam_settings);
|
||||
let date = Local::now();
|
||||
let date_string = date.format("%Y-%m-%d-%H-%M-%S");
|
||||
if let Ok(user_infos) = paths {
|
||||
for user_info in user_infos {
|
||||
if let Some(shortcut_path) = user_info.shortcut_path {
|
||||
let new_path = backup_folder.join(format!(
|
||||
"{}-{}-shortcuts.vdf",
|
||||
user_info.user_id, date_string
|
||||
));
|
||||
println!("Backed up shortcut at: {:?}", new_path);
|
||||
std::fs::copy(&shortcut_path, &new_path).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use crate::sync;
|
||||
|
||||
use crate::sync::{download_images, SyncProgress};
|
||||
|
||||
use super::ImageSelectState;
|
||||
use super::{ImageSelectState, backup_shortcuts};
|
||||
use super::{
|
||||
ui_colors::{BACKGROUND_COLOR, EXTRA_BACKGROUND_COLOR},
|
||||
MyEguiApp,
|
||||
@@ -42,6 +42,9 @@ impl<T> FetcStatus<T> {
|
||||
}
|
||||
|
||||
impl MyEguiApp {
|
||||
|
||||
|
||||
|
||||
pub(crate) fn render_import_games(&mut self, ui: &mut egui::Ui) {
|
||||
ui.heading("Import Games");
|
||||
|
||||
@@ -118,6 +121,7 @@ impl MyEguiApp {
|
||||
self.rt.spawn_blocking(move || {
|
||||
MyEguiApp::save_settings_to_file(&settings);
|
||||
let mut some_sender = Some(sender);
|
||||
backup_shortcuts(&settings.steam);
|
||||
let usersinfo = sync::run_sync(&settings, &mut some_sender).unwrap();
|
||||
let task = download_images(&settings, &usersinfo, &mut some_sender);
|
||||
block_on(task);
|
||||
|
||||
+21
-6
@@ -17,7 +17,7 @@ use super::{
|
||||
},
|
||||
ui_images::{get_import_image, get_logo, get_logo_icon},
|
||||
ui_import_games::FetcStatus,
|
||||
ImageSelectState,
|
||||
BackupState, ImageSelectState,
|
||||
};
|
||||
|
||||
const SECTION_SPACING: f32 = 25.0;
|
||||
@@ -37,6 +37,7 @@ pub struct MyEguiApp {
|
||||
pub(crate) status_reciever: Receiver<SyncProgress>,
|
||||
pub(crate) epic_manifests: Option<Vec<ManifestItem>>,
|
||||
pub(crate) image_selected_state: ImageSelectState,
|
||||
pub(crate) backup_state: BackupState,
|
||||
}
|
||||
|
||||
impl MyEguiApp {
|
||||
@@ -51,6 +52,7 @@ impl MyEguiApp {
|
||||
status_reciever: watch::channel(SyncProgress::NotStarted).1,
|
||||
epic_manifests: None,
|
||||
image_selected_state: ImageSelectState::default(),
|
||||
backup_state: BackupState::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,6 +62,7 @@ enum Menues {
|
||||
Import,
|
||||
Settings,
|
||||
Images,
|
||||
Backup,
|
||||
}
|
||||
|
||||
impl Default for Menues {
|
||||
@@ -82,19 +85,28 @@ impl App for MyEguiApp {
|
||||
ui.image(texture, size);
|
||||
ui.add_space(SECTION_SPACING);
|
||||
|
||||
let changed = ui
|
||||
let mut changed = ui
|
||||
.selectable_value(&mut self.selected_menu, Menues::Import, "Import Games")
|
||||
.changed();
|
||||
let mut changed = changed
|
||||
|| ui
|
||||
.selectable_value(&mut self.selected_menu, Menues::Settings, "Settings")
|
||||
.changed();
|
||||
if self.settings.steamgrid_db.auth_key.is_some() {
|
||||
changed = changed
|
||||
|| ui
|
||||
.selectable_value(&mut self.selected_menu, Menues::Images, "Images")
|
||||
.changed();
|
||||
}
|
||||
changed = changed
|
||||
|| ui
|
||||
.selectable_value(&mut self.selected_menu, Menues::Settings, "Settings")
|
||||
.changed();
|
||||
|
||||
changed = changed
|
||||
|| ui
|
||||
.selectable_value(&mut self.selected_menu, Menues::Backup, "Backup")
|
||||
.changed();
|
||||
|
||||
if changed {
|
||||
self.backup_state.available_backups = None;
|
||||
}
|
||||
if changed && self.selected_menu == Menues::Settings {
|
||||
//We reset games here, since user might change settings
|
||||
self.games_to_sync = watch::channel(FetcStatus::NeedsFetched).1;
|
||||
@@ -155,6 +167,9 @@ impl App for MyEguiApp {
|
||||
Menues::Images => {
|
||||
self.render_ui_images(ui);
|
||||
}
|
||||
Menues::Backup => {
|
||||
self.render_backup(ui);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user