refactor: content tab styling (#7091)

* refactor: managed content card

* fix: update filter pill styling to be chips-like

* fix: modpack exporting

* fixed: vanilla server projs + header

* refactor: filters

* refactor: detect external file icons + other metadata inside

* refactor: support json5 metadata

* fix: qa

* fix: qa

* fix: fmt + prepr

* fix: fmt

* fix: qa

* fix: headers

* feat: locking

* fix: clippy

* fix: qa

* fix: frozen loc

* fix: shared instances diff calc break

* fix: env filter + remove categories
This commit is contained in:
Calum H.
2026-08-13 14:55:35 +00:00
committed by GitHub
parent e087e571f3
commit 06b7c44dcc
126 changed files with 3654 additions and 3473 deletions
+3 -2
View File
@@ -35,8 +35,9 @@ pub use self::projects::{
InstallProjectWithDependenciesRequest, add_project_from_path,
add_project_from_version, install_project_with_dependencies,
is_file_on_modrinth, remove_project, repair_managed_modrinth,
switch_project_version_with_dependencies, toggle_disable_project,
update_all_projects, update_managed_modrinth_version, update_project,
set_project_locked, switch_project_version_with_dependencies,
toggle_disable_project, update_all_projects,
update_managed_modrinth_version, update_project,
};
pub use self::run::{
QuickPlayType, kill, run, try_update_playtime_by_instance_id,
@@ -8,6 +8,7 @@ use crate::pack::install_from::{
};
use crate::state::{
CacheBehaviour, CachedEntry, InstanceMetadata, ModLoader, SideType, State,
VersionEnvironment,
};
use crate::util::io::{self, IOError};
use async_zip::tokio::write::ZipFileWriter;
@@ -413,6 +414,39 @@ fn pack_get_relative_path(
)?)
}
fn get_mrpack_environment(
environment: Option<VersionEnvironment>,
) -> HashMap<EnvType, SideType> {
let (client, server) = match environment
.unwrap_or(VersionEnvironment::Unknown)
{
VersionEnvironment::ClientAndServer
| VersionEnvironment::SingleplayerOnly => {
(SideType::Required, SideType::Required)
}
VersionEnvironment::ClientOnly => {
(SideType::Required, SideType::Unsupported)
}
VersionEnvironment::ClientOnlyServerOptional => {
(SideType::Required, SideType::Optional)
}
VersionEnvironment::ServerOnly
| VersionEnvironment::DedicatedServerOnly => {
(SideType::Unsupported, SideType::Required)
}
VersionEnvironment::ServerOnlyClientOptional => {
(SideType::Optional, SideType::Required)
}
VersionEnvironment::ClientOrServer
| VersionEnvironment::ClientOrServerPrefersBoth => {
(SideType::Optional, SideType::Optional)
}
VersionEnvironment::Unknown => (SideType::Optional, SideType::Optional),
};
HashMap::from([(EnvType::Client, client), (EnvType::Server, server)])
}
#[tracing::instrument(skip_all)]
pub async fn create_mrpack_json(
metadata: &InstanceMetadata,
@@ -461,9 +495,10 @@ pub async fn create_mrpack_json(
_ => None,
})
.collect::<Vec<_>>();
let versions = CachedEntry::get_version_many(
&projects.iter().map(|x| &*x.1).collect::<Vec<_>>(),
None,
let version_ids = projects.iter().map(|x| &*x.1).collect::<Vec<_>>();
let versions = CachedEntry::get_version_v3_many(
&version_ids,
Some(CacheBehaviour::MustRevalidate),
&state.pool,
&state.api_semaphore,
)
@@ -473,9 +508,7 @@ pub async fn create_mrpack_json(
.filter_map(|(path, version_id)| {
if let Some(version) = versions.iter().find(|x| x.id == version_id)
{
let mut env = HashMap::new();
env.insert(EnvType::Client, SideType::Required);
env.insert(EnvType::Server, SideType::Required);
let env = get_mrpack_environment(version.environment);
let Some(primary_file) = version.files.first() else {
return Some(Err(crate::ErrorKind::OtherError(format!(
"No primary file found for mod at: {path}"
@@ -60,6 +60,7 @@ pub async fn update_project(
&state,
)
.await?;
ensure_project_not_frozen(instance_id, project_path, &state).await?;
let path = crate::state::instances::commands::update_project(
instance_id,
project_path,
@@ -197,6 +198,7 @@ pub async fn switch_project_version_with_dependencies(
&state,
)
.await?;
ensure_project_not_frozen(instance_id, project_path, &state).await?;
let metadata = super::get::get(instance_id).await?.ok_or_else(|| {
crate::ErrorKind::InputError("Unknown instance".to_string())
})?;
@@ -289,6 +291,27 @@ pub async fn remove_project(
Ok(())
}
#[tracing::instrument]
pub async fn set_project_locked(
instance_id: &str,
project: &str,
locked: bool,
) -> crate::Result<()> {
let state = State::get().await?;
ensure_shared_instance_can_modify_project(instance_id, project, &state)
.await?;
crate::state::instances::commands::set_project_locked(
instance_id,
project,
locked,
&state,
)
.await?;
emit_instance(instance_id, InstancePayloadType::Edited).await?;
Ok(())
}
async fn ensure_shared_instance_can_modify_project(
instance_id: &str,
project_path: &str,
@@ -328,6 +351,28 @@ async fn ensure_shared_instance_can_modify_project(
Ok(())
}
async fn ensure_project_not_frozen(
instance_id: &str,
project_path: &str,
state: &State,
) -> crate::Result<()> {
if crate::state::instances::commands::is_project_locked(
instance_id,
project_path,
state,
)
.await?
{
return Err(crate::ErrorKind::InputError(
"Frozen content cannot change versions. Unfreeze it first."
.to_string(),
)
.into());
}
Ok(())
}
#[tracing::instrument]
pub async fn update_managed_modrinth_version(
instance_id: &str,