use super::App;
use crate::app::Config;
use crate::app::DirtyFlags;
use crate::app::KeyBinds;
use crate::app::cli::Args;
use crate::app::{MenuMode, PanelFocus};
use ratatui::widgets::ListState;
use std::cell::Cell;
use std::path::PathBuf;
#[allow(dead_code)]
pub trait AppConstructor {
fn new(args: Args) -> color_eyre::Result<Self>
where
Self: Sized;
}
fn get_state_path() -> Option<PathBuf> {
let base_dir = dirs::state_dir().or_else(dirs::data_dir)?;
Some(base_dir.join("zarumet").join("state.toml"))
}
fn load_bit_perfect_state() -> bool {
let state_path = match get_state_path() {
Some(path) => path,
None => return false,
};
if !state_path.exists() {
return false;
}
let contents = match std::fs::read_to_string(&state_path) {
Ok(c) => c,
Err(_) => return false,
};
contents
.lines()
.find(|line| line.starts_with("bit_perfect"))
.and_then(|line| line.split('=').nth(1))
.map(|val| val.trim() == "true")
.unwrap_or(false)
}
pub fn save_bit_perfect_state(enabled: bool) -> std::io::Result<()> {
let state_path = match get_state_path() {
Some(path) => path,
None => return Ok(()),
};
if let Some(parent) = state_path.parent() {
std::fs::create_dir_all(parent)?;
}
let contents = format!("bit_perfect = {}\n", enabled);
std::fs::write(&state_path, contents)
}
impl AppConstructor for App {
fn new(args: Args) -> color_eyre::Result<Self> {
let config_path = args.config.clone();
let address = args.address.clone();
let (mut config, _warnings) = Config::load(config_path)?;
if let Some(addr) = address {
config.mpd.address = addr;
}
Self::new_with_config(config, args)
}
}
impl App {
pub fn new_with_config(config: Config, args: Args) -> color_eyre::Result<Self> {
let queue_list_state = ListState::default();
let (global_map, queue_map, artists_map, albums_map, sequential_bindings) =
config.binds.build_enhanced_key_maps();
let key_binds = KeyBinds::new_with_sequential(
global_map,
queue_map,
artists_map,
albums_map,
sequential_bindings,
);
let bit_perfect_enabled = match args.bit_perfect {
Some(value) => value, None => load_bit_perfect_state(), };
Ok(Self {
running: false,
current_song: None,
queue: Vec::new(),
selected_queue_index: None, queue_list_state,
artist_list_state: ListState::default(),
album_list_state: ListState::default(),
album_display_list_state: ListState::default(),
all_albums_list_state: ListState::default(),
album_tracks_list_state: ListState::default(),
year_list_state: ListState::default(),
genre_list_state: ListState::default(),
year_album_list_state: ListState::default(),
genre_album_list_state: ListState::default(),
years_panel_focus: PanelFocus::YearList,
genre_panel_focus: PanelFocus::GenreList,
config,
menu_mode: MenuMode::Queue, panel_focus: PanelFocus::Artists, artists_panel_focus: PanelFocus::Artists, albums_panel_focus: PanelFocus::AlbumList, library: None,
expanded_albums: std::collections::HashSet::new(),
expanded_albums_years: std::collections::HashSet::new(),
expanded_albums_genres: std::collections::HashSet::new(),
year_album_display_list_state: ListState::default(),
genre_album_display_list_state: ListState::default(),
mpd_status: None,
key_binds,
bit_perfect_enabled,
force_update: true, config_warnings: Vec::new(),
show_config_warnings_popup: false,
last_play_state: None,
last_sample_rate: None,
last_playlist_version: None,
last_song_id: None,
dirty: DirtyFlags::new(),
library_reload_pending: false,
pending_artist_index: None,
status_message: None,
update_in_progress: false,
last_animation_frame: Cell::new(0),
user_initiated_reload: false,
vol_before_mute: 100,
})
}
}