use std::time::{Duration, Instant};
pub(crate) const NOTIFICATION_TTL: Duration = Duration::from_secs(2);
pub(crate) const ERROR_TTL: Duration = Duration::from_millis(2500);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum NoticeKind {
Error,
Info,
}
pub(crate) fn notice_expired(shown_at: Option<Instant>, now: Instant, ttl: Duration) -> bool {
shown_at.is_some_and(|t| now.saturating_duration_since(t) >= ttl)
}
pub(crate) fn pick_notice<'a>(
error: Option<&'a str>,
info: Option<&'a str>,
) -> Option<(NoticeKind, &'a str)> {
error
.map(|e| (NoticeKind::Error, e))
.or_else(|| info.map(|i| (NoticeKind::Info, i)))
}
pub(crate) fn notice_label(text: &str, max_chars: usize) -> Option<String> {
const PADDING: usize = 2;
const ELLIPSIS: char = '…';
let collapsed = text.split_whitespace().collect::<Vec<_>>().join(" ");
if collapsed.is_empty() || max_chars < PADDING + 2 {
return None;
}
let room = max_chars - PADDING;
let len = collapsed.chars().count();
let body: String = if len <= room {
collapsed
} else {
let mut cut: String = collapsed.chars().take(room - 1).collect();
cut.push(ELLIPSIS);
cut
};
Some(format!(" {body} "))
}