From 4df7605b8db73eba2124a70452beb55b086b332a Mon Sep 17 00:00:00 2001 From: Geometrically <18202329+Geometrically@users.noreply.github.com> Date: Thu, 18 May 2023 17:12:36 -0700 Subject: [PATCH] Profile mods page (#119) * Finish profile mods page * commit missing * finish pr * Run lint --- theseus/src/api/profile.rs | 49 +++++++++--- theseus/src/state/profiles.rs | 28 +++++-- theseus/src/state/projects.rs | 30 ++++--- theseus_gui/src-tauri/src/api/profile.rs | 23 +++--- theseus_gui/src/components/ui/Instance.vue | 24 +++--- theseus_gui/src/pages/Browse.vue | 34 ++++---- theseus_gui/src/pages/Settings.vue | 21 ++--- theseus_gui/src/pages/instance/Index.vue | 1 + theseus_gui/src/pages/instance/Mods.vue | 91 ++++++++++++++++++---- 9 files changed, 206 insertions(+), 95 deletions(-) diff --git a/theseus/src/api/profile.rs b/theseus/src/api/profile.rs index fad638d0..180fc72d 100644 --- a/theseus/src/api/profile.rs +++ b/theseus/src/api/profile.rs @@ -125,7 +125,9 @@ pub async fn install(path: &Path) -> crate::Result<()> { #[tracing::instrument] #[theseus_macros::debug_pin] -pub async fn update_all(profile_path: &Path) -> crate::Result<()> { +pub async fn update_all( + profile_path: &Path, +) -> crate::Result> { if let Some(profile) = get(profile_path, None).await? { let loading_bar = init_loading( LoadingBarType::ProfileUpdate { @@ -137,24 +139,49 @@ pub async fn update_all(profile_path: &Path) -> crate::Result<()> { ) .await?; + let keys = profile + .projects + .into_iter() + .filter(|(_, project)| { + matches!( + &project.metadata, + ProjectMetadata::Modrinth { + update_version: Some(_), + .. + } + ) + }) + .map(|x| x.0) + .collect::>(); + let len = keys.len(); + + let map = Arc::new(RwLock::new(HashMap::new())); + use futures::StreamExt; loading_try_for_each_concurrent( - futures::stream::iter(profile.projects.keys()) - .map(Ok::<&PathBuf, crate::Error>), + futures::stream::iter(keys).map(Ok::), None, Some(&loading_bar), 100.0, - profile.projects.keys().len(), + len, None, - |project| async move { - let _ = update_project(profile_path, project).await?; + |project| async { + let map = map.clone(); - Ok(()) + async move { + let new_path = + update_project(profile_path, &project).await?; + + map.write().await.insert(project, new_path); + + Ok(()) + } + .await }, ) .await?; - Ok(()) + Ok(Arc::try_unwrap(map).unwrap().into_inner()) } else { Err(crate::ErrorKind::UnmanagedProfileError( profile_path.display().to_string(), @@ -271,11 +298,9 @@ pub async fn add_project_from_path( pub async fn toggle_disable_project( profile: &Path, project: &Path, -) -> crate::Result<()> { +) -> crate::Result { if let Some(profile) = get(profile, None).await? { - profile.toggle_disable_project(project).await?; - - Ok(()) + Ok(profile.toggle_disable_project(project).await?) } else { Err(crate::ErrorKind::UnmanagedProfileError( profile.display().to_string(), diff --git a/theseus/src/state/profiles.rs b/theseus/src/state/profiles.rs index 5082c3cb..cbadcf7d 100644 --- a/theseus/src/state/profiles.rs +++ b/theseus/src/state/profiles.rs @@ -193,7 +193,7 @@ impl Profile { let paths = profile.get_profile_project_paths()?; let projects = crate::state::infer_data_from_files( - profile, + profile.clone(), paths, state.directories.caches_dir(), &state.io_semaphore, @@ -205,6 +205,14 @@ impl Profile { if let Some(profile) = new_profiles.0.get_mut(&path) { profile.projects = projects; } + + emit_profile( + profile.uuid, + profile.path, + &profile.metadata.name, + ProfilePayloadType::Synced, + ) + .await?; } else { tracing::warn!( "Unable to fetch single profile projects: path {path:?} invalid", @@ -409,7 +417,7 @@ impl Profile { pub async fn toggle_disable_project( &self, path: &Path, - ) -> crate::Result<()> { + ) -> crate::Result { let state = State::get().await?; if let Some(mut project) = { let mut profiles = state.profiles.write().await; @@ -425,6 +433,12 @@ impl Profile { if path.extension().map_or(false, |ext| ext == "disabled") { project.disabled = false; + new_path.set_file_name( + path.file_name() + .unwrap_or_default() + .to_string_lossy() + .replace(".disabled", ""), + ); } else { new_path.set_file_name(format!( "{}.disabled", @@ -437,17 +451,17 @@ impl Profile { let mut profiles = state.profiles.write().await; if let Some(profile) = profiles.0.get_mut(&self.path) { - profile.projects.insert(new_path, project); + profile.projects.insert(new_path.clone(), project); } + + Ok(new_path) } else { - return Err(crate::ErrorKind::InputError(format!( + Err(crate::ErrorKind::InputError(format!( "Project path does not exist: {:?}", path )) - .into()); + .into()) } - - Ok(()) } pub async fn remove_project( diff --git a/theseus/src/state/projects.rs b/theseus/src/state/projects.rs index cef95634..105fa9f9 100644 --- a/theseus/src/state/projects.rs +++ b/theseus/src/state/projects.rs @@ -355,7 +355,7 @@ pub async fn infer_data_from_files( return_projects.insert( path, Project { - disabled: false, + disabled: file_name.ends_with(".disabled"), metadata: ProjectMetadata::Modrinth { project: Box::new(project.clone()), version: Box::new(version.clone()), @@ -364,9 +364,17 @@ pub async fn infer_data_from_files( .filter(|x| x.team_id == project.team) .cloned() .collect::>(), - update_version: update_versions - .get(&hash) - .map(|val| Box::new(val.clone())), + update_version: if let Some(value) = + update_versions.get(&hash) + { + if value.id != version.id { + Some(Box::new(value.clone())) + } else { + None + } + } else { + None + }, incompatible: !version.loaders.contains( &profile .metadata @@ -404,7 +412,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), metadata: ProjectMetadata::Unknown, file_name, }, @@ -458,7 +466,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), file_name, metadata: ProjectMetadata::Inferred { title: Some( @@ -524,7 +532,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), file_name, metadata: ProjectMetadata::Inferred { title: Some(if pack.name.is_empty() { @@ -589,7 +597,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), file_name, metadata: ProjectMetadata::Inferred { title: Some(pack.name.unwrap_or(pack.id)), @@ -654,7 +662,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), file_name, metadata: ProjectMetadata::Inferred { title: Some( @@ -719,7 +727,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), file_name, metadata: ProjectMetadata::Inferred { title: None, @@ -739,7 +747,7 @@ pub async fn infer_data_from_files( path.clone(), Project { sha512: hash, - disabled: path.ends_with(".disabled"), + disabled: file_name.ends_with(".disabled"), file_name, metadata: ProjectMetadata::Unknown, }, diff --git a/theseus_gui/src-tauri/src/api/profile.rs b/theseus_gui/src-tauri/src/api/profile.rs index ac2a11b8..991d4537 100644 --- a/theseus_gui/src-tauri/src/api/profile.rs +++ b/theseus_gui/src-tauri/src/api/profile.rs @@ -1,6 +1,7 @@ use crate::api::Result; use daedalus::modded::LoaderVersion; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::path::{Path, PathBuf}; use theseus::prelude::*; use uuid::Uuid; @@ -32,7 +33,7 @@ pub async fn profile_get( #[theseus_macros::debug_pin] pub async fn profile_list( clear_projects: Option, -) -> Result> { +) -> Result> { let res = profile::list(clear_projects).await?; Ok(res) } @@ -71,9 +72,10 @@ pub async fn profile_install(path: &Path) -> Result<()> { /// invoke('profile_update_all') #[tauri::command] #[theseus_macros::debug_pin] -pub async fn profile_update_all(path: &Path) -> Result<()> { - profile::update_all(path).await?; - Ok(()) +pub async fn profile_update_all( + path: &Path, +) -> Result> { + Ok(profile::update_all(path).await?) } /// Updates a specified project @@ -83,9 +85,8 @@ pub async fn profile_update_all(path: &Path) -> Result<()> { pub async fn profile_update_project( path: &Path, project_path: &Path, -) -> Result<()> { - profile::update_project(path, project_path).await?; - Ok(()) +) -> Result { + Ok(profile::update_project(path, project_path).await?) } // Adds a project to a profile from a version ID @@ -96,8 +97,7 @@ pub async fn profile_add_project_from_version( path: &Path, version_id: String, ) -> Result { - let res = profile::add_project_from_version(path, version_id).await?; - Ok(res) + Ok(profile::add_project_from_version(path, version_id).await?) } // Adds a project to a profile from a path @@ -121,9 +121,8 @@ pub async fn profile_add_project_from_path( pub async fn profile_toggle_disable_project( path: &Path, project_path: &Path, -) -> Result<()> { - profile::toggle_disable_project(path, project_path).await?; - Ok(()) +) -> Result { + Ok(profile::toggle_disable_project(path, project_path).await?) } // Removes a project from a profile diff --git a/theseus_gui/src/components/ui/Instance.vue b/theseus_gui/src/components/ui/Instance.vue index 44dfd1bf..d33fd1a4 100644 --- a/theseus_gui/src/components/ui/Instance.vue +++ b/theseus_gui/src/components/ui/Instance.vue @@ -193,7 +193,7 @@ onUnmounted(() => unlisten())
- +
unlisten()) + + + + +