use rnk::cmd::{AppMsg, Cmd};
#[derive(Debug, Clone)]
enum Msg {
DataLoaded(Vec<String>),
LoadError(String),
Tick(u64),
Refresh,
}
fn load_data() -> Cmd<Msg> {
Cmd::perform(|| async {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
Msg::DataLoaded(vec![
"Item 1".to_string(),
"Item 2".to_string(),
"Item 3".to_string(),
])
})
}
fn start_timer(count: u64) -> Cmd<Msg> {
Cmd::tick(std::time::Duration::from_secs(1), move |_| {
Msg::Tick(count + 1)
})
}
fn init_commands() -> Cmd<Msg> {
Cmd::batch(vec![load_data(), start_timer(0)])
}
#[derive(Debug)]
enum ParentMsg {
Child(Msg),
Other,
}
fn map_example() -> Cmd<ParentMsg> {
let child_cmd: Cmd<Msg> = load_data();
child_cmd.map(ParentMsg::Child)
}
fn consume_msg(msg: &Msg) -> usize {
match msg {
Msg::DataLoaded(items) => items.len(),
Msg::LoadError(err) => err.len(),
Msg::Tick(value) => *value as usize,
Msg::Refresh => 0,
}
}
fn consume_parent(msg: &ParentMsg) -> usize {
match msg {
ParentMsg::Child(child) => consume_msg(child),
ParentMsg::Other => 0,
}
}
fn main() {
println!("Typed Command Demo - Type-safe message passing\n");
println!("1. Creating a perform command:");
let cmd: Cmd<Msg> = load_data();
println!(" {:?}\n", cmd);
println!("2. Creating a tick command:");
let cmd: Cmd<Msg> = start_timer(0);
println!(" {:?}\n", cmd);
println!("3. Batching commands:");
let cmd: Cmd<Msg> = init_commands();
println!(" {:?}\n", cmd);
println!("4. Mapping message types:");
let cmd: Cmd<ParentMsg> = map_example();
println!(" {:?}\n", cmd);
println!("5. Sequencing commands:");
let cmd: Cmd<Msg> = Cmd::sequence(vec![
Cmd::sleep(std::time::Duration::from_millis(100)),
load_data(),
]);
println!(" {:?}\n", cmd);
println!("6. Chaining with and_then:");
let cmd: Cmd<Msg> = Cmd::sleep(std::time::Duration::from_millis(50)).and_then(load_data());
println!(" {:?}\n", cmd);
println!("7. Built-in AppMsg types:");
let msgs = vec![
AppMsg::WindowResize {
width: 80,
height: 24,
},
AppMsg::KeyInput("q".to_string()),
AppMsg::Tick(std::time::Instant::now()),
AppMsg::FocusChanged(Some("input-1".to_string())),
AppMsg::Blur,
AppMsg::None,
];
for msg in msgs {
println!(" {:?}", msg);
}
let _ = consume_msg(&Msg::DataLoaded(vec!["demo".to_string()]));
let _ = consume_msg(&Msg::LoadError("oops".to_string()));
let _ = consume_msg(&Msg::Tick(1));
let _ = consume_msg(&Msg::Refresh);
let _ = consume_parent(&ParentMsg::Child(Msg::Refresh));
let _ = consume_parent(&ParentMsg::Other);
println!("\nCmd<M> provides type-safe async operations!");
println!("Use it with the Component trait for TEA-style architecture.");
}