use std::{fmt::Debug, sync::Arc};
use async_trait::async_trait;
use r3bl_redux::*;
use r3bl_rs_utils_core::*;
use tokio::sync::RwLock;
use crate::*;
#[derive(Clone, Default)]
pub struct DialogComponent<S, A>
where
S: Default + Clone + PartialEq + Debug + Sync + Send,
A: Default + Clone + Sync + Send,
{
pub id: FlexBoxIdType,
pub dialog_engine: DialogEngine,
pub on_dialog_press_handler: Option<OnDialogPressFn<S, A>>,
pub on_dialog_editor_change_handler: Option<OnDialogEditorChangeFn<S, A>>,
}
pub mod impl_component {
use super::*;
#[async_trait]
impl<S, A> Component<S, A> for DialogComponent<S, A>
where
S: HasDialogBuffer + Default + Clone + PartialEq + Debug + Sync + Send,
A: Default + Clone + Sync + Send,
{
fn get_id(&self) -> FlexBoxIdType { self.id }
async fn handle_event(
&mut self,
args: ComponentScopeArgs<'_, S, A>,
input_event: &InputEvent,
) -> CommonResult<EventPropagation> {
let ComponentScopeArgs {
state,
shared_store,
shared_tw_data,
component_registry,
window_size,
} = args;
let dialog_engine_args = {
DialogEngineArgs {
shared_tw_data,
shared_store,
state,
component_registry,
self_id: self.get_id(),
dialog_engine: &mut self.dialog_engine,
dialog_buffer: state.get_dialog_buffer(),
window_size,
}
};
match DialogEngineApi::apply_event(dialog_engine_args, input_event).await? {
DialogEngineApplyResponse::DialogChoice(dialog_choice) => {
let _ = component_registry.has_focus.reset_modal_id();
if let Some(handler) = &self.on_dialog_press_handler {
handler(dialog_choice, shared_store);
};
Ok(EventPropagation::ConsumedRerender)
}
DialogEngineApplyResponse::UpdateEditorBuffer(new_editor_buffer) => {
if let Some(handler) = &self.on_dialog_editor_change_handler {
handler(new_editor_buffer, shared_store);
};
Ok(EventPropagation::Consumed)
}
_ => Ok(EventPropagation::Propagate),
}
}
async fn render(
&mut self,
args: ComponentScopeArgs<'_, S, A>,
current_box: &FlexBox,
) -> CommonResult<RenderPipeline> {
let ComponentScopeArgs {
state,
shared_store,
shared_tw_data,
component_registry,
window_size,
} = args;
let dialog_engine_args = {
DialogEngineArgs {
shared_tw_data,
shared_store,
state,
component_registry,
self_id: self.get_id(),
dialog_engine: &mut self.dialog_engine,
dialog_buffer: state.get_dialog_buffer(),
window_size,
}
};
DialogEngineApi::render_engine(dialog_engine_args, current_box).await
}
}
}
pub mod constructor {
use super::*;
impl<S, A> DialogComponent<S, A>
where
S: Default + Clone + PartialEq + Debug + Sync + Send,
A: Default + Clone + Sync + Send,
{
pub fn new(
id: FlexBoxIdType,
on_dialog_press_handler: OnDialogPressFn<S, A>,
on_dialog_editor_change_handler: OnDialogEditorChangeFn<S, A>,
maybe_style_border: Option<Style>,
maybe_style_title: Option<Style>,
maybe_style_editor: Option<Style>,
) -> Self {
Self {
dialog_engine: DialogEngine {
maybe_style_border,
maybe_style_title,
maybe_style_editor,
..Default::default()
},
id,
on_dialog_press_handler: Some(on_dialog_press_handler),
on_dialog_editor_change_handler: Some(on_dialog_editor_change_handler),
}
}
pub fn new_shared(
id: FlexBoxIdType,
on_dialog_press_handler: OnDialogPressFn<S, A>,
on_dialog_editor_change_handler: OnDialogEditorChangeFn<S, A>,
maybe_style_border: Option<Style>,
maybe_style_title: Option<Style>,
maybe_style_editor: Option<Style>,
) -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(DialogComponent::new(
id,
on_dialog_press_handler,
on_dialog_editor_change_handler,
maybe_style_border,
maybe_style_title,
maybe_style_editor,
)))
}
}
}
pub mod misc {
use super::*;
pub trait HasDialogBuffer {
fn get_dialog_buffer(&self) -> &DialogBuffer;
}
#[derive(Debug)]
pub enum DialogChoice {
Yes(String),
No,
}
pub type OnDialogPressFn<S, A> = fn(DialogChoice, &SharedStore<S, A>);
pub type OnDialogEditorChangeFn<S, A> = fn(EditorBuffer, &SharedStore<S, A>);
}
pub use misc::*;