mirror of
https://github.com/modrinth/code.git
synced 2026-08-26 01:26:23 +00:00
* 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
923 lines
27 KiB
Rust
923 lines
27 KiB
Rust
use crate::api::Result;
|
|
use dashmap::DashMap;
|
|
use path_util::SafeRelativeUtf8UnixPathBuf;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::path::{Path, PathBuf};
|
|
use theseus::DownloadReason;
|
|
use theseus::data::{
|
|
AppliedContentSetPatch, ContentItem, Dependency,
|
|
EditInstance as CoreEditInstance, InstanceInstallCandidate,
|
|
InstanceInstallTarget, InstanceLaunchOverridesPatch,
|
|
InstanceLink as CoreInstanceLink, InstanceMetadata, LinkedModpackInfo,
|
|
SharedInstanceAttachment as CoreSharedInstanceAttachment,
|
|
SharedInstanceRole,
|
|
};
|
|
use theseus::instance::InstallProjectWithDependenciesRequest;
|
|
use theseus::instance::QuickPlayType;
|
|
use theseus::prelude::*;
|
|
use theseus::server_address::ServerAddress;
|
|
|
|
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
|
tauri::plugin::Builder::new("instance")
|
|
.invoke_handler(tauri::generate_handler![
|
|
instance_remove,
|
|
instance_get,
|
|
instance_get_many,
|
|
instance_list,
|
|
instance_get_projects,
|
|
instance_get_installed_project_ids,
|
|
instance_get_install_candidates,
|
|
instance_content,
|
|
instance_get_content_items,
|
|
instance_refresh_content_updates,
|
|
instance_get_dependencies_as_content_items,
|
|
instance_get_linked_modpack_info,
|
|
instance_get_linked_modpack_content,
|
|
instance_get_optimal_jre_key,
|
|
instance_get_full_path,
|
|
instance_get_mod_full_path,
|
|
instance_check_installed,
|
|
instance_update_all,
|
|
instance_update_project,
|
|
instance_add_project_from_version,
|
|
instance_install_project_with_dependencies,
|
|
instance_switch_project_version_with_dependencies,
|
|
instance_add_project_from_path,
|
|
instance_is_file_on_modrinth,
|
|
instance_toggle_disable_project,
|
|
instance_set_project_locked,
|
|
instance_remove_project,
|
|
instance_update_managed_modrinth_version,
|
|
instance_repair_managed_modrinth,
|
|
instance_run,
|
|
instance_kill,
|
|
instance_edit,
|
|
instance_edit_icon,
|
|
instance_share_can_current_user_use,
|
|
instance_share_get_users,
|
|
instance_share_invite_users,
|
|
instance_share_create_invite_link,
|
|
instance_share_get_invites,
|
|
instance_share_revoke_invite,
|
|
instance_share_remove_users,
|
|
instance_share_get_publish_preview,
|
|
instance_share_publish,
|
|
instance_share_unlink,
|
|
instance_share_unpublish,
|
|
instance_export_mrpack,
|
|
instance_get_pack_export_candidates,
|
|
])
|
|
.build()
|
|
}
|
|
|
|
#[derive(Serialize, Debug, Clone)]
|
|
pub struct Instance {
|
|
pub id: String,
|
|
pub path: String,
|
|
pub install_stage: String,
|
|
pub launcher_feature_version: String,
|
|
pub name: String,
|
|
pub icon_path: Option<String>,
|
|
pub game_version: String,
|
|
pub protocol_version: Option<u32>,
|
|
pub loader: ModLoader,
|
|
pub loader_version: Option<String>,
|
|
pub groups: Vec<String>,
|
|
pub link: Option<InstanceLink>,
|
|
pub shared_instance: Option<SharedInstanceAttachment>,
|
|
pub quarantined: bool,
|
|
pub update_channel: ReleaseChannel,
|
|
pub created: chrono::DateTime<chrono::Utc>,
|
|
pub modified: chrono::DateTime<chrono::Utc>,
|
|
pub last_played: Option<chrono::DateTime<chrono::Utc>>,
|
|
pub submitted_time_played: u64,
|
|
pub recent_time_played: u64,
|
|
pub java_path: Option<String>,
|
|
pub extra_launch_args: Option<Vec<String>>,
|
|
pub custom_env_vars: Option<Vec<(String, String)>>,
|
|
pub memory: Option<MemorySettings>,
|
|
pub force_fullscreen: Option<bool>,
|
|
pub game_resolution: Option<WindowSize>,
|
|
pub hooks: Hooks,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
#[serde(tag = "type", rename_all = "snake_case")]
|
|
pub enum InstanceLink {
|
|
ModrinthModpack {
|
|
project_id: String,
|
|
version_id: String,
|
|
},
|
|
ServerProject {
|
|
project_id: String,
|
|
},
|
|
ServerProjectModpack {
|
|
server_project_id: String,
|
|
content_project_id: Option<String>,
|
|
content_version_id: String,
|
|
project_id: Option<String>,
|
|
version_id: Option<String>,
|
|
},
|
|
ImportedModpack {
|
|
project_id: Option<String>,
|
|
version_id: Option<String>,
|
|
name: Option<String>,
|
|
version_number: Option<String>,
|
|
filename: Option<String>,
|
|
},
|
|
ModrinthHosting {
|
|
server_id: String,
|
|
instance_ids: Vec<String>,
|
|
active_instance_id: Option<String>,
|
|
},
|
|
SharedInstance {
|
|
modpack_project_id: Option<String>,
|
|
modpack_version_id: Option<String>,
|
|
},
|
|
}
|
|
|
|
#[derive(Serialize, Debug, Clone)]
|
|
pub struct SharedInstanceAttachment {
|
|
pub id: String,
|
|
pub role: SharedInstanceRole,
|
|
pub manager_id: Option<String>,
|
|
pub server_manager_name: Option<String>,
|
|
pub server_manager_icon_url: Option<String>,
|
|
pub linked_user_id: Option<String>,
|
|
pub status: String,
|
|
pub applied_version: Option<i32>,
|
|
pub latest_version: Option<i32>,
|
|
}
|
|
|
|
impl From<CoreSharedInstanceAttachment> for SharedInstanceAttachment {
|
|
fn from(attachment: CoreSharedInstanceAttachment) -> Self {
|
|
Self {
|
|
id: attachment.id.to_string(),
|
|
role: attachment.role,
|
|
manager_id: attachment.manager_id,
|
|
server_manager_name: attachment.server_manager_name,
|
|
server_manager_icon_url: attachment.server_manager_icon_url,
|
|
linked_user_id: attachment.linked_user_id,
|
|
status: attachment.status.as_str().to_string(),
|
|
applied_version: attachment.applied_version,
|
|
latest_version: attachment.latest_version,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
pub struct EditInstance {
|
|
pub name: Option<String>,
|
|
|
|
pub game_version: Option<String>,
|
|
pub loader: Option<ModLoader>,
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub loader_version: Option<Option<String>>,
|
|
|
|
pub groups: Option<Vec<String>>,
|
|
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub link: Option<Option<InstanceLink>>,
|
|
pub update_channel: Option<ReleaseChannel>,
|
|
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub java_path: Option<Option<String>>,
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub extra_launch_args: Option<Option<Vec<String>>>,
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub custom_env_vars: Option<Option<Vec<(String, String)>>>,
|
|
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub memory: Option<Option<MemorySettings>>,
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub force_fullscreen: Option<Option<bool>>,
|
|
#[serde(
|
|
default,
|
|
skip_serializing_if = "Option::is_none",
|
|
with = "serde_with::rust::double_option"
|
|
)]
|
|
pub game_resolution: Option<Option<WindowSize>>,
|
|
pub hooks: Option<Hooks>,
|
|
}
|
|
|
|
impl From<InstanceMetadata> for Instance {
|
|
fn from(metadata: InstanceMetadata) -> Self {
|
|
Self {
|
|
id: metadata.instance.id,
|
|
path: metadata.instance.path,
|
|
install_stage: metadata.instance.install_stage.as_str().to_string(),
|
|
launcher_feature_version: metadata
|
|
.instance
|
|
.launcher_feature_version
|
|
.as_str()
|
|
.to_string(),
|
|
name: metadata.instance.name,
|
|
icon_path: metadata.instance.icon_path,
|
|
game_version: metadata.applied_content_set.game_version,
|
|
protocol_version: metadata.applied_content_set.protocol_version,
|
|
loader: metadata.applied_content_set.loader,
|
|
loader_version: metadata.applied_content_set.loader_version,
|
|
groups: metadata.groups,
|
|
link: InstanceLink::from_core(metadata.link),
|
|
shared_instance: metadata.shared_instance.map(Into::into),
|
|
quarantined: metadata.quarantined,
|
|
update_channel: metadata.instance.update_channel,
|
|
created: metadata.instance.created,
|
|
modified: metadata.instance.modified,
|
|
last_played: metadata.instance.last_played,
|
|
submitted_time_played: metadata.instance.submitted_time_played,
|
|
recent_time_played: metadata.instance.recent_time_played,
|
|
java_path: metadata.launch_overrides.java_path,
|
|
extra_launch_args: metadata.launch_overrides.extra_launch_args,
|
|
custom_env_vars: metadata.launch_overrides.custom_env_vars,
|
|
memory: metadata.launch_overrides.memory,
|
|
force_fullscreen: metadata.launch_overrides.force_fullscreen,
|
|
game_resolution: metadata.launch_overrides.game_resolution,
|
|
hooks: metadata.launch_overrides.hooks,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl InstanceLink {
|
|
fn from_core(link: CoreInstanceLink) -> Option<Self> {
|
|
match link {
|
|
CoreInstanceLink::Unmanaged => None,
|
|
CoreInstanceLink::ModrinthModpack {
|
|
project_id,
|
|
version_id,
|
|
} => Some(Self::ModrinthModpack {
|
|
project_id,
|
|
version_id,
|
|
}),
|
|
CoreInstanceLink::ServerProject { project_id } => {
|
|
Some(Self::ServerProject { project_id })
|
|
}
|
|
CoreInstanceLink::ServerProjectModpack {
|
|
server_project_id,
|
|
content_project_id,
|
|
content_version_id,
|
|
} => Some(Self::ServerProjectModpack {
|
|
project_id: Some(server_project_id.clone()),
|
|
version_id: Some(content_version_id.clone()),
|
|
server_project_id,
|
|
content_project_id: Some(content_project_id),
|
|
content_version_id,
|
|
}),
|
|
CoreInstanceLink::ImportedModpack {
|
|
project_id,
|
|
version_id,
|
|
name,
|
|
version_number,
|
|
filename,
|
|
} => Some(Self::ImportedModpack {
|
|
project_id,
|
|
version_id,
|
|
name,
|
|
version_number,
|
|
filename,
|
|
}),
|
|
CoreInstanceLink::ModrinthHosting {
|
|
server_id,
|
|
instance_ids,
|
|
active_instance_id,
|
|
} => Some(Self::ModrinthHosting {
|
|
server_id: server_id.to_string(),
|
|
instance_ids: instance_ids
|
|
.into_iter()
|
|
.map(|id| id.to_string())
|
|
.collect(),
|
|
active_instance_id: active_instance_id.map(|id| id.to_string()),
|
|
}),
|
|
CoreInstanceLink::SharedInstance {
|
|
modpack_project_id,
|
|
modpack_version_id,
|
|
} => Some(Self::SharedInstance {
|
|
modpack_project_id,
|
|
modpack_version_id,
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn into_core(self) -> Result<CoreInstanceLink> {
|
|
match self {
|
|
Self::ModrinthModpack {
|
|
project_id,
|
|
version_id,
|
|
} => Ok(CoreInstanceLink::ModrinthModpack {
|
|
project_id,
|
|
version_id,
|
|
}),
|
|
Self::ServerProject { project_id } => {
|
|
Ok(CoreInstanceLink::ServerProject { project_id })
|
|
}
|
|
Self::ServerProjectModpack {
|
|
server_project_id,
|
|
content_project_id,
|
|
content_version_id,
|
|
..
|
|
} => Ok(CoreInstanceLink::ServerProjectModpack {
|
|
server_project_id,
|
|
content_project_id: content_project_id.unwrap_or_default(),
|
|
content_version_id,
|
|
}),
|
|
Self::ImportedModpack {
|
|
project_id,
|
|
version_id,
|
|
name,
|
|
version_number,
|
|
filename,
|
|
} => Ok(CoreInstanceLink::ImportedModpack {
|
|
project_id,
|
|
version_id,
|
|
name,
|
|
version_number,
|
|
filename,
|
|
}),
|
|
Self::ModrinthHosting {
|
|
server_id,
|
|
instance_ids,
|
|
active_instance_id,
|
|
} => Ok(CoreInstanceLink::ModrinthHosting {
|
|
server_id: server_id.parse().map_err(|err| {
|
|
theseus::Error::from(theseus::ErrorKind::InputError(
|
|
format!("Invalid server id: {err}"),
|
|
))
|
|
})?,
|
|
instance_ids: instance_ids
|
|
.into_iter()
|
|
.map(|id| {
|
|
id.parse().map_err(|err| {
|
|
theseus::Error::from(
|
|
theseus::ErrorKind::InputError(format!(
|
|
"Invalid hosted instance id: {err}"
|
|
)),
|
|
)
|
|
})
|
|
})
|
|
.collect::<std::result::Result<Vec<_>, _>>()?,
|
|
active_instance_id: active_instance_id
|
|
.map(|id| {
|
|
id.parse().map_err(|err| {
|
|
theseus::Error::from(
|
|
theseus::ErrorKind::InputError(format!(
|
|
"Invalid active instance id: {err}"
|
|
)),
|
|
)
|
|
})
|
|
})
|
|
.transpose()?,
|
|
}),
|
|
Self::SharedInstance {
|
|
modpack_project_id,
|
|
modpack_version_id,
|
|
} => Ok(CoreInstanceLink::SharedInstance {
|
|
modpack_project_id,
|
|
modpack_version_id,
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn edit_to_core(edit_instance: EditInstance) -> Result<CoreEditInstance> {
|
|
Ok(CoreEditInstance {
|
|
install_stage: None,
|
|
launcher_feature_version: None,
|
|
name: edit_instance.name,
|
|
icon_path: None,
|
|
update_channel: edit_instance.update_channel,
|
|
groups: edit_instance.groups,
|
|
link: edit_instance
|
|
.link
|
|
.map(|link| match link {
|
|
Some(link) => link.into_core(),
|
|
None => Ok(CoreInstanceLink::Unmanaged),
|
|
})
|
|
.transpose()?,
|
|
launch_overrides: Some(InstanceLaunchOverridesPatch {
|
|
java_path: edit_instance.java_path,
|
|
extra_launch_args: edit_instance.extra_launch_args,
|
|
custom_env_vars: edit_instance.custom_env_vars,
|
|
memory: edit_instance.memory,
|
|
force_fullscreen: edit_instance.force_fullscreen,
|
|
game_resolution: edit_instance.game_resolution,
|
|
hooks: edit_instance.hooks,
|
|
}),
|
|
content_set_patch: Some(AppliedContentSetPatch {
|
|
source_kind: None,
|
|
game_version: edit_instance.game_version,
|
|
protocol_version: Some(None),
|
|
loader: edit_instance.loader,
|
|
loader_version: edit_instance.loader_version,
|
|
}),
|
|
last_played: None,
|
|
submitted_time_played: None,
|
|
recent_time_played: None,
|
|
})
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_remove(instance_id: &str) -> Result<()> {
|
|
theseus::instance::remove(instance_id).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get(instance_id: &str) -> Result<Option<Instance>> {
|
|
Ok(theseus::instance::get(instance_id)
|
|
.await?
|
|
.map(Instance::from))
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_many(
|
|
instance_ids: Vec<String>,
|
|
) -> Result<Vec<Instance>> {
|
|
let ids = instance_ids.iter().map(|x| &**x).collect::<Vec<&str>>();
|
|
Ok(theseus::instance::get_many(&ids)
|
|
.await?
|
|
.into_iter()
|
|
.map(Instance::from)
|
|
.collect())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_list() -> Result<Vec<Instance>> {
|
|
Ok(theseus::instance::list()
|
|
.await?
|
|
.into_iter()
|
|
.map(Instance::from)
|
|
.collect())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_projects(
|
|
instance_id: &str,
|
|
cache_behaviour: Option<CacheBehaviour>,
|
|
) -> Result<DashMap<String, ContentFile>> {
|
|
Ok(theseus::instance::get_projects(instance_id, cache_behaviour).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_installed_project_ids(
|
|
instance_id: &str,
|
|
) -> Result<Vec<String>> {
|
|
Ok(theseus::instance::get_installed_project_ids(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_install_candidates(
|
|
project_id: &str,
|
|
project_type: ProjectType,
|
|
targets: Vec<InstanceInstallTarget>,
|
|
) -> Result<Vec<InstanceInstallCandidate>> {
|
|
Ok(theseus::instance::get_install_candidates(
|
|
project_id,
|
|
project_type,
|
|
targets,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_content(
|
|
instance_id: &str,
|
|
cache_behaviour: Option<CacheBehaviour>,
|
|
) -> Result<Vec<ContentItem>> {
|
|
instance_get_content_items(instance_id, cache_behaviour).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_content_items(
|
|
instance_id: &str,
|
|
cache_behaviour: Option<CacheBehaviour>,
|
|
) -> Result<Vec<ContentItem>> {
|
|
Ok(
|
|
theseus::instance::get_content_items(instance_id, cache_behaviour)
|
|
.await?,
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_refresh_content_updates(instance_id: &str) -> Result<()> {
|
|
Ok(theseus::instance::refresh_content_updates(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_dependencies_as_content_items(
|
|
dependencies: Vec<Dependency>,
|
|
cache_behaviour: Option<CacheBehaviour>,
|
|
) -> Result<Vec<ContentItem>> {
|
|
Ok(theseus::instance::get_dependencies_as_content_items(
|
|
dependencies,
|
|
cache_behaviour,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_linked_modpack_info(
|
|
instance_id: &str,
|
|
cache_behaviour: Option<CacheBehaviour>,
|
|
) -> Result<Option<LinkedModpackInfo>> {
|
|
Ok(
|
|
theseus::instance::get_linked_modpack_info(
|
|
instance_id,
|
|
cache_behaviour,
|
|
)
|
|
.await?,
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_linked_modpack_content(
|
|
instance_id: &str,
|
|
cache_behaviour: Option<CacheBehaviour>,
|
|
) -> Result<Vec<ContentItem>> {
|
|
Ok(theseus::instance::get_linked_modpack_content(
|
|
instance_id,
|
|
cache_behaviour,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_full_path(instance_id: &str) -> Result<PathBuf> {
|
|
Ok(theseus::instance::get_full_path(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_mod_full_path(
|
|
instance_id: &str,
|
|
project_path: &str,
|
|
) -> Result<PathBuf> {
|
|
Ok(theseus::instance::get_mod_full_path(instance_id, project_path).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_optimal_jre_key(
|
|
instance_id: &str,
|
|
) -> Result<Option<JavaVersion>> {
|
|
Ok(theseus::instance::get_optimal_jre_key(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_check_installed(
|
|
instance_id: &str,
|
|
project_id: &str,
|
|
) -> Result<bool> {
|
|
let check_project_id = project_id;
|
|
|
|
if let Ok(projects) =
|
|
theseus::instance::get_projects(instance_id, None).await
|
|
{
|
|
Ok(projects.into_iter().any(|(_, project)| {
|
|
project
|
|
.metadata
|
|
.as_ref()
|
|
.is_some_and(|metadata| check_project_id == metadata.project_id)
|
|
}))
|
|
} else {
|
|
Ok(false)
|
|
}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_update_all(
|
|
instance_id: &str,
|
|
) -> Result<HashMap<String, String>> {
|
|
Ok(theseus::instance::update_all_projects(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_update_project(
|
|
instance_id: &str,
|
|
project_path: &str,
|
|
) -> Result<String> {
|
|
Ok(
|
|
theseus::instance::update_project(instance_id, project_path, None)
|
|
.await?,
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_add_project_from_version(
|
|
instance_id: &str,
|
|
version_id: &str,
|
|
reason: DownloadReason,
|
|
dependent_on_version_id: Option<String>,
|
|
) -> Result<String> {
|
|
Ok(theseus::instance::add_project_from_version(
|
|
instance_id,
|
|
version_id,
|
|
reason,
|
|
dependent_on_version_id,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_install_project_with_dependencies(
|
|
instance_id: &str,
|
|
request: InstallProjectWithDependenciesRequest,
|
|
) -> Result<ResolveContentPlan> {
|
|
Ok(theseus::instance::install_project_with_dependencies(
|
|
instance_id,
|
|
request,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_switch_project_version_with_dependencies(
|
|
instance_id: &str,
|
|
project_path: &str,
|
|
version_id: &str,
|
|
) -> Result<String> {
|
|
Ok(theseus::instance::switch_project_version_with_dependencies(
|
|
instance_id,
|
|
project_path,
|
|
version_id,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_add_project_from_path(
|
|
instance_id: &str,
|
|
project_path: &Path,
|
|
project_type: Option<ProjectType>,
|
|
) -> Result<String> {
|
|
Ok(theseus::instance::add_project_from_path(
|
|
instance_id,
|
|
project_path,
|
|
project_type,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_is_file_on_modrinth(project_path: &Path) -> Result<bool> {
|
|
Ok(theseus::instance::is_file_on_modrinth(project_path).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_toggle_disable_project(
|
|
instance_id: &str,
|
|
project_path: &str,
|
|
desired_enabled: Option<bool>,
|
|
) -> Result<String> {
|
|
Ok(theseus::instance::toggle_disable_project(
|
|
instance_id,
|
|
project_path,
|
|
desired_enabled,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_set_project_locked(
|
|
instance_id: &str,
|
|
project_path: &str,
|
|
locked: bool,
|
|
) -> Result<()> {
|
|
theseus::instance::set_project_locked(instance_id, project_path, locked)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_remove_project(
|
|
instance_id: &str,
|
|
project_path: &str,
|
|
) -> Result<()> {
|
|
theseus::instance::remove_project(instance_id, project_path).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_update_managed_modrinth_version(
|
|
instance_id: String,
|
|
version_id: String,
|
|
) -> Result<theseus::install::InstallJobSnapshot> {
|
|
Ok(theseus::instance::update_managed_modrinth_version(
|
|
&instance_id,
|
|
&version_id,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_repair_managed_modrinth(
|
|
instance_id: &str,
|
|
) -> Result<theseus::install::InstallJobSnapshot> {
|
|
Ok(theseus::instance::repair_managed_modrinth(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_export_mrpack(
|
|
instance_id: &str,
|
|
export_location: PathBuf,
|
|
included_overrides: Vec<String>,
|
|
excluded_overrides: Vec<String>,
|
|
version_id: Option<String>,
|
|
description: Option<String>,
|
|
name: Option<String>,
|
|
) -> Result<()> {
|
|
theseus::instance::export_mrpack(
|
|
instance_id,
|
|
export_location,
|
|
included_overrides,
|
|
excluded_overrides,
|
|
version_id,
|
|
description,
|
|
name,
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_get_pack_export_candidates(
|
|
instance_id: &str,
|
|
parent: Option<SafeRelativeUtf8UnixPathBuf>,
|
|
) -> Result<Vec<theseus::instance::PackExportCandidate>> {
|
|
Ok(theseus::instance::get_pack_export_candidates_for_parent(
|
|
instance_id,
|
|
parent,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_run(
|
|
instance_id: &str,
|
|
server_address: Option<String>,
|
|
) -> Result<ProcessMetadata> {
|
|
let quick_play = match server_address {
|
|
Some(addr) => QuickPlayType::Server(ServerAddress::Unresolved(addr)),
|
|
None => QuickPlayType::None,
|
|
};
|
|
Ok(theseus::instance::run(instance_id, quick_play).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_kill(instance_id: &str) -> Result<()> {
|
|
theseus::instance::kill(instance_id).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_edit(
|
|
instance_id: &str,
|
|
edit_instance: EditInstance,
|
|
) -> Result<()> {
|
|
theseus::instance::edit(instance_id, edit_to_core(edit_instance)?).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_edit_icon(
|
|
instance_id: &str,
|
|
icon_path: Option<&Path>,
|
|
) -> Result<()> {
|
|
theseus::instance::edit_icon(instance_id, icon_path).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_can_current_user_use() -> Result<bool> {
|
|
Ok(theseus::instance::can_active_user_use_shared_instances().await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_get_users(
|
|
instance_id: &str,
|
|
) -> Result<theseus::instance::SharedInstanceUsers> {
|
|
Ok(theseus::instance::get_shared_instance_users(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_invite_users(
|
|
instance_id: &str,
|
|
user_ids: Vec<String>,
|
|
) -> Result<theseus::instance::SharedInstanceUsers> {
|
|
Ok(
|
|
theseus::instance::invite_shared_instance_users(instance_id, user_ids)
|
|
.await?,
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_create_invite_link(
|
|
instance_id: &str,
|
|
max_age_seconds: Option<i32>,
|
|
max_uses: Option<i32>,
|
|
replace_invite_id: Option<String>,
|
|
) -> Result<theseus::instance::SharedInstanceInviteLink> {
|
|
Ok(theseus::instance::create_shared_instance_invite_link(
|
|
instance_id,
|
|
max_age_seconds,
|
|
max_uses,
|
|
replace_invite_id,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_get_invites(
|
|
instance_id: &str,
|
|
) -> Result<Vec<theseus::instance::SharedInstanceInvite>> {
|
|
Ok(theseus::instance::get_shared_instance_invites(instance_id).await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_revoke_invite(
|
|
instance_id: &str,
|
|
invite_id: String,
|
|
) -> Result<()> {
|
|
Ok(
|
|
theseus::instance::revoke_shared_instance_invite(
|
|
instance_id,
|
|
invite_id,
|
|
)
|
|
.await?,
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_remove_users(
|
|
instance_id: &str,
|
|
user_ids: Vec<String>,
|
|
has_pending_recipients: bool,
|
|
) -> Result<theseus::instance::SharedInstanceUsers> {
|
|
Ok(theseus::instance::remove_shared_instance_users(
|
|
instance_id,
|
|
user_ids,
|
|
has_pending_recipients,
|
|
)
|
|
.await?)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_get_publish_preview(
|
|
instance_id: &str,
|
|
) -> Result<Option<theseus::instance::SharedInstancePublishPreview>> {
|
|
Ok(
|
|
theseus::instance::get_shared_instance_publish_preview(instance_id)
|
|
.await?,
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_publish(
|
|
instance_id: &str,
|
|
config_paths: Vec<String>,
|
|
) -> Result<SharedInstanceAttachment> {
|
|
Ok(
|
|
theseus::instance::publish_shared_instance(instance_id, config_paths)
|
|
.await?
|
|
.into(),
|
|
)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_unlink(instance_id: &str) -> Result<()> {
|
|
theseus::instance::unlink_shared_instance(instance_id).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn instance_share_unpublish(instance_id: &str) -> Result<()> {
|
|
theseus::instance::unpublish_shared_instance(instance_id).await?;
|
|
Ok(())
|
|
}
|