use crate::ui::{Model, theme};
pub const WORD: &str = "find";
pub const HEADING: &str = "find text";
pub const FIND: &str = "find";
pub const NEEDS_WORDS: &str = "type what to look for and this becomes live";
pub const NOT_ASKED: &str = "nothing has been looked for yet";
pub const NOTHING: &str = "this engine found none of it — try fewer words";
pub const NOT_ADDRESSABLE: &str = "a hit says where it is in the engine's own path spelling, which no gesture \
from this box can carry — so these are read here and aimed at by hand";
pub fn render(ui: &mut egui::Ui, model: &mut Model) -> bool {
if !model.finding() {
return false;
}
crate::ui::overlay::name(ui, HEADING);
asking(ui, model);
ui.separator();
let found = model.found.clone();
if found.is_empty() {
ui.label(NOT_ASKED);
return true;
}
ui.colored_label(theme::NOTICE, NOT_ADDRESSABLE);
egui::ScrollArea::vertical()
.id_salt(HEADING)
.auto_shrink(false)
.show(ui, |ui| {
for section in &found {
ui.separator();
ui.label(crate::ui::roster::header(§ion.channel));
answered(ui, §ion.found);
}
});
true
}
fn asking(ui: &mut egui::Ui, model: &mut Model) {
let (rect, _) = ui.allocate_exact_size(
egui::vec2(ui.available_width(), ui.spacing().interact_size.y),
egui::Sense::hover(),
);
ui.new_child(egui::UiBuilder::new().max_rect(rect)).add(
egui::TextEdit::singleline(&mut model.needle)
.desired_width(rect.width())
.clip_text(true),
);
let live = model.needled();
let mut fired = false;
ui.horizontal_wrapped(|ui| {
let act = ui.add_enabled(live, egui::Button::new(FIND));
crate::ui::act::tag(&act, &[crate::verbs::SEARCH.word]);
fired = act.clicked();
});
if !live {
ui.colored_label(theme::NOTICE, NEEDS_WORDS);
}
if fired {
model.post_search();
}
}
fn answered(ui: &mut egui::Ui, found: &crate::reply::search::Found) {
broken(ui, &looked_for(found), theme::INK);
for why in &found.unreadable {
ui.colored_label(theme::NOTICE, unread(why));
}
if found.rows.is_empty() {
theme::paint::empty(ui, NOTHING);
return;
}
for row in &found.rows {
hit(ui, row);
}
}
fn hit(ui: &mut egui::Ui, row: &crate::reply::search::Hit) {
broken(ui, &row.subject(), theme::INK);
broken(
ui,
&row.at_field(),
theme::tone_ink(&crate::reply::convs::Tone::Weak),
);
broken(ui, &row.excerpt, theme::INK);
}
fn broken(ui: &mut egui::Ui, text: &str, ink: egui::Color32) {
let font = egui::TextStyle::Body.resolve(ui.style());
let mut job = egui::text::LayoutJob::simple(text.to_owned(), font, ink, ui.available_width());
job.wrap.break_anywhere = true;
ui.label(job);
}
pub fn looked_for(found: &crate::reply::search::Found) -> String {
format!("looked for {:?}", found.needle)
}
pub fn unread(why: &str) -> String {
format!("could not be read: {why}")
}
#[cfg(test)]
mod tests;