mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Add a button that downloads all images only (#261)
* Add button that downloads all images only * Improve text
This commit is contained in:
+163
-103
@@ -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| {
|
||||||
let image_key =
|
for image in images {
|
||||||
image.thumbnail_path.as_path().to_string_lossy().to_string();
|
let image_key =
|
||||||
|
image.thumbnail_path.as_path().to_string_lossy().to_string();
|
||||||
|
|
||||||
match state.image_handles.get_mut(&image_key) {
|
match state.image_handles.get_mut(&image_key) {
|
||||||
Some(mut state) => {
|
Some(mut state) => {
|
||||||
match state.value() {
|
match state.value() {
|
||||||
TextureState::Downloading => {
|
TextureState::Downloading => {
|
||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
//nothing to do,just wait
|
//nothing to do,just wait
|
||||||
ui.spinner();
|
ui.spinner();
|
||||||
}
|
}
|
||||||
TextureState::Downloaded => {
|
TextureState::Downloaded => {
|
||||||
//Need to load
|
//Need to load
|
||||||
let image_data =
|
let image_data =
|
||||||
load_image_from_path(&image.thumbnail_path);
|
load_image_from_path(&image.thumbnail_path);
|
||||||
match image_data {
|
match image_data {
|
||||||
Ok(image_data) => {
|
Ok(image_data) => {
|
||||||
let handle = ui.ctx().load_texture(
|
let handle = ui.ctx().load_texture(
|
||||||
&image_key,
|
&image_key,
|
||||||
image_data,
|
image_data,
|
||||||
egui::TextureFilter::Linear,
|
egui::TextureFilter::Linear,
|
||||||
);
|
);
|
||||||
*state.value_mut() = TextureState::Loaded(handle);
|
*state.value_mut() =
|
||||||
ui.spinner();
|
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{
|
None
|
||||||
column=0;
|
})
|
||||||
ui.end_row();
|
.inner;
|
||||||
}
|
if x.is_some() {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}).inner;
|
|
||||||
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());
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user