Add a button that downloads all images only (#261)

* Add button that downloads all images only

* Improve text
This commit is contained in:
Philip Kristoffersen
2022-10-22 12:25:23 +02:00
committed by GitHub
parent be1c69bdc7
commit 889b25d441
2 changed files with 163 additions and 105 deletions
+162 -102
View File
@@ -8,6 +8,7 @@ use crate::{
steam::{get_installed_games, SteamGameInfo}, steam::{get_installed_games, SteamGameInfo},
steam::{get_shortcuts_paths, SteamUsersInfo}, steam::{get_shortcuts_paths, SteamUsersInfo},
steamgriddb::{get_image_extension, get_query_type, CachedSearch, ImageType, ToDownload}, steamgriddb::{get_image_extension, get_query_type, CachedSearch, ImageType, ToDownload},
sync::{download_images, SyncProgress},
}; };
use dashmap::DashMap; use dashmap::DashMap;
use egui::{Button, Grid, ImageButton, ScrollArea}; use egui::{Button, Grid, ImageButton, ScrollArea};
@@ -128,6 +129,8 @@ enum UserAction {
BackButton, BackButton,
NoAction, NoAction,
ClearImages, ClearImages,
DownloadAllImages,
RefreshImages,
} }
impl MyEguiApp { impl MyEguiApp {
@@ -178,6 +181,29 @@ impl MyEguiApp {
return action; return action;
} }
} }
match *self.status_reciever.borrow() {
crate::sync::SyncProgress::FindingImages => {
ui.spinner();
ui.label("Finding images to download");
ui.ctx().request_repaint();
}
crate::sync::SyncProgress::DownloadingImages { to_download } => {
ui.spinner();
ui.label(format!("Downloading {to_download} images"));
ui.ctx().request_repaint();
}
crate::sync::SyncProgress::Done => {
ui.ctx().request_repaint();
return UserAction::RefreshImages;
}
_ => {
if ui.button("Download images for all games").clicked() {
return UserAction::DownloadAllImages;
}
}
}
UserAction::NoAction UserAction::NoAction
} }
@@ -298,95 +324,103 @@ impl MyEguiApp {
let mut column = 0; let mut column = 0;
match &*state.image_options.borrow() { match &*state.image_options.borrow() {
FetcStatus::Fetched(images) => { FetcStatus::Fetched(images) => {
let x = Grid::new("ImageThumbnailSelectGrid").spacing([column_padding,column_padding]).show(ui, |ui| { let x = Grid::new("ImageThumbnailSelectGrid")
for image in images { .spacing([column_padding, column_padding])
.show(ui, |ui| {
for image in images {
let image_key =
image.thumbnail_path.as_path().to_string_lossy().to_string();
let image_key = match state.image_handles.get_mut(&image_key) {
image.thumbnail_path.as_path().to_string_lossy().to_string(); Some(mut state) => {
match state.value() {
match state.image_handles.get_mut(&image_key) { TextureState::Downloading => {
Some(mut state) => { ui.ctx().request_repaint();
match state.value() { //nothing to do,just wait
TextureState::Downloading => { ui.spinner();
ui.ctx().request_repaint(); }
//nothing to do,just wait TextureState::Downloaded => {
ui.spinner(); //Need to load
} let image_data =
TextureState::Downloaded => { load_image_from_path(&image.thumbnail_path);
//Need to load match image_data {
let image_data = Ok(image_data) => {
load_image_from_path(&image.thumbnail_path); let handle = ui.ctx().load_texture(
match image_data { &image_key,
Ok(image_data) => { image_data,
let handle = ui.ctx().load_texture( egui::TextureFilter::Linear,
&image_key, );
image_data, *state.value_mut() =
egui::TextureFilter::Linear, TextureState::Loaded(handle);
); ui.spinner();
*state.value_mut() = TextureState::Loaded(handle); }
ui.spinner(); Err(_) => *state.value_mut() = TextureState::Failed,
} }
Err(_) => *state.value_mut() = TextureState::Failed, ui.ctx().request_repaint();
} }
ui.ctx().request_repaint(); TextureState::Loaded(texture_handle) => {
} //need to show
TextureState::Loaded(texture_handle) => { let mut size = texture_handle.size_vec2();
//need to show clamp_to_width(&mut size, column_width);
let mut size = texture_handle.size_vec2(); let image_button =
clamp_to_width(&mut size, column_width); ImageButton::new(texture_handle, size);
let image_button = ImageButton::new(texture_handle, size); if ui.add_sized(size, image_button).clicked() {
if ui.add_sized(size,image_button).clicked() { return Some(UserAction::ImageSelected(
return Some(UserAction::ImageSelected(image.clone())); image.clone(),
));
}
}
TextureState::Failed => {
ui.label("Failed to load image");
} }
} }
TextureState::Failed => { }
ui.label("Failed to load image"); None => {
//We need to start a download
let image_handles = &self.image_selected_state.image_handles;
let path = &image.thumbnail_path;
//Redownload if file is too small
if !path.exists()
|| std::fs::metadata(path)
.map(|m| m.len())
.unwrap_or_default()
< 2
{
image_handles
.insert(image_key.clone(), TextureState::Downloading);
let to_download = ToDownload {
path: path.clone(),
url: image.thumbnail_url.clone(),
app_name: "Thumbnail".to_string(),
image_type: *image_type,
};
let image_handles = image_handles.clone();
let image_key = image_key.clone();
self.rt.spawn_blocking(move || {
block_on(crate::steamgriddb::download_to_download(
&to_download,
))
.unwrap();
image_handles
.insert(image_key, TextureState::Downloaded);
});
} else {
image_handles
.insert(image_key.clone(), TextureState::Downloaded);
} }
} }
} }
None => { column += 1;
//We need to start a download if column >= columns {
let image_handles = &self.image_selected_state.image_handles; column = 0;
let path = &image.thumbnail_path; ui.end_row();
//Redownload if file is too small
if !path.exists()
|| std::fs::metadata(path).map(|m| m.len()).unwrap_or_default()
< 2
{
image_handles
.insert(image_key.clone(), TextureState::Downloading);
let to_download = ToDownload {
path: path.clone(),
url: image.thumbnail_url.clone(),
app_name: "Thumbnail".to_string(),
image_type: *image_type,
};
let image_handles = image_handles.clone();
let image_key = image_key.clone();
self.rt.spawn_blocking(move || {
block_on(crate::steamgriddb::download_to_download(
&to_download,
))
.unwrap();
image_handles.insert(image_key, TextureState::Downloaded);
});
} else {
image_handles
.insert(image_key.clone(), TextureState::Downloaded);
}
} }
} }
column += 1;
if column >= columns{
column=0;
ui.end_row();
}
} None
})
None .inner;
}).inner; if x.is_some() {
if x.is_some(){
return x; return x;
} }
} }
@@ -475,6 +509,29 @@ impl MyEguiApp {
} }
self.handle_back_button_action(); self.handle_back_button_action();
} }
UserAction::DownloadAllImages => {
if let Some(users) = &self.image_selected_state.steam_users {
let (sender, reciever) = watch::channel(SyncProgress::FindingImages);
self.status_reciever = reciever;
let mut sender_op = Some(sender);
let settings = self.settings.clone();
let users = users.clone();
self.rt.spawn_blocking(move || {
let task = download_images(&settings, &users, &mut sender_op);
block_on(task);
let _ = sender_op.unwrap().send(SyncProgress::Done);
});
}
}
UserAction::RefreshImages => {
let (_, reciever) = watch::channel(SyncProgress::NotStarted);
let user = self.image_selected_state.steam_user.clone();
if let Some(user) = &user{
load_image_grids(user,&mut self.image_selected_state,ui);
}
self.status_reciever = reciever;
},
}; };
} }
@@ -544,30 +601,7 @@ impl MyEguiApp {
fn handle_user_selected(&mut self, user: SteamUsersInfo, ui: &mut egui::Ui) { fn handle_user_selected(&mut self, user: SteamUsersInfo, ui: &mut egui::Ui) {
let state = &mut self.image_selected_state; let state = &mut self.image_selected_state;
let user_info = crate::steam::get_shortcuts_for_user(&user); let shortcuts = load_image_grids(&user, state, ui);
let mut user_folder = user_info.path.clone();
user_folder.pop();
user_folder.pop();
let mut shortcuts = user_info.shortcuts;
shortcuts.sort_by_key(|s| s.app_name.clone());
let image_type = &ImageType::Grid;
for shortcut in &shortcuts {
let (path, key) = shortcut.key(image_type, &user_folder);
let loaded = state.image_handles.contains_key(&key);
if !loaded && path.exists() {
let image = load_image_from_path(&path);
if let Ok(image) = image {
let texture = ui
.ctx()
.load_texture(&key, image, egui::TextureFilter::Linear);
state
.image_handles
.insert(key, TextureState::Loaded(texture));
}
}
}
state.user_shortcuts = Some(shortcuts); state.user_shortcuts = Some(shortcuts);
state.steam_user = Some(user); state.steam_user = Some(user);
} }
@@ -741,6 +775,32 @@ impl MyEguiApp {
} }
} }
fn load_image_grids(user: &SteamUsersInfo, state: &mut ImageSelectState, ui: &mut egui::Ui) -> Vec<ShortcutOwned> {
let user_info = crate::steam::get_shortcuts_for_user(user);
let mut user_folder = user_info.path.clone();
user_folder.pop();
user_folder.pop();
let mut shortcuts = user_info.shortcuts;
shortcuts.sort_by_key(|s| s.app_name.clone());
let image_type = &ImageType::Grid;
for shortcut in &shortcuts {
let (path, key) = shortcut.key(image_type, &user_folder);
let loaded = state.image_handles.contains_key(&key);
if !loaded && path.exists() {
let image = load_image_from_path(&path);
if let Ok(image) = image {
let texture = ui
.ctx()
.load_texture(&key, image, egui::TextureFilter::Linear);
state
.image_handles
.insert(key, TextureState::Loaded(texture));
}
}
}
shortcuts
}
fn render_shortcut_mode_select(state: &ImageSelectState, ui: &mut egui::Ui) -> Option<UserAction> { fn render_shortcut_mode_select(state: &ImageSelectState, ui: &mut egui::Ui) -> Option<UserAction> {
let mode_before = state.game_mode.clone(); let mode_before = state.game_mode.clone();
let combo_box = egui::ComboBox::new("ImageModeSelect", "").selected_text(mode_before.label()); let combo_box = egui::ComboBox::new("ImageModeSelect", "").selected_text(mode_before.label());
-2
View File
@@ -130,8 +130,6 @@ impl MyEguiApp {
crate::steam::ensure_steam_stopped(); crate::steam::ensure_steam_stopped();
} }
//TODO This might break cli sync, test it
self.status_reciever = reciever; self.status_reciever = reciever;
let renames = self.rename_map.clone(); let renames = self.rename_map.clone();
let all_ready = all_ready(&self.games_to_sync); let all_ready = all_ready(&self.games_to_sync);