1use serde::{Deserialize, Serialize};
7
8pub mod i18n;
9pub use i18n::{I18n, Language, TranslationKey};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Theme {
14 pub name: String,
15 pub background: String,
16 pub grid_background: String,
17 pub tile_colors: Vec<String>,
18 pub text_color: String,
19 pub title_color: String,
20 pub score_color: String,
21 pub best_score_color: String,
22 pub moves_color: String,
23 pub time_color: String,
24}
25
26impl Default for Theme {
27 fn default() -> Self {
28 Self {
29 name: "Classic".to_string(),
30 background: "#faf8ef".to_string(),
31 grid_background: "#bbada0".to_string(),
32 tile_colors: vec![
33 "#cdc1b4".to_string(), "#eee4da".to_string(), "#ede0c8".to_string(), "#f2b179".to_string(), "#f59563".to_string(), "#f67c5f".to_string(), "#f65e3b".to_string(), "#edcf72".to_string(), "#edcc61".to_string(), "#edc850".to_string(), "#edc53f".to_string(), "#edc22e".to_string(), ],
46 text_color: "#776e65".to_string(),
47 title_color: "#776e65".to_string(),
48 score_color: "#776e65".to_string(),
49 best_score_color: "#776e65".to_string(),
50 moves_color: "#776e65".to_string(),
51 time_color: "#776e65".to_string(),
52 }
53 }
54}
55
56impl Theme {
57 pub fn dark() -> Self {
59 Self {
60 name: "Dark".to_string(),
61 background: "#1a1a1a".to_string(),
62 grid_background: "#2d2d2d".to_string(),
63 tile_colors: vec![
64 "#3c3c3c".to_string(), "#4a4a4a".to_string(), "#5a5a5a".to_string(), "#6a6a6a".to_string(), "#7a7a7a".to_string(), "#8a8a8a".to_string(), "#9a9a9a".to_string(), "#aaaaaa".to_string(), "#bbbbbb".to_string(), "#cccccc".to_string(), "#dddddd".to_string(), "#eeeeee".to_string(), ],
77 text_color: "#ffffff".to_string(),
78 title_color: "#ffffff".to_string(),
79 score_color: "#4ade80".to_string(),
80 best_score_color: "#fbbf24".to_string(),
81 moves_color: "#60a5fa".to_string(),
82 time_color: "#a78bfa".to_string(),
83 }
84 }
85
86 pub fn neon() -> Self {
88 Self {
89 name: "Neon".to_string(),
90 background: "#000000".to_string(),
91 grid_background: "#1a0033".to_string(),
92 tile_colors: vec![
93 "#330033".to_string(), "#ff00ff".to_string(), "#00ffff".to_string(), "#ffff00".to_string(), "#ff0080".to_string(), "#80ff00".to_string(), "#0080ff".to_string(), "#ff8000".to_string(), "#8000ff".to_string(), "#00ff80".to_string(), "#ff0080".to_string(), "#ffff00".to_string(), ],
106 text_color: "#ffffff".to_string(),
107 title_color: "#ff00ff".to_string(),
108 score_color: "#00ffff".to_string(),
109 best_score_color: "#ffff00".to_string(),
110 moves_color: "#ff0080".to_string(),
111 time_color: "#80ff00".to_string(),
112 }
113 }
114
115 pub fn retro() -> Self {
117 Self {
118 name: "Retro".to_string(),
119 background: "#2b2b2b".to_string(),
120 grid_background: "#404040".to_string(),
121 tile_colors: vec![
122 "#555555".to_string(), "#00ff00".to_string(), "#00dd00".to_string(), "#00bb00".to_string(), "#009900".to_string(), "#007700".to_string(), "#005500".to_string(), "#003300".to_string(), "#001100".to_string(), "#00ff00".to_string(), "#00dd00".to_string(), "#00bb00".to_string(), ],
135 text_color: "#00ff00".to_string(),
136 title_color: "#00ff00".to_string(),
137 score_color: "#00ff00".to_string(),
138 best_score_color: "#00ff00".to_string(),
139 moves_color: "#00ff00".to_string(),
140 time_color: "#00ff00".to_string(),
141 }
142 }
143
144 pub fn pastel() -> Self {
146 Self {
147 name: "Pastel".to_string(),
148 background: "#f8f9fa".to_string(),
149 grid_background: "#e9ecef".to_string(),
150 tile_colors: vec![
151 "#dee2e6".to_string(), "#ffb3ba".to_string(), "#baffc9".to_string(), "#bae1ff".to_string(), "#ffffba".to_string(), "#ffb3d9".to_string(), "#d9b3ff".to_string(), "#b3d9ff".to_string(), "#b3ffd9".to_string(), "#ffd9b3".to_string(), "#d9ffb3".to_string(), "#ffb3b3".to_string(), ],
164 text_color: "#495057".to_string(),
165 title_color: "#6c757d".to_string(),
166 score_color: "#28a745".to_string(),
167 best_score_color: "#ffc107".to_string(),
168 moves_color: "#17a2b8".to_string(),
169 time_color: "#6f42c1".to_string(),
170 }
171 }
172
173 pub fn all_themes() -> Vec<Self> {
175 vec![
176 Self::default(),
177 Self::dark(),
178 Self::neon(),
179 Self::retro(),
180 Self::pastel(),
181 ]
182 }
183
184 pub fn by_name(name: &str) -> Option<Self> {
186 Self::all_themes().into_iter().find(|t| t.name == name)
187 }
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct SharedConfig {
193 pub theme: Theme,
194 pub board_size: usize,
195 pub target_score: u32,
196 pub enable_animations: bool,
197 pub enable_sound: bool,
198}
199
200impl Default for SharedConfig {
201 fn default() -> Self {
202 Self {
203 theme: Theme::default(),
204 board_size: 4,
205 target_score: 2048,
206 enable_animations: true,
207 enable_sound: false,
208 }
209 }
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct AnimationConfig {
215 pub duration_ms: u32,
216 pub easing: String,
217 pub enable_slide: bool,
218 pub enable_merge: bool,
219 pub enable_spawn: bool,
220}
221
222impl Default for AnimationConfig {
223 fn default() -> Self {
224 Self {
225 duration_ms: 150,
226 easing: "ease-out".to_string(),
227 enable_slide: true,
228 enable_merge: true,
229 enable_spawn: true,
230 }
231 }
232}