use anyhow::Result;
use crossterm::event::{KeyCode, KeyEvent};
use super::{categorize_error, App, SettingsField};
impl App {
pub async fn load_settings(&mut self) -> Result<()> {
self.settings_state.loading = true;
self.settings_state.error = None;
match self.api_client.get_config().await {
Ok(config) => {
self.settings_state.max_posts_input = config.max_posts_display.to_string();
self.settings_state.original_max_posts_input = config.max_posts_display.to_string();
self.settings_state.config = Some(config.clone());
self.settings_state.original_config = Some(config);
self.settings_state.loading = false;
self.settings_state.has_unsaved_changes = false;
}
Err(e) => {
let error_msg = categorize_error(&e.to_string());
self.settings_state.error = Some(error_msg);
self.settings_state.loading = false;
}
}
Ok(())
}
pub fn try_switch_tab(&mut self, new_tab: super::Tab) {
if self.current_tab == super::Tab::Settings && self.settings_state.has_unsaved_changes {
self.settings_state.show_save_confirmation = true;
self.settings_state.pending_tab = Some(new_tab);
} else {
self.current_tab = new_tab;
}
}
pub fn confirm_discard_changes(&mut self) {
self.settings_state.has_unsaved_changes = false;
self.settings_state.show_save_confirmation = false;
if let Some(pending_tab) = self.settings_state.pending_tab.take() {
self.current_tab = pending_tab;
} else {
if let Err(e) = self.config_manager.delete_session(&self.instance_id) {
eprintln!("Warning: Failed to delete session: {}", e);
}
self.auth_state.current_user = None;
self.current_screen = super::Screen::Auth;
self.posts_state.posts.clear();
self.profile_state.profile = None;
self.dms_state.conversations.clear();
self.dms_state.conversations_loaded = false;
self.dms_state.messages.clear();
}
}
pub fn cancel_tab_switch(&mut self) {
self.settings_state.show_save_confirmation = false;
self.settings_state.pending_tab = None;
}
pub fn cycle_color_scheme(&mut self) {
if let Some(config) = &mut self.settings_state.config {
config.color_scheme = match config.color_scheme {
fido_types::ColorScheme::Default => fido_types::ColorScheme::Dark,
fido_types::ColorScheme::Dark => fido_types::ColorScheme::Light,
fido_types::ColorScheme::Light => fido_types::ColorScheme::Solarized,
fido_types::ColorScheme::Solarized => fido_types::ColorScheme::Default,
};
self.check_settings_changes();
}
}
pub fn cycle_color_scheme_backward(&mut self) {
if let Some(config) = &mut self.settings_state.config {
config.color_scheme = match config.color_scheme {
fido_types::ColorScheme::Default => fido_types::ColorScheme::Solarized,
fido_types::ColorScheme::Dark => fido_types::ColorScheme::Default,
fido_types::ColorScheme::Light => fido_types::ColorScheme::Dark,
fido_types::ColorScheme::Solarized => fido_types::ColorScheme::Light,
};
self.check_settings_changes();
}
}
pub fn cycle_sort_order(&mut self) {
if let Some(config) = &mut self.settings_state.config {
config.sort_order = match config.sort_order {
fido_types::SortOrder::Newest => fido_types::SortOrder::Popular,
fido_types::SortOrder::Popular => fido_types::SortOrder::Controversial,
fido_types::SortOrder::Controversial => fido_types::SortOrder::Newest,
};
self.check_settings_changes();
}
}
pub fn cycle_sort_order_backward(&mut self) {
if let Some(config) = &mut self.settings_state.config {
config.sort_order = match config.sort_order {
fido_types::SortOrder::Newest => fido_types::SortOrder::Controversial,
fido_types::SortOrder::Popular => fido_types::SortOrder::Newest,
fido_types::SortOrder::Controversial => fido_types::SortOrder::Popular,
};
self.check_settings_changes();
}
}
pub fn add_digit_to_max_posts(&mut self, c: char) {
if c.is_ascii_digit() && self.settings_state.max_posts_input.len() < 3 {
self.settings_state.max_posts_input.push(c);
self.check_settings_changes();
}
}
pub fn remove_digit_from_max_posts(&mut self) {
if !self.settings_state.max_posts_input.is_empty() {
self.settings_state.max_posts_input.pop();
self.check_settings_changes();
}
}
pub fn increment_max_posts(&mut self) {
if let Ok(current) = self.settings_state.max_posts_input.parse::<i32>() {
let new_value = (current + 1).min(420); self.settings_state.max_posts_input = new_value.to_string();
self.check_settings_changes();
}
}
pub fn decrement_max_posts(&mut self) {
if let Ok(current) = self.settings_state.max_posts_input.parse::<i32>() {
let new_value = (current - 1).max(1); self.settings_state.max_posts_input = new_value.to_string();
self.check_settings_changes();
}
}
pub async fn save_settings(&mut self) -> Result<()> {
if let Some(config) = &self.settings_state.config {
self.settings_state.error = None;
let max_posts = match self.settings_state.max_posts_input.parse::<i32>() {
Ok(n) if n > 0 => n,
Ok(n) => {
self.settings_state.error = Some(format!(
"Validation Error: Max posts must be positive (got {})",
n
));
return Ok(());
}
Err(_) if self.settings_state.max_posts_input.is_empty() => {
self.settings_state.error =
Some("Validation Error: Max posts cannot be empty".to_string());
return Ok(());
}
Err(_) => {
self.settings_state.error = Some(format!(
"Validation Error: '{}' is not a valid number",
self.settings_state.max_posts_input
));
return Ok(());
}
};
let request = fido_types::UpdateConfigRequest {
color_scheme: Some(config.color_scheme.as_str().to_string()),
sort_order: Some(config.sort_order.as_str().to_string()),
max_posts_display: Some(max_posts),
emoji_enabled: Some(config.emoji_enabled),
};
match self.api_client.update_config(request).await {
Ok(updated_config) => {
self.settings_state.max_posts_input =
updated_config.max_posts_display.to_string();
self.settings_state.original_max_posts_input =
updated_config.max_posts_display.to_string();
self.settings_state.config = Some(updated_config.clone());
self.settings_state.original_config = Some(updated_config);
self.settings_state.has_unsaved_changes = false;
self.settings_state.error = Some("✓ Settings saved successfully!".to_string());
let _ = self.load_posts().await;
}
Err(e) => {
self.settings_state.error = Some(format!(
"Network Error: Failed to save settings: {} (Press 's' to retry)",
e
));
}
}
}
Ok(())
}
pub fn handle_settings_keys(&mut self, key: KeyEvent) -> Result<()> {
if self.settings_state.show_save_confirmation {
match key.code {
KeyCode::Char('y') | KeyCode::Char('Y') => {
}
KeyCode::Char('n') | KeyCode::Char('N') => {
self.confirm_discard_changes();
}
_ => {}
}
return Ok(());
}
match key.code {
KeyCode::Down | KeyCode::Char('j') | KeyCode::Char('J') => {
self.settings_state.selected_field = match self.settings_state.selected_field {
SettingsField::ColorScheme => SettingsField::SortOrder,
SettingsField::SortOrder => SettingsField::MaxPosts,
SettingsField::MaxPosts => SettingsField::MaxPosts, };
}
KeyCode::Up | KeyCode::Char('k') | KeyCode::Char('K') => {
self.settings_state.selected_field = match self.settings_state.selected_field {
SettingsField::ColorScheme => SettingsField::ColorScheme, SettingsField::SortOrder => SettingsField::ColorScheme,
SettingsField::MaxPosts => SettingsField::SortOrder,
};
}
KeyCode::Char('h') | KeyCode::Char('H') | KeyCode::Left => {
match self.settings_state.selected_field {
SettingsField::ColorScheme => self.cycle_color_scheme_backward(),
SettingsField::SortOrder => self.cycle_sort_order_backward(),
SettingsField::MaxPosts => self.decrement_max_posts(),
}
}
KeyCode::Char('l') | KeyCode::Char('L') | KeyCode::Right | KeyCode::Enter => {
match self.settings_state.selected_field {
SettingsField::ColorScheme => self.cycle_color_scheme(),
SettingsField::SortOrder => self.cycle_sort_order(),
SettingsField::MaxPosts => self.increment_max_posts(),
}
}
KeyCode::Backspace if self.settings_state.selected_field == SettingsField::MaxPosts => {
self.remove_digit_from_max_posts();
}
KeyCode::Char(c) if self.settings_state.selected_field == SettingsField::MaxPosts => {
self.add_digit_to_max_posts(c);
}
KeyCode::Char('s') => {
}
_ => {}
}
Ok(())
}
fn check_settings_changes(&mut self) {
if let (Some(current), Some(original)) = (
&self.settings_state.config,
&self.settings_state.original_config,
) {
let config_changed = current.color_scheme != original.color_scheme
|| current.sort_order != original.sort_order;
let max_posts_changed =
self.settings_state.max_posts_input != self.settings_state.original_max_posts_input;
self.settings_state.has_unsaved_changes = config_changed || max_posts_changed;
}
}
}