use std::time::Instant;
use crate::app::action::Action;
use crate::app::connection_state::ConnectionState;
use crate::app::effect::Effect;
use crate::app::input_mode::InputMode;
use crate::app::state::AppState;
use crate::domain::MetadataState;
pub fn reduce(state: &mut AppState, action: &Action, now: Instant) -> Option<Vec<Effect>> {
match action {
Action::ShowConnectionError(info) => {
state.connection_error.set_error(info.clone());
state.modal.replace_mode(InputMode::ConnectionError);
Some(vec![])
}
Action::CloseConnectionError => {
state.connection_error.details_expanded = false;
state.connection_error.scroll_offset = 0;
state.connection_error.clear_copied_feedback();
state.modal.set_mode(InputMode::Normal);
Some(vec![])
}
Action::ToggleConnectionErrorDetails => {
state.connection_error.toggle_details();
Some(vec![])
}
Action::ScrollConnectionErrorUp => {
state.connection_error.scroll_up();
Some(vec![])
}
Action::ScrollConnectionErrorDown => {
state.connection_error.scroll_down(100);
Some(vec![])
}
Action::CopyConnectionError => {
if let Some(content) = state.connection_error.masked_details() {
Some(vec![Effect::CopyToClipboard {
content: content.to_string(),
on_success: Some(Action::ConnectionErrorCopied),
on_failure: None,
}])
} else {
Some(vec![])
}
}
Action::ConnectionErrorCopied => {
state.connection_error.mark_copied_at(now);
Some(vec![])
}
Action::ReenterConnectionSetup => {
if state.session.is_service_connection() {
return Some(vec![]);
}
state.connection_error.clear();
state
.session
.set_connection_state(ConnectionState::NotConnected);
state.session.set_metadata_state(MetadataState::NotLoaded);
state.modal.replace_mode(InputMode::ConnectionSetup);
Some(vec![])
}
Action::RetryServiceConnection => {
if let Some(dsn) = state.session.dsn.clone() {
state.connection_error.clear();
state.session.begin_connecting(&dsn);
state.session.read_only = false;
state.modal.set_mode(InputMode::Normal);
Some(vec![Effect::FetchMetadata { dsn }])
} else {
Some(vec![])
}
}
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
mod reenter_connection_setup {
use super::*;
#[test]
fn blocked_for_service_connection() {
let mut state = AppState::new("test".to_string());
state.session.dsn = Some("service=mydb".to_string());
state.modal.set_mode(InputMode::ConnectionError);
reduce(&mut state, &Action::ReenterConnectionSetup, Instant::now());
assert_eq!(state.input_mode(), InputMode::ConnectionError);
}
#[test]
fn allowed_for_profile_connection() {
let mut state = AppState::new("test".to_string());
state.session.dsn = Some("postgres://localhost/db".to_string());
state.modal.set_mode(InputMode::ConnectionError);
reduce(&mut state, &Action::ReenterConnectionSetup, Instant::now());
assert_eq!(state.input_mode(), InputMode::ConnectionSetup);
}
}
}