183 lines
6.8 KiB
Rust
183 lines
6.8 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use freya::query::{Mutation, MutationCapability, QueriesStorage, UseMutation, use_mutation};
|
|
use oneclient_content::packages::{ContentType, PackageStore};
|
|
use oneclient_db::models::ClusterId;
|
|
|
|
use super::bundles::{BundleOverridesQuery, BundleUpdatesQuery, BundlesWithStatusQuery};
|
|
use super::cluster_content::ClusterContentQuery;
|
|
use super::clusters::ListClustersQuery;
|
|
use super::package_updates::PackageUpdatesQuery;
|
|
use super::settings_profiles::{
|
|
ClusterProfileQuery, ClusterSettingsQuery, GameProfileQuery, ListNamedProfilesQuery,
|
|
};
|
|
use super::versions::{LoaderVersionsQuery, VersionsMetadataQuery};
|
|
|
|
pub async fn invalidate_cluster_queries() {
|
|
QueriesStorage::<ListClustersQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<ClusterContentQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<BundlesWithStatusQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<BundleOverridesQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<BundleUpdatesQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<PackageUpdatesQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<VersionsMetadataQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<LoaderVersionsQuery>::try_invalidate_all().await;
|
|
}
|
|
|
|
/// Split out of [`invalidate_cluster_queries`] so an install can wait for just
|
|
/// this before dropping its busy flag the full sweep hits the network
|
|
pub async fn invalidate_cluster_content_queries() {
|
|
QueriesStorage::<ClusterContentQuery>::try_invalidate_all().await;
|
|
}
|
|
|
|
pub async fn invalidate_profile_queries() {
|
|
QueriesStorage::<ListNamedProfilesQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<GameProfileQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<ClusterProfileQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<ClusterSettingsQuery>::try_invalidate_all().await;
|
|
QueriesStorage::<ListClustersQuery>::try_invalidate_all().await;
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
|
pub struct ClusterMutation;
|
|
|
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
|
pub enum ClusterAction {
|
|
ToggleArtifact {
|
|
cluster_id: ClusterId,
|
|
hash: String,
|
|
},
|
|
RemoveArtifact {
|
|
cluster_id: ClusterId,
|
|
hash: String,
|
|
},
|
|
RemoveBundlePackageFromDisk {
|
|
cluster_id: ClusterId,
|
|
hash: String,
|
|
},
|
|
SetBundlePackageEnabled {
|
|
cluster_id: ClusterId,
|
|
bundle_name: String,
|
|
package_id: String,
|
|
enabled: bool,
|
|
/// Manifest default matching it clears the override contradicting it
|
|
/// writes `Enabled` / `Disabled`
|
|
manifest_default: bool,
|
|
},
|
|
ImportLocalFile {
|
|
cluster_id: ClusterId,
|
|
content_type: ContentType,
|
|
path: PathBuf,
|
|
},
|
|
SetDedicatedDir {
|
|
cluster_id: ClusterId,
|
|
dedicated: bool,
|
|
},
|
|
VerifyFiles {
|
|
cluster_id: ClusterId,
|
|
},
|
|
}
|
|
|
|
impl MutationCapability for ClusterMutation {
|
|
type Ok = ();
|
|
type Err = String;
|
|
type Keys = ClusterAction;
|
|
|
|
async fn run(&self, keys: &ClusterAction) -> Result<(), String> {
|
|
let state = crate::launcher::state().map_err(|e| e.to_string())?;
|
|
let services = &state.services;
|
|
let content = &state.services.content();
|
|
let result = match keys {
|
|
ClusterAction::ToggleArtifact { cluster_id, hash } => {
|
|
// Applied to the game folder at next launch never mid-session
|
|
// Minecraft reads its mods once at startup
|
|
oneclient_core::toggle_artifact_enabled(*cluster_id, hash, content)
|
|
.await
|
|
.map(|_| ())
|
|
}
|
|
ClusterAction::RemoveArtifact { cluster_id, hash } => {
|
|
oneclient_core::remove_artifact_from_cluster(*cluster_id, hash, true, content).await
|
|
}
|
|
ClusterAction::RemoveBundlePackageFromDisk { cluster_id, hash } => {
|
|
oneclient_core::remove_artifact_from_cluster(*cluster_id, hash, false, content).await
|
|
}
|
|
ClusterAction::SetBundlePackageEnabled {
|
|
cluster_id,
|
|
bundle_name,
|
|
package_id,
|
|
enabled,
|
|
manifest_default,
|
|
} => {
|
|
oneclient_core::set_bundle_package_enabled(
|
|
*cluster_id,
|
|
bundle_name,
|
|
package_id,
|
|
*enabled,
|
|
*manifest_default,
|
|
content,
|
|
)
|
|
.await
|
|
}
|
|
ClusterAction::ImportLocalFile {
|
|
cluster_id,
|
|
content_type,
|
|
path,
|
|
} => PackageStore::import_local_file(path, *content_type, *cluster_id, content)
|
|
.await
|
|
.map(|row| {
|
|
services
|
|
.events
|
|
.notify("Imported").body(format!("Added {}", row.file_name)).send();
|
|
}),
|
|
ClusterAction::SetDedicatedDir {
|
|
cluster_id,
|
|
dedicated,
|
|
} => {
|
|
state
|
|
.clusters
|
|
.set_dedicated_dir(
|
|
*cluster_id,
|
|
*dedicated,
|
|
state.games.is_active(*cluster_id),
|
|
)
|
|
.await
|
|
.map_err(|err| oneclient_content::ContentError::InvalidData {
|
|
reason: err.to_string(),
|
|
})
|
|
}
|
|
ClusterAction::VerifyFiles { cluster_id } => {
|
|
// Reports its own outcome not the generic failure toast a
|
|
// verify that finds nothing wrong is still a useful result
|
|
match oneclient_core::verify_cluster_files(&state, *cluster_id).await {
|
|
Ok(report) => {
|
|
let notify = services.events.notify("Verification complete");
|
|
let notify = notify.body(report.summary());
|
|
if report.unrepairable.is_empty() {
|
|
notify.send();
|
|
} else {
|
|
notify.error().send();
|
|
}
|
|
Ok(())
|
|
}
|
|
Err(err) => Err(oneclient_content::ContentError::InvalidData {
|
|
reason: err.to_string(),
|
|
}),
|
|
}
|
|
}
|
|
};
|
|
result.map_err(|e| e.to_string())
|
|
}
|
|
|
|
async fn on_settled(&self, _keys: &ClusterAction, result: &Result<(), String>) {
|
|
if let Err(err) = result
|
|
&& let Ok(state) = crate::launcher::state()
|
|
{
|
|
state.services.events.notify("Action failed").body(err).error().send();
|
|
}
|
|
invalidate_cluster_queries().await;
|
|
}
|
|
}
|
|
|
|
pub fn use_cluster_mutation() -> UseMutation<ClusterMutation> {
|
|
use_mutation(Mutation::new(ClusterMutation))
|
|
}
|