You've already forked AstralRinth
forked from didirus/AstralRinth
Move files in preparation for monorepo migration
This commit is contained in:
415
libs/theseus/src/event/emit.rs
Normal file
415
libs/theseus/src/event/emit.rs
Normal file
@@ -0,0 +1,415 @@
|
||||
use super::LoadingBarId;
|
||||
use crate::{
|
||||
event::{
|
||||
CommandPayload, EventError, LoadingBar, LoadingBarType,
|
||||
ProcessPayloadType, ProfilePayloadType,
|
||||
},
|
||||
prelude::ProfilePathId,
|
||||
state::{ProcessType, SafeProcesses},
|
||||
};
|
||||
use futures::prelude::*;
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
use crate::event::{
|
||||
LoadingPayload, ProcessPayload, ProfilePayload, WarningPayload,
|
||||
};
|
||||
#[cfg(feature = "tauri")]
|
||||
use tauri::Manager;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
const CLI_PROGRESS_BAR_TOTAL: u64 = 1000;
|
||||
|
||||
/*
|
||||
Events are a way we can communciate with the Tauri frontend from the Rust backend.
|
||||
We include a feature flag for Tauri, so that we can compile this code without Tauri.
|
||||
|
||||
To use events, we need to do the following:
|
||||
1) Make sure we are using the tauri feature flag
|
||||
2) Initialize the EventState with EventState::init() *before* initializing the theseus State
|
||||
3) Call emit_x functions to send events to the frontend
|
||||
For emit_loading() specifically, we need to inialize the loading bar with init_loading() first and pass the received loader in
|
||||
|
||||
For example:
|
||||
pub async fn loading_function() -> crate::Result<()> {
|
||||
loading_function()).await;
|
||||
}
|
||||
|
||||
pub async fn loading_function() -> crate::Result<()> {
|
||||
let loading_bar = init_loading(LoadingBarType::StateInit, 100.0, "Loading something long...").await;
|
||||
for i in 0..100 {
|
||||
emit_loading(&loading_bar, 1.0, None).await?;
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// Initialize a loading bar for use in emit_loading
|
||||
/// This will generate a LoadingBarId, which is used to refer to the loading bar uniquely.
|
||||
/// total is the total amount of work to be done- all emissions will be considered a fraction of this value (should be 1 or 100 for simplicity)
|
||||
/// title is the title of the loading bar
|
||||
/// The app will wait for this loading bar to finish before exiting, as it is considered safe.
|
||||
#[theseus_macros::debug_pin]
|
||||
pub async fn init_loading(
|
||||
bar_type: LoadingBarType,
|
||||
total: f64,
|
||||
title: &str,
|
||||
) -> crate::Result<LoadingBarId> {
|
||||
let key = init_loading_unsafe(bar_type, total, title).await?;
|
||||
SafeProcesses::add_uuid(ProcessType::LoadingBar, key.0).await?;
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
/// An unsafe loading bar can be created without adding it to the SafeProcesses list,
|
||||
/// meaning that the app won't ask to wait for it to finish before exiting.
|
||||
#[theseus_macros::debug_pin]
|
||||
pub async fn init_loading_unsafe(
|
||||
bar_type: LoadingBarType,
|
||||
total: f64,
|
||||
title: &str,
|
||||
) -> crate::Result<LoadingBarId> {
|
||||
let event_state = crate::EventState::get().await?;
|
||||
let key = LoadingBarId(Uuid::new_v4());
|
||||
|
||||
event_state.loading_bars.write().await.insert(
|
||||
key.0,
|
||||
LoadingBar {
|
||||
loading_bar_uuid: key.0,
|
||||
message: title.to_string(),
|
||||
total,
|
||||
current: 0.0,
|
||||
last_sent: 0.0,
|
||||
bar_type,
|
||||
#[cfg(feature = "cli")]
|
||||
cli_progress_bar: {
|
||||
let pb = indicatif::ProgressBar::new(CLI_PROGRESS_BAR_TOTAL);
|
||||
|
||||
pb.set_position(0);
|
||||
pb.set_style(
|
||||
indicatif::ProgressStyle::default_bar()
|
||||
.template(
|
||||
"{spinner:.green} [{elapsed_precise}] [{bar:.lime/green}] {pos}/{len} {msg}",
|
||||
).unwrap()
|
||||
.progress_chars("#>-"),
|
||||
);
|
||||
pb
|
||||
},
|
||||
},
|
||||
);
|
||||
// attempt an initial loading_emit event to the frontend
|
||||
emit_loading(&key, 0.0, None).await?;
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
pub async fn init_or_edit_loading(
|
||||
id: Option<LoadingBarId>,
|
||||
bar_type: LoadingBarType,
|
||||
total: f64,
|
||||
title: &str,
|
||||
) -> crate::Result<LoadingBarId> {
|
||||
if let Some(id) = id {
|
||||
edit_loading(&id, bar_type, total, title).await?;
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
init_loading(bar_type, total, title).await
|
||||
}
|
||||
}
|
||||
|
||||
// Edits a loading bar's type
|
||||
// This also resets the bar's current progress to 0
|
||||
pub async fn edit_loading(
|
||||
id: &LoadingBarId,
|
||||
bar_type: LoadingBarType,
|
||||
total: f64,
|
||||
title: &str,
|
||||
) -> crate::Result<()> {
|
||||
let event_state = crate::EventState::get().await?;
|
||||
|
||||
if let Some(bar) = event_state.loading_bars.write().await.get_mut(&id.0) {
|
||||
bar.bar_type = bar_type;
|
||||
bar.total = total;
|
||||
bar.message = title.to_string();
|
||||
bar.current = 0.0;
|
||||
bar.last_sent = 0.0;
|
||||
#[cfg(feature = "cli")]
|
||||
{
|
||||
bar.cli_progress_bar.reset(); // indicatif::ProgressBar::new(CLI_PROGRESS_BAR_TOTAL as u64);
|
||||
}
|
||||
};
|
||||
|
||||
emit_loading(id, 0.0, None).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emit_loading emits a loading event to the frontend
|
||||
// key refers to the loading bar to update
|
||||
// increment refers to by what relative increment to the loading struct's total to update
|
||||
// message is the message to display on the loading bar- if None, use the loading bar's default one
|
||||
// By convention, fraction is the fraction of the progress bar that is filled
|
||||
#[allow(unused_variables)]
|
||||
#[tracing::instrument(level = "debug")]
|
||||
#[theseus_macros::debug_pin]
|
||||
pub async fn emit_loading(
|
||||
key: &LoadingBarId,
|
||||
increment_frac: f64,
|
||||
message: Option<&str>,
|
||||
) -> crate::Result<()> {
|
||||
let event_state = crate::EventState::get().await?;
|
||||
|
||||
let mut loading_bar = event_state.loading_bars.write().await;
|
||||
let loading_bar = match loading_bar.get_mut(&key.0) {
|
||||
Some(f) => f,
|
||||
None => {
|
||||
return Err(EventError::NoLoadingBar(key.0).into());
|
||||
}
|
||||
};
|
||||
|
||||
// Tick up loading bar
|
||||
loading_bar.current += increment_frac;
|
||||
let display_frac = loading_bar.current / loading_bar.total;
|
||||
let opt_display_frac = if display_frac >= 1.0 {
|
||||
None // by convention, when its done, we submit None
|
||||
// any further updates will be ignored (also sending None)
|
||||
} else {
|
||||
Some(display_frac)
|
||||
};
|
||||
|
||||
if f64::abs(display_frac - loading_bar.last_sent) > 0.005 {
|
||||
// Emit event to indicatif progress bar
|
||||
#[cfg(feature = "cli")]
|
||||
{
|
||||
loading_bar.cli_progress_bar.set_message(
|
||||
message
|
||||
.map(|x| x.to_string())
|
||||
.unwrap_or(loading_bar.message.clone()),
|
||||
);
|
||||
loading_bar.cli_progress_bar.set_position(
|
||||
(display_frac * CLI_PROGRESS_BAR_TOTAL as f64).round() as u64,
|
||||
);
|
||||
}
|
||||
|
||||
//Emit event to tauri
|
||||
#[cfg(feature = "tauri")]
|
||||
event_state
|
||||
.app
|
||||
.emit_all(
|
||||
"loading",
|
||||
LoadingPayload {
|
||||
fraction: opt_display_frac,
|
||||
message: message
|
||||
.unwrap_or(&loading_bar.message)
|
||||
.to_string(),
|
||||
event: loading_bar.bar_type.clone(),
|
||||
loader_uuid: loading_bar.loading_bar_uuid,
|
||||
},
|
||||
)
|
||||
.map_err(EventError::from)?;
|
||||
|
||||
loading_bar.last_sent = display_frac;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emit_warning(message)
|
||||
#[allow(dead_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub async fn emit_warning(message: &str) -> crate::Result<()> {
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
let event_state = crate::EventState::get().await?;
|
||||
event_state
|
||||
.app
|
||||
.emit_all(
|
||||
"warning",
|
||||
WarningPayload {
|
||||
message: message.to_string(),
|
||||
},
|
||||
)
|
||||
.map_err(EventError::from)?;
|
||||
}
|
||||
tracing::warn!("{}", message);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emit_offline(bool)
|
||||
// This is used to emit an event to the frontend that the app is offline after a refresh (or online)
|
||||
#[allow(dead_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub async fn emit_offline(offline: bool) -> crate::Result<()> {
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
let event_state = crate::EventState::get().await?;
|
||||
event_state
|
||||
.app
|
||||
.emit_all("offline", offline)
|
||||
.map_err(EventError::from)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emit_command(CommandPayload::Something { something })
|
||||
// ie: installing a pack, opening an .mrpack, etc
|
||||
// Generally used for url deep links and file opens that we we want to handle in the frontend
|
||||
#[allow(dead_code)]
|
||||
#[allow(unused_variables)]
|
||||
pub async fn emit_command(command: CommandPayload) -> crate::Result<()> {
|
||||
tracing::debug!("Command: {}", serde_json::to_string(&command)?);
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
let event_state = crate::EventState::get().await?;
|
||||
event_state
|
||||
.app
|
||||
.emit_all("command", command)
|
||||
.map_err(EventError::from)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emit_process(uuid, pid, event, message)
|
||||
#[allow(unused_variables)]
|
||||
pub async fn emit_process(
|
||||
uuid: Uuid,
|
||||
pid: u32,
|
||||
event: ProcessPayloadType,
|
||||
message: &str,
|
||||
) -> crate::Result<()> {
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
let event_state = crate::EventState::get().await?;
|
||||
event_state
|
||||
.app
|
||||
.emit_all(
|
||||
"process",
|
||||
ProcessPayload {
|
||||
uuid,
|
||||
pid,
|
||||
event,
|
||||
message: message.to_string(),
|
||||
},
|
||||
)
|
||||
.map_err(EventError::from)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// emit_profile(path, event)
|
||||
#[allow(unused_variables)]
|
||||
pub async fn emit_profile(
|
||||
uuid: Uuid,
|
||||
profile_path_id: &ProfilePathId,
|
||||
name: &str,
|
||||
event: ProfilePayloadType,
|
||||
) -> crate::Result<()> {
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
let path = profile_path_id.get_full_path().await?;
|
||||
let event_state = crate::EventState::get().await?;
|
||||
event_state
|
||||
.app
|
||||
.emit_all(
|
||||
"profile",
|
||||
ProfilePayload {
|
||||
uuid,
|
||||
profile_path_id: profile_path_id.clone(),
|
||||
path,
|
||||
name: name.to_string(),
|
||||
event,
|
||||
},
|
||||
)
|
||||
.map_err(EventError::from)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// loading_join! macro
|
||||
// loading_join!(key: Option<&LoadingBarId>, total: f64, message: Option<&str>; task1, task2, task3...)
|
||||
// This will submit a loading event with the given message for each task as they complete
|
||||
// task1, task2, task3 are async tasks that yuo want to to join on await on
|
||||
// Key is the key to use for which loading bar to submit these results to- a LoadingBarId. If None, it does nothing
|
||||
// Total is the total amount of progress that the loading bar should take up by all futures in this (will be split evenly amongst them).
|
||||
// If message is Some(t) you will overwrite this loading bar's message with a custom one
|
||||
// For example, if you want the tasks to range as 0.1, 0.2, 0.3 (of the progress bar), you would do:
|
||||
// loading_join!(loading_bar, 0.1; task1, task2, task3)
|
||||
// This will await on each of the tasks, and as each completes, it will emit a loading event for 0.033, 0.066, 0.099, etc
|
||||
// This should function as a drop-in replacement for tokio::try_join_all! in most cases- except the function *itself* calls ? rather than needing it.
|
||||
#[macro_export]
|
||||
macro_rules! count {
|
||||
() => (0usize);
|
||||
( $x:tt $($xs:tt)* ) => (1usize + $crate::count!($($xs)*));
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! loading_join {
|
||||
($key:expr, $total:expr, $message:expr; $($task:expr $(,)?)+) => {
|
||||
{
|
||||
let key = $key;
|
||||
let message : Option<&str> = $message;
|
||||
|
||||
let num_futures = $crate::count!($($task)*);
|
||||
let increment = $total / num_futures as f64;
|
||||
|
||||
|
||||
paste::paste! {
|
||||
$( let [ <unique_name $task>] = {
|
||||
{
|
||||
let key = key.clone();
|
||||
let message = message.clone();
|
||||
async move {
|
||||
let res = $task.await;
|
||||
if let Some(key) = key {
|
||||
$crate::event::emit::emit_loading(key, increment, message).await?;
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
};)+
|
||||
}
|
||||
|
||||
paste::paste! {
|
||||
tokio::try_join! (
|
||||
$( [ <unique_name $task>] ),+
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// A drop in replacement to try_for_each_concurrent that emits loading events as it goes
|
||||
// Key is the key to use for which loading bar- a LoadingBarId. If None, does nothing
|
||||
// Total is the total amount of progress that the loading bar should take up by all futures in this (will be split evenly amongst them).
|
||||
// If message is Some(t) you will overwrite this loading bar's message with a custom one
|
||||
// num_futs is the number of futures that will be run, which is needed as we allow Iterator to be passed in, which doesn't have a size
|
||||
#[tracing::instrument(skip(stream, f))]
|
||||
#[theseus_macros::debug_pin]
|
||||
pub async fn loading_try_for_each_concurrent<I, F, Fut, T>(
|
||||
stream: I,
|
||||
limit: Option<usize>,
|
||||
key: Option<&LoadingBarId>,
|
||||
total: f64,
|
||||
num_futs: usize, // num is in here as we allow Iterator to be passed in, which doesn't have a size
|
||||
message: Option<&str>,
|
||||
f: F,
|
||||
) -> crate::Result<()>
|
||||
where
|
||||
I: futures::TryStreamExt<Error = crate::Error> + TryStream<Ok = T>,
|
||||
F: FnMut(T) -> Fut + Send,
|
||||
Fut: Future<Output = crate::Result<()>> + Send,
|
||||
T: Send,
|
||||
{
|
||||
let mut f = f;
|
||||
stream
|
||||
.try_for_each_concurrent(limit, |item| {
|
||||
let f = f(item);
|
||||
async move {
|
||||
f.await?;
|
||||
if let Some(key) = key {
|
||||
emit_loading(key, total / (num_futs as f64), message)
|
||||
.await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
278
libs/theseus/src/event/mod.rs
Normal file
278
libs/theseus/src/event/mod.rs
Normal file
@@ -0,0 +1,278 @@
|
||||
//! Theseus state management system
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, path::PathBuf, sync::Arc};
|
||||
use tokio::sync::OnceCell;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::prelude::ProfilePathId;
|
||||
use crate::state::SafeProcesses;
|
||||
|
||||
pub mod emit;
|
||||
|
||||
// Global event state
|
||||
// Stores the Tauri app handle and other event-related state variables
|
||||
static EVENT_STATE: OnceCell<Arc<EventState>> = OnceCell::const_new();
|
||||
pub struct EventState {
|
||||
/// Tauri app
|
||||
#[cfg(feature = "tauri")]
|
||||
pub app: tauri::AppHandle,
|
||||
pub loading_bars: RwLock<HashMap<Uuid, LoadingBar>>,
|
||||
}
|
||||
|
||||
impl EventState {
|
||||
#[cfg(feature = "tauri")]
|
||||
pub async fn init(app: tauri::AppHandle) -> crate::Result<Arc<Self>> {
|
||||
EVENT_STATE
|
||||
.get_or_try_init(|| async {
|
||||
Ok(Arc::new(Self {
|
||||
app,
|
||||
loading_bars: RwLock::new(HashMap::new()),
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.cloned()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tauri"))]
|
||||
pub async fn init() -> crate::Result<Arc<Self>> {
|
||||
EVENT_STATE
|
||||
.get_or_try_init(|| async {
|
||||
Ok(Arc::new(Self {
|
||||
loading_bars: RwLock::new(HashMap::new()),
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.cloned()
|
||||
}
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
pub async fn get() -> crate::Result<Arc<Self>> {
|
||||
Ok(EVENT_STATE.get().ok_or(EventError::NotInitialized)?.clone())
|
||||
}
|
||||
|
||||
// Initialization requires no app handle in non-tauri mode, so we can just use the same function
|
||||
#[cfg(not(feature = "tauri"))]
|
||||
pub async fn get() -> crate::Result<Arc<Self>> {
|
||||
Self::init().await
|
||||
}
|
||||
|
||||
// Values provided should not be used directly, as they are clones and are not guaranteed to be up-to-date
|
||||
pub async fn list_progress_bars() -> crate::Result<HashMap<Uuid, LoadingBar>>
|
||||
{
|
||||
let value = Self::get().await?;
|
||||
let read = value.loading_bars.read().await;
|
||||
|
||||
let mut display_list: HashMap<Uuid, LoadingBar> = HashMap::new();
|
||||
for (uuid, loading_bar) in read.iter() {
|
||||
display_list.insert(*uuid, loading_bar.clone());
|
||||
}
|
||||
|
||||
Ok(display_list)
|
||||
}
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
pub async fn get_main_window() -> crate::Result<Option<tauri::Window>> {
|
||||
use tauri::Manager;
|
||||
let value = Self::get().await?;
|
||||
Ok(value.app.get_window("main"))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct LoadingBar {
|
||||
// loading_bar_uuid not be used directly by external functions as it may not reflect the current state of the loading bar/hashmap
|
||||
pub loading_bar_uuid: Uuid,
|
||||
pub message: String,
|
||||
pub total: f64,
|
||||
pub current: f64,
|
||||
#[serde(skip)]
|
||||
pub last_sent: f64,
|
||||
pub bar_type: LoadingBarType,
|
||||
#[cfg(feature = "cli")]
|
||||
#[serde(skip)]
|
||||
pub cli_progress_bar: indicatif::ProgressBar,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct LoadingBarId(Uuid);
|
||||
|
||||
// When Loading bar id is dropped, we should remove it from the hashmap
|
||||
impl Drop for LoadingBarId {
|
||||
fn drop(&mut self) {
|
||||
let loader_uuid = self.0;
|
||||
tokio::spawn(async move {
|
||||
if let Ok(event_state) = EventState::get().await {
|
||||
let mut bars = event_state.loading_bars.write().await;
|
||||
|
||||
#[cfg(any(feature = "tauri", feature = "cli"))]
|
||||
if let Some(bar) = bars.remove(&loader_uuid) {
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
let loader_uuid = bar.loading_bar_uuid;
|
||||
let event = bar.bar_type.clone();
|
||||
let fraction = bar.current / bar.total;
|
||||
|
||||
use tauri::Manager;
|
||||
let _ = event_state.app.emit_all(
|
||||
"loading",
|
||||
LoadingPayload {
|
||||
fraction: None,
|
||||
message: "Completed".to_string(),
|
||||
event,
|
||||
loader_uuid,
|
||||
},
|
||||
);
|
||||
tracing::trace!(
|
||||
"Exited at {fraction} for loading bar: {:?}",
|
||||
loader_uuid
|
||||
);
|
||||
}
|
||||
|
||||
// Emit event to indicatif progress bar arc
|
||||
#[cfg(feature = "cli")]
|
||||
{
|
||||
let cli_progress_bar = bar.cli_progress_bar;
|
||||
cli_progress_bar.finish();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "tauri", feature = "cli")))]
|
||||
bars.remove(&loader_uuid);
|
||||
}
|
||||
// complete calls state, and since a LoadingBarId is created in state initialization, we only complete if its already initializaed
|
||||
// to avoid an infinite loop.
|
||||
if crate::State::initialized() {
|
||||
let _ = SafeProcesses::complete(
|
||||
crate::state::ProcessType::LoadingBar,
|
||||
loader_uuid,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum LoadingBarType {
|
||||
StateInit,
|
||||
JavaDownload {
|
||||
version: u32,
|
||||
},
|
||||
PackFileDownload {
|
||||
profile_path: PathBuf,
|
||||
pack_name: String,
|
||||
icon: Option<String>,
|
||||
pack_version: String,
|
||||
},
|
||||
PackDownload {
|
||||
profile_path: PathBuf,
|
||||
pack_name: String,
|
||||
icon: Option<PathBuf>,
|
||||
pack_id: Option<String>,
|
||||
pack_version: Option<String>,
|
||||
},
|
||||
MinecraftDownload {
|
||||
profile_path: PathBuf,
|
||||
profile_name: String,
|
||||
},
|
||||
ProfileUpdate {
|
||||
profile_path: PathBuf,
|
||||
profile_name: String,
|
||||
},
|
||||
ZipExtract {
|
||||
profile_path: PathBuf,
|
||||
profile_name: String,
|
||||
},
|
||||
ConfigChange {
|
||||
new_path: PathBuf,
|
||||
},
|
||||
CopyProfile {
|
||||
import_location: PathBuf,
|
||||
profile_name: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct LoadingPayload {
|
||||
pub event: LoadingBarType,
|
||||
pub loader_uuid: Uuid,
|
||||
pub fraction: Option<f64>, // by convention, if optional, it means the loading is done
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct OfflinePayload {
|
||||
pub offline: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct WarningPayload {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
#[serde(tag = "event")]
|
||||
pub enum CommandPayload {
|
||||
InstallMod {
|
||||
id: String,
|
||||
},
|
||||
InstallVersion {
|
||||
id: String,
|
||||
},
|
||||
InstallModpack {
|
||||
id: String,
|
||||
},
|
||||
RunMRPack {
|
||||
// run or install .mrpack
|
||||
path: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct ProcessPayload {
|
||||
pub uuid: Uuid, // processes in state are going to be identified by UUIDs, as they might change to different processes
|
||||
pub pid: u32,
|
||||
pub event: ProcessPayloadType,
|
||||
pub message: String,
|
||||
}
|
||||
#[derive(Serialize, Clone, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ProcessPayloadType {
|
||||
Launched,
|
||||
Updated, // eg: if the MinecraftChild changes to its post-command process instead of the Minecraft process
|
||||
Finished,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct ProfilePayload {
|
||||
pub uuid: Uuid,
|
||||
pub profile_path_id: ProfilePathId,
|
||||
pub path: PathBuf,
|
||||
pub name: String,
|
||||
pub event: ProfilePayloadType,
|
||||
}
|
||||
#[derive(Serialize, Clone)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ProfilePayloadType {
|
||||
Created,
|
||||
Added, // also triggered when Created
|
||||
Synced,
|
||||
Edited,
|
||||
Removed,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EventError {
|
||||
#[error("Event state was not properly initialized")]
|
||||
NotInitialized,
|
||||
|
||||
#[error("Non-existent loading bar of key: {0}")]
|
||||
NoLoadingBar(Uuid),
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
#[error("Tauri error: {0}")]
|
||||
TauriError(#[from] tauri::Error),
|
||||
}
|
||||
Reference in New Issue
Block a user