use std::sync::Mutex;
use crate::pane::PaneId;
pub struct WebPane {
pub id: PaneId,
state: Mutex<State>,
}
struct State {
history: Vec<String>,
cursor: usize,
}
impl WebPane {
pub fn new(id: PaneId, url: String) -> WebPane {
WebPane {
id,
state: Mutex::new(State {
history: vec![url],
cursor: 0,
}),
}
}
pub fn url(&self) -> String {
let st = self.state.lock().unwrap();
st.history[st.cursor].clone()
}
pub fn navigate(&self, url: String) {
let mut st = self.state.lock().unwrap();
let cursor_pos = st.cursor;
st.history.truncate(cursor_pos + 1);
st.history.push(url);
st.cursor = st.history.len() - 1;
}
pub fn back(&self) -> bool {
let mut st = self.state.lock().unwrap();
if st.cursor == 0 {
return false;
}
st.cursor -= 1;
true
}
pub fn forward(&self) -> bool {
let mut st = self.state.lock().unwrap();
if st.cursor + 1 >= st.history.len() {
return false;
}
st.cursor += 1;
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn nouvelle_pile_commence_sur_l_url_initiale() {
let w = WebPane::new(1, "http://a/".into());
assert_eq!(w.url(), "http://a/");
assert!(!w.back(), "rien avant la première URL");
assert!(!w.forward(), "rien après la première URL");
}
#[test]
fn navigate_empile_et_back_forward_parcourent() {
let w = WebPane::new(1, "http://a/".into());
w.navigate("http://b/".into());
w.navigate("http://c/".into());
assert_eq!(w.url(), "http://c/");
assert!(w.back());
assert_eq!(w.url(), "http://b/");
assert!(w.back());
assert_eq!(w.url(), "http://a/");
assert!(!w.back(), "en tête de pile, back est un no-op");
assert_eq!(w.url(), "http://a/");
assert!(w.forward());
assert_eq!(w.url(), "http://b/");
assert!(w.forward());
assert_eq!(w.url(), "http://c/");
assert!(!w.forward(), "en fin de pile, forward est un no-op");
}
#[test]
fn naviguer_apres_un_back_tronque_l_avant() {
let w = WebPane::new(1, "http://a/".into());
w.navigate("http://b/".into());
assert!(w.back()); w.navigate("http://z/".into());
assert_eq!(w.url(), "http://z/");
assert!(
!w.forward(),
"après une nouvelle navigation, l'avant est tronqué"
);
assert!(w.back());
assert_eq!(w.url(), "http://a/");
}
}