use crate::reply::config::{Config, Setting};
use crate::reply::lineages::Lineage;
use crate::ui::{Model, theme};
use crate::verbs::Where;
pub const OPEN: &str = "config…";
pub const CLOSE: &str = "done";
pub const HEADING: &str = "config";
pub const NOTHING_PICKED: &str = "pick a file to read";
pub const NOT_ANSWERED: &str = "waiting to hear which lineages this wall holds";
pub const NO_LINEAGES: &str = "this wall holds no config lineage";
pub const NOT_READ: &str = "waiting to hear what this file holds";
pub const NO_BYTES: &str = "this file has no bytes yet";
pub const NO_SETTINGS: &str = "this file has no typed settings — its bytes are the whole of it";
pub fn render(ui: &mut egui::Ui, model: &mut Model) -> bool {
if model.configuring.is_none() {
return false;
}
ui.heading(HEADING);
if let Some(aim) = model.aim.clone() {
ui.label(format!("on {} — {}", aim.address, aim.channel));
}
ui.horizontal_wrapped(|ui| {
if ui.button(CLOSE).clicked() {
model.close_configuring();
}
});
ui.separator();
egui::ScrollArea::vertical()
.id_salt(HEADING)
.auto_shrink(false)
.show(ui, |ui| {
destinations(ui, model);
ui.separator();
file(ui, model);
});
true
}
fn destinations(ui: &mut egui::Ui, model: &mut Model) {
let Some(aim) = model.aim.clone() else {
return;
};
ui.horizontal_wrapped(|ui| {
for at in [
Where::Brazen {
workspace: aim.address.clone(),
},
Where::LitanyModels,
Where::Cadence,
] {
pick(ui, model, &at);
}
});
match model.lineages.clone() {
None => {
ui.label(NOT_ANSWERED);
}
Some(rows) if rows.is_empty() => {
ui.label(NO_LINEAGES);
}
Some(rows) => {
for row in &rows {
lineage(ui, model, row, &aim.address);
}
}
}
}
fn lineage(ui: &mut egui::Ui, model: &mut Model, row: &Lineage, workspace: &str) {
ui.colored_label(
theme::tone_ink(&crate::reply::convs::Tone::Weak),
row.line(),
);
ui.horizontal_wrapped(|ui| {
for path in &row.files {
pick(
ui,
model,
&Where::Branch {
workspace: workspace.to_owned(),
lineage: row.name.clone(),
path: path.clone(),
},
);
}
});
}
fn pick(ui: &mut egui::Ui, model: &mut Model, at: &Where) {
let chosen = model.configured().as_ref() == Some(at);
let control = ui.selectable_label(chosen, at.label());
crate::ui::act::tag(&control, &[crate::verbs::CONFIG]);
if control.clicked() {
model.read_config(at);
}
}
fn file(ui: &mut egui::Ui, model: &Model) {
let Some(at) = model.configured() else {
ui.label(NOTHING_PICKED);
return;
};
ui.label(at.label());
let Some(held) = model.config.clone() else {
ui.label(NOT_READ);
return;
};
settings(ui, &held);
ui.separator();
if held.text.is_empty() {
ui.label(NO_BYTES);
return;
}
ui.label(held.text);
}
fn settings(ui: &mut egui::Ui, held: &Config) {
if held.settings.is_empty() {
ui.colored_label(
theme::tone_ink(&crate::reply::convs::Tone::Weak),
NO_SETTINGS,
);
return;
}
for row in &held.settings {
setting(ui, row);
}
}
fn setting(ui: &mut egui::Ui, row: &Setting) {
let weak = theme::tone_ink(&crate::reply::convs::Tone::Weak);
ui.horizontal_wrapped(|ui| {
ui.label(format!("{}.{}", row.entry, row.name));
ui.label(row.value.clone());
ui.colored_label(weak, row.control.says());
});
ui.colored_label(weak, row.help.clone());
if let Some(fault) = &row.fault {
ui.colored_label(theme::NOTICE, fault.clone());
}
}
#[cfg(test)]
mod tests;