added settings API + fixed bug (#62)

* added settings API + fixed bug

* removed redundant API funcs

* comment clarifications

---------

Co-authored-by: Wyatt <wyatt@modrinth.com>
This commit is contained in:
Wyatt Verchere 2023-04-03 13:46:04 -07:00 committed by GitHub
parent 6a05276a21
commit a13b7a2566
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 140 additions and 22 deletions

View File

@ -2,6 +2,7 @@
pub mod auth;
pub mod profile;
pub mod profile_create;
pub mod settings;
pub mod data {
pub use crate::state::{
@ -15,6 +16,6 @@ pub mod prelude {
auth::{self, Credentials},
data::*,
profile::{self, Profile},
profile_create, State,
profile_create, settings, State,
};
}

View File

@ -204,12 +204,15 @@ pub async fn run(
let memory = profile.memory.unwrap_or(settings.memory);
let resolution = profile.resolution.unwrap_or(settings.game_resolution);
let env_args = &settings.custom_env_args;
let mc_process = crate::launcher::launch_minecraft(
&profile.metadata.game_version,
&profile.metadata.loader_version,
&profile.path,
java_install,
java_args,
env_args,
wrapper,
&memory,
&resolution,

View File

@ -0,0 +1,24 @@
//! Theseus profile management interface
pub use crate::{
state::{
Hooks, JavaSettings, MemorySettings, Profile, Settings, WindowSize,
},
State,
};
/// Gets entire settings
#[tracing::instrument]
pub async fn get() -> crate::Result<Settings> {
let state = State::get().await?;
let settings = state.settings.read().await;
Ok(settings.clone())
}
/// Sets entire settings
#[tracing::instrument]
pub async fn set(settings: Settings) -> crate::Result<()> {
let state = State::get().await?;
// Replaces the settings struct in the RwLock with the passed argument
*state.settings.write().await = settings;
Ok(())
}

View File

@ -53,6 +53,7 @@ pub async fn launch_minecraft(
instance_path: &Path,
java_install: &Path,
java_args: &[String],
env_args: &[(String, String)],
wrapper: &Option<String>,
memory: &st::MemorySettings,
resolution: &st::WindowSize,
@ -173,6 +174,8 @@ pub async fn launch_minecraft(
None => Command::new(String::from(java_install.to_string_lossy())),
};
let env_args = Vec::from(env_args);
command
.args(
args::get_jvm_arguments(
@ -213,6 +216,7 @@ pub async fn launch_minecraft(
)
.current_dir(instance_path.clone())
.env_clear()
.envs(env_args)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());

View File

@ -17,6 +17,7 @@ pub struct Settings {
pub memory: MemorySettings,
pub game_resolution: WindowSize,
pub custom_java_args: Vec<String>,
pub custom_env_args: Vec<(String, String)>,
pub java_8_path: Option<PathBuf>,
pub java_17_path: Option<PathBuf>,
pub default_user: Option<uuid::Uuid>,
@ -31,6 +32,7 @@ impl Default for Settings {
memory: MemorySettings::default(),
game_resolution: WindowSize::default(),
custom_java_args: Vec::new(),
custom_env_args: Vec::new(),
java_8_path: None,
java_17_path: None,
default_user: None,

View File

@ -6,6 +6,7 @@ pub mod auth;
pub mod profile;
pub mod profile_create;
pub mod settings;
pub type Result<T> = std::result::Result<T, TheseusGuiError>;

View File

@ -0,0 +1,17 @@
use crate::api::Result;
use theseus::prelude::*;
// Get full settings
// invoke('settings_get')
#[tauri::command]
pub async fn settings_get() -> Result<Settings> {
Ok(settings::get().await?)
}
// Set full settings
// invoke('settings_set', settings)
#[tauri::command]
pub async fn settings_set(settings: Settings) -> Result<()> {
settings::set(settings).await?;
Ok(())
}

View File

@ -38,6 +38,8 @@ fn main() {
api::auth::auth_has_user,
api::auth::auth_users,
api::auth::auth_get_user,
api::settings::settings_get,
api::settings::settings_set,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

View File

@ -14,7 +14,8 @@ import { invoke } from '@tauri-apps/api/tauri'
// }
/// Authenticate a user with Hydra - part 1
/// This begins the authentication flow quasi-synchronously, returning a URL to visit (that the user will sign in at)
/// This begins the authentication flow quasi-synchronously
/// This returns a URL to be opened in a browser
export async function authenticate_begin_flow() {
return await invoke('auth_authenticate_begin_flow')
}
@ -22,30 +23,34 @@ export async function authenticate_begin_flow() {
/// Authenticate a user with Hydra - part 2
/// This completes the authentication flow quasi-synchronously, returning the sign-in credentials
/// (and also adding the credentials to the state)
/// This returns a Credentials object
export async function authenticate_await_completion() {
return await invoke('auth_authenticate_await_completion')
}
/// Refresh some credentials using Hydra, if needed
// user is UUID
// update_name is bool
/// user is UUID
/// update_name is bool
/// Returns a Credentials object
export async function refresh(user, update_name) {
return await invoke('auth_refresh', user, update_name)
return await invoke('auth_refresh', { user, update_name })
}
/// Remove a user account from the database
// user is UUID
/// user is UUID
export async function remove_user(user) {
return await invoke('auth_remove_user', user)
return await invoke('auth_remove_user', { user })
}
// Add a path as a profile in-memory
// user is UUID
/// Returns a bool
export async function has_user(user) {
return await invoke('auth_has_user', user)
return await invoke('auth_has_user', { user })
}
// Remove a profile
/// Returns a list of users
/// Returns an Array of Credentials
export async function users() {
return await invoke('auth_users')
}
@ -53,6 +58,7 @@ export async function users() {
// Get a user by UUID
// Prefer to use refresh() instead of this because it will refresh the credentials
// user is UUID
// Returns Credentials (of user)
export async function get_user(user) {
return await invoke('auth_get_user', user)
return await invoke('auth_get_user', { user })
}

View File

@ -10,42 +10,47 @@ export async function addDefaultInstance() {
return await invoke('profile_create_empty')
}
// Add empty default instance
/// Add empty default instance
/// Returns a path to the profile created
export async function create() {
return await invoke('profile_create')
}
// Add a profile to the in-memory state
export async function add(profile) {
return await invoke('profile_add', profile)
return await invoke('profile_add', { profile })
}
// Add a path as a profile in-memory
export async function add_path(path) {
return await invoke('profile_add_path', path)
return await invoke('profile_add_path', { path })
}
// Remove a profile
export async function remove(path) {
return await invoke('profile_remove', path)
return await invoke('profile_remove', { path })
}
// Get a profile by path
// Returns a Profile
export async function get(path) {
return await invoke('profile_get', path)
return await invoke('profile_get', { path })
}
// Check if a pathed profile is already managed by Theseus
// Returns bool
export async function is_managed(path) {
return await invoke('profile_is_managed', path)
return await invoke('profile_is_managed', { path })
}
// Check if a pathed profile is loaded
// Returns bool
export async function is_loaded(path) {
return await invoke('profile_is_loaded', path)
return await invoke('profile_is_loaded', { path })
}
// Get a copy of the profile set
// Returns hashmap of path -> Profile
export async function list() {
return await invoke('profile_list')
}
@ -53,21 +58,21 @@ export async function list() {
// Run Minecraft using a pathed profile
// Returns PID of child
export async function run(path, credentials) {
return await invoke('profile_run', path, credentials)
return await invoke('profile_run', { path, credentials })
}
// Run Minecraft using a pathed profile
// Waits for end
export async function run_wait(path, credentials) {
return await invoke('run_wait', path, credentials)
return await invoke('profile_run_wait', { path, credentials })
}
// Tries to kill a running minecraft process (if PID is still stored)
export async function kill(child_pid) {
return await invoke('profile_kill', child_pid)
return await invoke('profile_kill', { child_pid })
}
// Wait for a running minecraft process (a Child)
export async function wait_for(child_pid) {
return await invoke('profile_wait_for', child_pid)
return await invoke('profile_wait_for', { child_pid })
}

View File

@ -0,0 +1,53 @@
/**
* All theseus API calls return serialized values (both return values and errors);
* So, for example, addDefaultInstance creates a blank Profile object, where the Rust struct is serialized,
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/tauri'
// Settings object
/*
Settings {
"memory": MemorySettings,
"game_resolution": [int int],
"custom_java_args": [String ...],
"custom_env_args" : [(string, string) ... ]>,
"java_8_path": Path (can be null),
"java_17_path": Path (can be null),
"default_user": Uuid string (can be null),
"hooks": Hooks,
"max_concurrent_downloads": uint,
"version": u32,
}
Memorysettings {
"min": u32, can be null,
"max": u32,
}
*/
// An example test function for getting/setting settings
export async function test() {
// First, print settings and store them to an object
let settings = await get()
console.log(JSON.stringify(settings))
// Then set some random settings in that object
settings.java_8_path = '/example/path'
// Set the new settings object
await set(settings)
console.log(JSON.stringify(await get()))
}
// Get full settings object
export async function get() {
return await invoke('settings_get')
}
// Set full settings object
export async function set(settings) {
return await invoke('settings_set', { settings })
}

View File

@ -87,7 +87,7 @@ async fn main() -> theseus::Result<()> {
// Attempt to get the default user, if it exists, and refresh their credentials
let default_user_uuid = {
let settings = st.settings.read().await;
settings.default_user.clone()
settings.default_user
};
let credentials = if let Some(uuid) = default_user_uuid {
println!("Attempting to refresh existing authentication.");