use std::path::PathBuf;
use fastpack_core::types::config::PackerConfig;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Keybind {
pub key: String,
pub modifier: bool,
pub shift: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeybindsConfig {
#[serde(default = "default_kb_new_project")]
pub new_project: Keybind,
#[serde(default = "default_kb_open_project")]
pub open_project: Keybind,
#[serde(default = "default_kb_save_project")]
pub save_project: Keybind,
#[serde(default = "default_kb_save_project_as")]
pub save_project_as: Keybind,
#[serde(default = "default_kb_anim_preview")]
pub anim_preview: Keybind,
}
impl Default for KeybindsConfig {
fn default() -> Self {
Self {
new_project: default_kb_new_project(),
open_project: default_kb_open_project(),
save_project: default_kb_save_project(),
save_project_as: default_kb_save_project_as(),
anim_preview: default_kb_anim_preview(),
}
}
}
fn default_kb_new_project() -> Keybind {
Keybind {
key: "n".into(),
modifier: true,
shift: false,
}
}
fn default_kb_open_project() -> Keybind {
Keybind {
key: "o".into(),
modifier: true,
shift: false,
}
}
fn default_kb_save_project() -> Keybind {
Keybind {
key: "s".into(),
modifier: true,
shift: false,
}
}
fn default_kb_save_project_as() -> Keybind {
Keybind {
key: "s".into(),
modifier: true,
shift: true,
}
}
fn default_kb_anim_preview() -> Keybind {
Keybind {
key: "p".into(),
modifier: false,
shift: false,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum Language {
#[default]
En,
Fr,
Es,
De,
It,
Pt,
Ja,
Zh,
Ko,
}
impl Language {
pub fn code(self) -> &'static str {
match self {
Self::En => "en",
Self::Fr => "fr",
Self::Es => "es",
Self::De => "de",
Self::It => "it",
Self::Pt => "pt",
Self::Ja => "ja",
Self::Zh => "zh",
Self::Ko => "ko",
}
}
pub fn display(self) -> &'static str {
match self {
Self::En => "English",
Self::Fr => "Français",
Self::Es => "Español",
Self::De => "Deutsch",
Self::It => "Italiano",
Self::Pt => "Português",
Self::Ja => "日本語",
Self::Zh => "中文(简体)",
Self::Ko => "한국어",
}
}
pub const ALL: &'static [Language] = &[
Self::En,
Self::Fr,
Self::Es,
Self::De,
Self::It,
Self::Pt,
Self::Ja,
Self::Zh,
Self::Ko,
];
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Preferences {
#[serde(default = "default_true")]
pub dark_mode: bool,
#[serde(default = "default_true")]
pub auto_check_updates: bool,
#[serde(default)]
pub default_config: PackerConfig,
#[serde(default)]
pub language: Language,
#[serde(default = "default_ui_scale")]
pub ui_scale: f32,
#[serde(default)]
pub keybinds: KeybindsConfig,
#[serde(default = "default_zoom_speed")]
pub atlas_zoom_speed: f32,
#[serde(default)]
pub atlas_invert_scroll: bool,
}
fn default_true() -> bool {
true
}
fn default_ui_scale() -> f32 {
1.0
}
fn default_zoom_speed() -> f32 {
1.0
}
impl Default for Preferences {
fn default() -> Self {
Self {
dark_mode: true,
auto_check_updates: true,
default_config: PackerConfig::default(),
language: Language::En,
ui_scale: 1.0,
keybinds: KeybindsConfig::default(),
atlas_zoom_speed: 1.0,
atlas_invert_scroll: false,
}
}
}
impl Preferences {
pub fn load() -> Self {
prefs_path()
.and_then(|p| std::fs::read_to_string(p).ok())
.and_then(|text| toml::from_str(&text).ok())
.unwrap_or_default()
}
pub fn save(&self) {
let Some(path) = prefs_path() else { return };
if let Some(parent) = path.parent() {
let _ = std::fs::create_dir_all(parent);
}
if let Ok(text) = toml::to_string_pretty(self) {
let _ = std::fs::write(path, text.as_bytes());
}
}
}
fn prefs_path() -> Option<PathBuf> {
dirs::config_dir().map(|d| d.join("FastPack").join("prefs.toml"))
}