You've already forked AstralRinth
forked from didirus/AstralRinth
Misc improvements and fixes (#109)
* now utilizing tracing better * better tracing * fix mac vs pc oppositional env var issue * modified loading package * added droppable loadingbarid that sends completion message * loading bar * regressed bug on mac * fixed non-updated loading bar on playground * Loading bar improvements --------- Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
use super::LoadingBarId;
|
||||
use crate::event::{
|
||||
EventError, LoadingBar, LoadingBarType, ProcessPayloadType,
|
||||
ProfilePayloadType,
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use tracing::warn;
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
use crate::event::{
|
||||
@@ -13,6 +15,9 @@ use crate::event::{
|
||||
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.
|
||||
@@ -45,18 +50,34 @@ pub async fn init_loading(
|
||||
bar_type: LoadingBarType,
|
||||
total: f64,
|
||||
title: &str,
|
||||
) -> crate::Result<Uuid> {
|
||||
) -> crate::Result<LoadingBarId> {
|
||||
let event_state = crate::EventState::get().await?;
|
||||
let key = Uuid::new_v4();
|
||||
let key = LoadingBarId(Uuid::new_v4());
|
||||
|
||||
event_state.loading_bars.write().await.insert(
|
||||
key,
|
||||
key.0,
|
||||
LoadingBar {
|
||||
loading_bar_id: key,
|
||||
loading_bar_uuid: key.0,
|
||||
message: title.to_string(),
|
||||
total,
|
||||
current: 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.set_message(title);
|
||||
|
||||
pb
|
||||
},
|
||||
},
|
||||
);
|
||||
// attempt an initial loading_emit event to the frontend
|
||||
@@ -65,13 +86,13 @@ pub async fn init_loading(
|
||||
}
|
||||
|
||||
pub async fn init_or_edit_loading(
|
||||
id: Option<Uuid>,
|
||||
id: Option<LoadingBarId>,
|
||||
bar_type: LoadingBarType,
|
||||
total: f64,
|
||||
title: &str,
|
||||
) -> crate::Result<Uuid> {
|
||||
) -> crate::Result<LoadingBarId> {
|
||||
if let Some(id) = id {
|
||||
edit_loading(id, bar_type, total, title).await?;
|
||||
edit_loading(&id, bar_type, total, title).await?;
|
||||
|
||||
Ok(id)
|
||||
} else {
|
||||
@@ -80,21 +101,27 @@ pub async fn init_or_edit_loading(
|
||||
}
|
||||
|
||||
// Edits a loading bar's type
|
||||
// This also resets the bar's current progress to 0
|
||||
pub async fn edit_loading(
|
||||
id: Uuid,
|
||||
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) {
|
||||
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;
|
||||
#[cfg(feature = "cli")]
|
||||
{
|
||||
bar.cli_progress_bar.reset(); // indicatif::ProgressBar::new(CLI_PROGRESS_BAR_TOTAL as u64);
|
||||
}
|
||||
};
|
||||
|
||||
emit_loading(&id, 0.0, None).await?;
|
||||
emit_loading(id, 0.0, None).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -104,18 +131,19 @@ pub async fn edit_loading(
|
||||
// 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")]
|
||||
pub async fn emit_loading(
|
||||
key: &Uuid,
|
||||
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) {
|
||||
let loading_bar = match loading_bar.get_mut(&key.0) {
|
||||
Some(f) => f,
|
||||
None => {
|
||||
return Err(EventError::NoLoadingBar(*key).into());
|
||||
return Err(EventError::NoLoadingBar(key.0).into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,6 +156,22 @@ pub async fn emit_loading(
|
||||
} else {
|
||||
Some(display_frac)
|
||||
};
|
||||
|
||||
// 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(
|
||||
((loading_bar.current / loading_bar.total)
|
||||
* CLI_PROGRESS_BAR_TOTAL as f64)
|
||||
.round() as u64,
|
||||
);
|
||||
}
|
||||
|
||||
// Emit event to tauri
|
||||
#[cfg(feature = "tauri")]
|
||||
event_state
|
||||
@@ -138,7 +182,7 @@ pub async fn emit_loading(
|
||||
fraction: display_frac,
|
||||
message: message.unwrap_or(&loading_bar.message).to_string(),
|
||||
event: loading_bar.bar_type.clone(),
|
||||
loader_uuid: loading_bar.loading_bar_id,
|
||||
loader_uuid: loading_bar.loading_bar_uuid,
|
||||
},
|
||||
)
|
||||
.map_err(EventError::from)?;
|
||||
@@ -162,6 +206,7 @@ pub async fn emit_warning(message: &str) -> crate::Result<()> {
|
||||
)
|
||||
.map_err(EventError::from)?;
|
||||
}
|
||||
warn!("{}", message);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -235,7 +280,6 @@ macro_rules! count {
|
||||
() => (0usize);
|
||||
( $x:tt $($xs:tt)* ) => (1usize + $crate::count!($($xs)*));
|
||||
}
|
||||
#[cfg(feature = "tauri")]
|
||||
#[macro_export]
|
||||
macro_rules! loading_join {
|
||||
($key:expr, $total:expr, $message:expr; $($task:expr $(,)?)+) => {
|
||||
@@ -272,24 +316,16 @@ macro_rules! loading_join {
|
||||
};
|
||||
|
||||
}
|
||||
#[cfg(not(feature = "tauri"))]
|
||||
#[macro_export]
|
||||
macro_rules! loading_join {
|
||||
($start:expr, $end:expr, $message:expr; $($future:expr $(,)?)+) => {{
|
||||
tokio::try_join!($($future),+)
|
||||
}};
|
||||
}
|
||||
|
||||
// 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
|
||||
#[cfg(feature = "tauri")]
|
||||
pub async fn loading_try_for_each_concurrent<I, F, Fut, T>(
|
||||
stream: I,
|
||||
limit: Option<usize>,
|
||||
key: Option<&Uuid>,
|
||||
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>,
|
||||
@@ -316,31 +352,3 @@ where
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tauri"))]
|
||||
pub async fn loading_try_for_each_concurrent<I, F, Fut, T>(
|
||||
stream: I,
|
||||
limit: Option<usize>,
|
||||
_key: Option<&Uuid>,
|
||||
_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?;
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -48,11 +48,18 @@ impl EventState {
|
||||
Ok(EVENT_STATE.get().ok_or(EventError::NotInitialized)?.clone())
|
||||
}
|
||||
|
||||
// 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;
|
||||
Ok(read.clone())
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// Initialization requires no app handle in non-tauri mode, so we can just use the same function
|
||||
@@ -64,16 +71,84 @@ impl EventState {
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct LoadingBar {
|
||||
pub loading_bar_id: Uuid,
|
||||
// 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,
|
||||
pub bar_type: LoadingBarType,
|
||||
#[cfg(feature = "cli")]
|
||||
#[serde(skip)]
|
||||
pub cli_progress_bar: indicatif::ProgressBar,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
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;
|
||||
let _event = LoadingBarType::StateInit;
|
||||
let _message = "finished".to_string();
|
||||
tokio::spawn(async move {
|
||||
if let Ok(event_state) = crate::EventState::get().await {
|
||||
{
|
||||
let mut bars = event_state.loading_bars.write().await;
|
||||
bars.remove(&loader_uuid);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// When Loading bar is dropped, should attempt to throw out one last event to indicate that the loading bar is done
|
||||
#[cfg(feature = "tauri")]
|
||||
impl Drop for LoadingBar {
|
||||
fn drop(&mut self) {
|
||||
let loader_uuid = self.loading_bar_uuid;
|
||||
let event = self.bar_type.clone();
|
||||
let fraction = self.current / self.total;
|
||||
let cli_progress_bar = self.cli_progress_bar.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
#[cfg(feature = "tauri")]
|
||||
{
|
||||
use tauri::Manager;
|
||||
if let Ok(event_state) = crate::EventState::get().await {
|
||||
let _ = event_state.app.emit_all(
|
||||
"loading",
|
||||
LoadingPayload {
|
||||
fraction: None,
|
||||
message: "Completed".to_string(),
|
||||
event,
|
||||
loader_uuid,
|
||||
},
|
||||
);
|
||||
tracing::debug!(
|
||||
"Exited at {fraction} for loading bar: {:?}",
|
||||
loader_uuid
|
||||
);
|
||||
}
|
||||
}
|
||||
// Emit event to indicatif progress bar arc
|
||||
#[cfg(feature = "cli")]
|
||||
{
|
||||
cli_progress_bar.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum LoadingBarType {
|
||||
StateInit,
|
||||
PackFileDownload {
|
||||
pack_name: Option<String>,
|
||||
pack_version: String,
|
||||
},
|
||||
PackDownload {
|
||||
pack_name: String,
|
||||
pack_id: Option<String>,
|
||||
@@ -124,6 +199,7 @@ pub struct ProfilePayload {
|
||||
pub event: ProfilePayloadType,
|
||||
}
|
||||
#[derive(Serialize, Clone)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ProfilePayloadType {
|
||||
Created,
|
||||
Added, // also triggered when Created
|
||||
|
||||
Reference in New Issue
Block a user