use std::process::ExitCode;
use lernie::cli::{Decided, Stream, Verdict};
use lernie::state::Link;
use lernie::ui::Model;
fn main() -> ExitCode {
let verdict = match lernie::cli::run(std::env::args().skip(1).collect()) {
Decided::Say(verdict) => verdict,
Decided::Entries => rooted(lernie::seat::listing),
Decided::Ask(envelope) => rooted(|root| lernie::seat::ask(root, &envelope)),
Decided::Fanned(envelope) => rooted(|root| lernie::seat::fanned(root, &envelope)),
Decided::Start { address, goal } => {
rooted(|root| lernie::seat::start(root, &address, &goal))
}
Decided::Enroll {
workspace,
name,
grade,
} => rooted(|root| lernie::seat::enroll(root, &workspace, &name, &grade)),
Decided::Window => rooted(window),
};
match verdict.stream {
Stream::Out => println!("{}", verdict.text),
Stream::Err => eprintln!("{}", verdict.text),
}
ExitCode::from(verdict.code)
}
fn rooted(act: impl FnOnce(&std::path::Path) -> Verdict) -> Verdict {
match lernie::paths::data_root() {
Ok(root) => act(&root),
Err(reason) => Verdict::failed(reason),
}
}
fn window(root: &std::path::Path) -> Verdict {
let keep = lernie::paths::state_root().ok();
let mut model = Model {
roster: lernie::seat::channels(root),
aim: keep.as_deref().and_then(lernie::place::read),
..Model::default()
};
let link = Link::new(BEAT);
link.settle(&mut model);
let workers = lernie::offframe::run(&link, root);
let ran = eframe::run_native(
lernie::mark::APP_ID,
eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_app_id(lernie::mark::APP_ID)
.with_icon(egui::IconData {
rgba: lernie::mark::rgba(ICON_PX),
width: u32::from(ICON_PX),
height: u32::from(ICON_PX),
}),
..eframe::NativeOptions::default()
},
Box::new({
let link = link.clone();
move |_| {
Ok(Box::new(Seat {
model: std::mem::take(&mut model),
link,
}))
}
}),
);
link.stop();
for worker in workers {
let _ = worker.join();
}
if let Some(said) = keep
.as_deref()
.and_then(|at| lernie::place::write(at, link.standing().aim).err())
{
eprintln!("the seat could not keep its place: {said}");
}
match ran {
Ok(()) => Verdict::ok(String::new()),
Err(e) => Verdict::failed(format!("the window would not open: {e}")),
}
}
const ICON_PX: u16 = 256;
const BEAT: std::time::Duration = std::time::Duration::from_millis(750);
struct Seat {
model: Model,
link: Link,
}
impl eframe::App for Seat {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
self.link.settle(&mut self.model);
lernie::ui::render(ctx, &mut self.model);
ctx.request_repaint_after(self.link.beat());
}
}