repositories / smith
smith
There are many coding harnesses - but this one is fast
owned by admin
smith-ui/src/lib.rs
Raw//! Frontend-local, read-only observer presentation state (`SMH-SPEC-SPEC0001`, Observer mode).
#![deny(unsafe_code)]
/// Maximum retained visible records and UTF-8 bytes per row.
pub const ROWS: usize = 12;
/// Byte budget for each visible line, including label and clipping marker.
pub const ROW_BYTES: usize = 512;
/// Prepared, bounded visible row; never an owned session frame.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Row {
/// Entry identity for explicit fork/search results.
pub id: String,
/// One clipped UTF-8 line.
pub text: String,
}
/// Navigation lives only in the frontend, never in persisted selection.
#[derive(Debug, Default)]
pub struct Observer {
/// First visible record index in selected history.
pub start: usize,
/// Total records in most recent published snapshot.
pub total: usize,
/// Whether a worker has reported writer activity yet.
pub status_known: bool,
/// Last complete snapshot's writer activity.
pub writer_active: bool,
/// Follow must be explicitly enabled; browsing disables it.
pub follow: bool,
/// Only bounded prepared rows are retained.
pub rows: Vec<Row>,
/// Search query being entered, local to this frontend.
pub search: String,
/// Search entry, if found in most recent query.
pub found: Option<String>,
/// Recent operation status.
pub notice: String,
}
impl Observer {
/// Navigate back without changing selected history.
pub const fn back(&mut self) {
self.follow = false;
self.start = self.start.saturating_sub(ROWS);
}
/// Navigate forward without enabling follow.
pub fn forward(&mut self) {
self.follow = false;
self.start = self
.start
.saturating_add(ROWS)
.min(self.total.saturating_sub(ROWS));
}
/// Jump to last page and toggle explicit live following.
pub const fn toggle_follow(&mut self) {
self.follow = !self.follow;
if self.follow {
self.start = self.total.saturating_sub(ROWS);
}
}
/// Replace the prepared snapshot without jumping while browsing.
pub fn publish(&mut self, total: usize, writer_active: bool, rows: Vec<Row>) {
self.total = total;
self.writer_active = writer_active;
self.status_known = true;
if self.follow {
self.start = total.saturating_sub(ROWS);
}
self.rows = rows;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn published_live_rows_never_jump_while_browsing() {
let mut ui = Observer::default();
ui.publish(30, true, vec![]);
assert_eq!(ui.start, 0);
ui.toggle_follow();
assert_eq!(ui.start, 18);
ui.publish(32, true, vec![]);
assert_eq!(ui.start, 20);
ui.back();
assert_eq!(ui.start, 8);
ui.publish(80, false, vec![]);
assert_eq!(ui.start, 8);
assert!(!ui.follow);
}
#[test]
fn state_is_small_without_payloads() {
assert!(std::mem::size_of::<Observer>() <= 256);
}
}