use std::cell::Cell;
use crate::reactive::{create_root, Scope, Signal};
thread_local! {
static NOTICES_SIGNAL: Cell<Option<Signal<Vec<String>>>> = const { Cell::new(None) };
}
fn notices_signal() -> Signal<Vec<String>> {
NOTICES_SIGNAL.with(|slot| {
if let Some(sig) = slot.get() {
return sig;
}
let (root, sig) = create_root(|cx| cx.signal(Vec::new()));
std::mem::forget(root);
slot.set(Some(sig));
sig
})
}
pub fn use_startup_notices(_cx: Scope) -> Signal<Vec<String>> {
notices_signal()
}
pub(super) fn publish_notice(notice: String) {
let sig = notices_signal();
sig.update(|v| v.push(notice));
}
#[cfg(test)]
pub(crate) fn reset_notices_for_test() {
notices_signal().set(Vec::new());
}
#[cfg(test)]
mod tests {
use super::*;
use crate::reactive::{create_root, flush_effects};
#[test]
fn late_pushes_propagate_to_mount_time_readers() {
reset_notices_for_test();
let seen: std::rc::Rc<std::cell::RefCell<Vec<usize>>> =
std::rc::Rc::new(std::cell::RefCell::new(Vec::new()));
let s = seen.clone();
let (root, ()) = create_root(|cx| {
let notices = use_startup_notices(cx);
cx.effect(move || s.borrow_mut().push(notices.with(|n| n.len())));
});
flush_effects();
assert_eq!(*seen.borrow(), vec![0], "clean at mount");
let mut app = crate::app::App::new(crate::base::Size::new(10, 3));
app.push_startup_notice("input: degraded (stdin fallback)");
flush_effects();
assert_eq!(*seen.borrow(), vec![0, 1], "late push re-ran the reader");
assert_eq!(app.startup_notices().len(), 1, "plain read keeps working");
root.dispose();
}
}