use crate::{ user_config::{Connection, UserConfig}, utils::get_tables, }; use sqlx::mysql::MySqlPool; use tui::widgets::{ListState, TableState}; pub enum InputMode { Normal, Editing, } pub enum FocusType { Dabatases(bool), Tables(bool), Records(bool), Connections, } #[derive(Clone)] pub struct Database { pub selected_table: ListState, pub name: String, pub tables: Vec, } #[derive(Clone)] pub struct Table { pub name: String, } pub struct RecordTable { pub state: TableState, pub headers: Vec, pub rows: Vec>, pub column_index: usize, } impl Default for RecordTable { fn default() -> Self { Self { state: TableState::default(), headers: vec![], rows: vec![], column_index: 0, } } } impl RecordTable { pub fn next(&mut self) { let i = match self.state.selected() { Some(i) => { if i >= self.rows.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.state.select(Some(i)); } pub fn previous(&mut self) { let i = match self.state.selected() { Some(i) => { if i == 0 { self.rows.len() - 1 } else { i - 1 } } None => 0, }; self.state.select(Some(i)); } pub fn next_column(&mut self) { if self.headers.len() > 9 && self.column_index < self.headers.len() - 9 { self.column_index += 1 } } pub fn previous_column(&mut self) { if self.column_index > 0 { self.column_index -= 1 } } } impl Database { pub async fn new(name: String, pool: &MySqlPool) -> anyhow::Result { Ok(Self { selected_table: ListState::default(), name: name.clone(), tables: get_tables(name, pool).await?, }) } pub fn next(&mut self) { let i = match self.selected_table.selected() { Some(i) => { if i >= self.tables.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.selected_table.select(Some(i)); } pub fn previous(&mut self) { let i = match self.selected_table.selected() { Some(i) => { if i == 0 { self.tables.len() - 1 } else { i - 1 } } None => 0, }; self.selected_table.select(Some(i)); } } pub struct App { pub input: String, pub input_mode: InputMode, pub messages: Vec>, pub selected_database: ListState, pub databases: Vec, pub record_table: RecordTable, pub focus_type: FocusType, pub user_config: Option, pub selected_connection: ListState, pub pool: Option, } impl Default for App { fn default() -> App { App { input: String::new(), input_mode: InputMode::Normal, messages: Vec::new(), selected_database: ListState::default(), databases: Vec::new(), record_table: RecordTable::default(), focus_type: FocusType::Dabatases(false), user_config: None, selected_connection: ListState::default(), pool: None, } } } impl App { pub fn new(title: &str, enhanced_graphics: bool) -> App { Self::default() } pub fn next_database(&mut self) { let i = match self.selected_database.selected() { Some(i) => { if i >= self.databases.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.selected_database.select(Some(i)); } pub fn previous_database(&mut self) { let i = match self.selected_database.selected() { Some(i) => { if i == 0 { self.databases.len() - 1 } else { i - 1 } } None => 0, }; self.selected_database.select(Some(i)); } pub fn next_connection(&mut self) { if let Some(config) = &self.user_config { let i = match self.selected_connection.selected() { Some(i) => { if i >= config.conn.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.selected_connection.select(Some(i)); } } pub fn previous_connection(&mut self) { if let Some(config) = &self.user_config { let i = match self.selected_connection.selected() { Some(i) => { if i == 0 { config.conn.len() - 1 } else { i - 1 } } None => 0, }; self.selected_connection.select(Some(i)); } } pub fn selected_database(&self) -> Option<&Database> { match self.selected_database.selected() { Some(i) => match self.databases.get(i) { Some(db) => Some(db), None => None, }, None => None, } } pub fn selected_table(&self) -> Option<&Table> { match self.selected_database() { Some(db) => match db.selected_table.selected() { Some(i) => db.tables.get(i), None => None, }, None => None, } } pub fn selected_connection(&self) -> Option<&Connection> { match &self.user_config { Some(config) => match self.selected_connection.selected() { Some(i) => config.conn.get(i), None => None, }, None => None, } } }