use crate::command::AgendaRange;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkspaceState {
pub view: View,
pub selected_index: usize,
pub status: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum View {
Home,
Inboxes,
MailList { mailbox: String },
MailReader { message_id: String },
Calendars,
Agenda { range: AgendaRange },
EventReader { event_id: String },
SearchResults { query: String },
Compose,
}
impl Default for WorkspaceState {
fn default() -> Self {
Self {
view: View::Home,
selected_index: 0,
status: None,
}
}
}
impl WorkspaceState {
pub fn select_next(&mut self, len: usize) {
if len == 0 {
self.selected_index = 0;
return;
}
self.selected_index = (self.selected_index + 1).min(len - 1);
}
pub fn select_previous(&mut self) {
self.selected_index = self.selected_index.saturating_sub(1);
}
pub fn select_top(&mut self) {
self.selected_index = 0;
}
pub fn select_bottom(&mut self, len: usize) {
self.selected_index = len.saturating_sub(1);
}
pub fn set_view(&mut self, view: View) {
self.view = view;
self.selected_index = 0;
}
pub fn set_status(&mut self, status: impl Into<String>) {
self.status = Some(status.into());
}
pub fn clear_status(&mut self) {
self.status = None;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn select_next_stops_at_end() {
let mut state = WorkspaceState::default();
state.select_next(2);
state.select_next(2);
state.select_next(2);
assert_eq!(state.selected_index, 1);
}
#[test]
fn select_previous_saturates_at_zero() {
let mut state = WorkspaceState::default();
state.select_previous();
assert_eq!(state.selected_index, 0);
}
#[test]
fn select_next_zero_len_resets_to_zero() {
let mut state = WorkspaceState {
selected_index: 4,
..WorkspaceState::default()
};
state.select_next(0);
assert_eq!(state.selected_index, 0);
}
#[test]
fn select_top_resets_selection() {
let mut state = WorkspaceState {
selected_index: 8,
..WorkspaceState::default()
};
state.select_top();
assert_eq!(state.selected_index, 0);
}
#[test]
fn select_bottom_tracks_list_len_and_saturates() {
let mut state = WorkspaceState::default();
state.select_bottom(3);
assert_eq!(state.selected_index, 2);
state.select_bottom(0);
assert_eq!(state.selected_index, 0);
}
#[test]
fn status_set_and_clear_round_trip() {
let mut state = WorkspaceState::default();
state.set_status("sync ok");
assert_eq!(state.status, Some("sync ok".to_owned()));
state.clear_status();
assert_eq!(state.status, None);
}
#[test]
fn set_view_resets_selection() {
let mut state = WorkspaceState::default();
state.select_next(10);
state.set_view(View::Inboxes);
assert_eq!(state.selected_index, 0);
assert_eq!(state.view, View::Inboxes);
}
}