Starts working on an Error flash.

This commit is contained in:
2026-01-28 22:02:11 +01:00
parent 9d3c5afb07
commit d86d0d2f32
6 changed files with 143 additions and 123 deletions

View File

@@ -1,11 +1,11 @@
use std::fmt::Display;
use super::*;
use crate::flows::own::Own;
use async_trait::async_trait;
use gamenight_api_client_rs::apis::default_api::PostGamesError;
use gamenight_api_client_rs::models::AddGameRequestBody;
use inquire::Text;
use serde_json::Value;
use std::fmt::Display;
#[derive(Clone)]
pub struct AddGame {
@@ -24,7 +24,13 @@ impl<'a> Flow<'a> for AddGame {
let add_game_request = AddGameRequestBody {
name
};
let game_id_response = state.api.post_games(Some(add_game_request)).await?;
let game_id_response = match state.api.post_games(Some(add_game_request)).await {
Ok(x) => x,
Err(x) => {
let error_string = get_error_message::<PostGamesError, FlowError>(&x)?;
return create_error_flow_result(async |state| {Ok((FlowOutcome::Successful, state))}, x, state, error_string);
}
};
let own_flow = Own::new(Uuid::parse_str(&game_id_response.game_id)?);
return self.continue_with(state, &own_flow).await;
@@ -33,6 +39,18 @@ impl<'a> Flow<'a> for AddGame {
}
}
fn get_error_message<T, E>(error: &Error<T>) -> Result<String, FlowError> {
match error {
Error::Reqwest(x) => {Ok(x.to_string())}
Error::Serde(x) => {Ok(x.to_string())}
Error::Io(x) => {Ok(x.to_string())}
Error::ResponseError(inner) => {
let json : Value = serde_json::from_str(&inner.content)?;
Ok(json["message"].to_string())
}
}
}
impl Display for AddGame {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Add Game")

View File

@@ -84,7 +84,7 @@ impl Connect {
#[async_trait]
impl<'a> Flow<'a> for Connect {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> where FlowResult<'a> : Send {
let mut instance = if let Some(instance) = self.instance.clone() {
instance
} else if let Some(instance) = self.prompt_new_instance(&state.gamenight_configuration)? {
@@ -106,20 +106,16 @@ impl<'a> Flow<'a> for Connect {
let login_flow = Login::new();
let (outcome, state) = login_flow.run(state).await?;
if outcome == FlowOutcome::Successful {
self.update_state_on_logon(&mut instance, state, &instance_name)?;
let gamenight_menu_flow = GamenightMenu::new();
gamenight_menu_flow.run(state).await
}
else {
Ok((outcome, state))
match outcome {
FlowOutcome::Successful => {
self.update_state_on_logon(&mut instance, state, &instance_name)?;
let gamenight_menu_flow = GamenightMenu::new();
gamenight_menu_flow.run(state).await
},
_ => Ok((outcome, state))
}
}
}
}

View File

@@ -1,5 +1,6 @@
use gamenight_api_client_rs::apis::default_api::{DefaultApi, DefaultApiClient};
use std::{fmt::Display, num::ParseIntError};
use std::pin::Pin;
use std::sync::{Arc, MutexGuard, PoisonError};
use async_trait::async_trait;
use chrono::ParseError;
@@ -157,22 +158,6 @@ impl From<jsonwebtoken::errors::Error> for FlowError {
}
}
impl From<PoisonError<&mut Configuration>> for FlowError {
fn from(value: PoisonError<&mut Configuration>) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<PoisonError<Configuration>> for FlowError {
fn from(value: PoisonError<Configuration>) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<PoisonError<std::sync::MutexGuard<'_, Configuration>>> for FlowError {
fn from(value: PoisonError<MutexGuard<'_, Configuration>>) -> Self {
Self {
@@ -181,14 +166,32 @@ impl From<PoisonError<std::sync::MutexGuard<'_, Configuration>>> for FlowError {
}
}
#[derive(PartialEq)]
pub enum FlowOutcome {
impl From<serde_json::Error> for FlowError {
fn from(value: serde_json::Error) -> Self {
Self {
error: value.to_string()
}
}
}
pub enum FlowOutcome<'a> {
Successful,
Cancelled,
Error(Box<dyn Fn(&'a mut GamenightState) -> Pin<Box<dyn Future<Output = FlowResult> + Send + 'a>> + Send>, String),
Abort,
}
type FlowResult<'a> = Result<(FlowOutcome, &'a mut GamenightState), FlowError>;
unsafe impl Send for FlowOutcome<'_> { }
type FlowResult<'a> = Result<(FlowOutcome<'a>, &'a mut GamenightState), FlowError>;
fn create_error_flow_result<'a, F, Fut, T>(f: F, _error: Error<T>, state: &'a mut GamenightState, error_string: String) -> FlowResult<'a>
where
F: Fn(&'a mut GamenightState) -> Fut + 'static + Send,
Fut: Future<Output = FlowResult<'a>> + 'a + Send,
{
Ok((FlowOutcome::Error(Box::new(move |state| Box::pin(f(state))), error_string), state))
}
dyn_clone::clone_trait_object!(for<'a> Flow<'a>);
@@ -198,13 +201,15 @@ pub trait Flow<'a>: Sync + DynClone + Send + Display {
clear_screen::clear();
if let Some(choice) = choice {
let (outcome, new_state) = choice.run(state).await?;
if outcome == FlowOutcome::Abort {
Ok((FlowOutcome::Successful, new_state))
match outcome {
FlowOutcome::Abort => Ok((FlowOutcome::Successful, new_state)),
FlowOutcome::Error(recovery, _err) => {
let (_, state) = recovery(new_state).await?;
Ok((FlowOutcome::Successful, state))
},
_ => self.run(new_state).await
}
else {
self.run(new_state).await
}
}
else {
Ok((FlowOutcome::Cancelled, state))