use crate::{utils::IconEntry, views::main::MainState};
use std::sync::mpsc::{Receiver, Sender};
use tui_textarea::Input;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AppFocus {
Main,
AddPopup,
DeletePopup,
RenamePopup,
HelpPopup,
IconifySearchPopup,
SyncPopup,
}
#[derive(Debug, Clone)]
pub struct IconifyCollectionListItem {
pub prefix: String,
pub name: String,
pub total: Option<u32>,
}
#[derive(Debug, Clone)]
pub struct IconifySearchPayload {
pub icons: Vec<String>,
}
#[derive(Debug)]
pub enum AppEvent {
IconifyCollectionsLoaded {
request_id: u64,
result: Result<Vec<IconifyCollectionListItem>, String>,
},
IconifySearchLoaded {
request_id: u64,
query: String,
result: Result<IconifySearchPayload, String>,
},
IconifyCollectionIconsLoaded {
request_id: u64,
prefix: String,
result: Result<Vec<String>, String>,
},
}
#[derive(Debug, Clone)]
pub struct AppConfig {
pub folder: String,
pub preset: String,
pub svg_viewer_cmd: Option<String>,
pub svg_viewer_cmd_source: String,
pub global_config_loaded: bool,
pub project_config_loaded: bool,
pub flutter_barrel_file: Option<String>,
pub flutter_barrel_class: Option<String>,
}
pub struct App {
pub config: AppConfig,
pub tx: Sender<AppEvent>,
pub rx: Receiver<AppEvent>,
pub should_quit: bool,
pub selected_index: usize,
pub items: Vec<IconEntry>,
pub filtered_items: Vec<IconEntry>,
pub app_focus: AppFocus,
pub main_state: crate::views::main::MainState,
pub add_popup_state: Option<crate::views::add_popup::AddPopupState>,
pub delete_popup_state: Option<crate::views::delete_popup::DeletePopupState>,
pub rename_popup_state: Option<crate::views::rename_popup::RenamePopupState>,
pub iconify_search_popup_state:
Option<crate::views::iconify_search_popup::IconifySearchPopupState>,
pub sync_popup_state: Option<crate::views::sync_popup::SyncPopupState>,
pub next_async_request_id: u64,
}
impl App {
pub fn new(config: AppConfig) -> Self {
let (tx, rx) = std::sync::mpsc::channel();
let mut app = Self {
config,
should_quit: false,
tx,
rx,
selected_index: 0,
filtered_items: Vec::new(),
items: Vec::new(),
app_focus: AppFocus::Main,
add_popup_state: None,
delete_popup_state: None,
rename_popup_state: None,
iconify_search_popup_state: None,
sync_popup_state: None,
next_async_request_id: 0,
main_state: MainState::new(),
};
app.init_icons();
app
}
pub fn init_icons(&mut self) {
self.items = crate::utils::get_existing_icons_for_preset(
&self.config.folder,
&self.config.preset,
self.config.flutter_barrel_file.as_deref(),
)
.unwrap_or_default();
self.filtered_items = self.items.clone();
}
pub fn update(&mut self) {
while let Ok(event) = self.rx.try_recv() {
self.handle_app_event(event);
}
self.tick_iconify_search_popup();
}
pub fn handlekeys(&mut self, key: Input) {
match self.app_focus {
AppFocus::Main => self.handlekeys_main(key),
AppFocus::AddPopup => self.handlekeys_add_popup(key),
AppFocus::DeletePopup => self.handlekeys_delete_popup(key),
AppFocus::RenamePopup => self.handlekeys_rename_popup(key),
AppFocus::HelpPopup => self.handlekeys_help_popup(key),
AppFocus::IconifySearchPopup => self.handlekeys_iconify_search_popup(key),
AppFocus::SyncPopup => self.handlekeys_sync_popup(key),
}
}
pub fn handle_mouse(&mut self, mouse: ratatui::crossterm::event::MouseEvent) {
match self.app_focus {
AppFocus::Main => self.handle_mouse_main(mouse),
AppFocus::IconifySearchPopup => self.handle_mouse_iconify_search_popup(mouse),
_ => {}
}
}
}