use crate::ui::Model;
pub mod acts;
pub mod start;
pub const NOWHERE: &str = "pick a workspace to say anything or begin anything";
pub const SEND: &str = "send";
pub const INTERRUPT: &str = "interrupt";
pub const NUDGE: &str = "nudge";
pub fn render(ui: &mut egui::Ui, model: &mut Model) {
let Some(aim) = model.aim.clone() else {
ui.label(NOWHERE);
return;
};
let Some(agent) = model.conversation.clone() else {
start::render(ui, model, &aim);
return;
};
if let Some(held) = model.start.clone().filter(|_| model.pending().is_some()) {
ui.label(held.line());
return;
}
let entry = ui.add(
egui::TextEdit::singleline(&mut model.draft)
.id(egui::Id::new(crate::ui::keys::BOX_ID))
.desired_width(f32::INFINITY)
.hint_text(SEND),
);
let entered = entry.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
let mut sent = entered;
let mut cut = false;
let mut nudged = false;
ui.horizontal_wrapped(|ui| {
let deposit = ui.button(SEND);
crate::ui::act::tag(&deposit, &[crate::verbs::MESSAGE.word]);
sent |= deposit.clicked();
let cutting = ui.button(INTERRUPT);
crate::ui::act::tag(&cutting, &[crate::verbs::INTERRUPT.word]);
cut = cutting.clicked();
let advance = ui.button(NUDGE);
crate::ui::act::tag(&advance, &[crate::verbs::NUDGE.word]);
nudged = advance.clicked();
});
if sent {
fire(model, crate::verbs::message, &aim.address, &agent);
}
if cut {
fire(model, crate::verbs::interrupt, &aim.address, &agent);
}
if nudged {
model
.outbox
.push(crate::ui::Posted::act(crate::verbs::nudge(
aim.address.clone(),
agent.clone(),
)));
}
acts::render(ui, model, &aim, &agent);
}
fn fire(
model: &mut Model,
door: fn(String, String, String) -> serde_json::Value,
workspace: &str,
agent: &str,
) {
if model.draft.trim().is_empty() {
return;
}
let said = std::mem::take(&mut model.draft);
model.outbox.push(crate::ui::Posted::act(door(
workspace.to_owned(),
agent.to_owned(),
said,
)));
}
#[cfg(test)]
mod tests;