1use serde::{Deserialize, Serialize};
2use tuirealm::props::Color;
3
4#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, Debug)]
6pub enum ColorTermusic {
7 Reset = 0,
9 Foreground = 1,
10 Background = 2,
11 Black = 3,
12 Red = 4,
13 Green = 5,
14 Yellow = 6,
15 Blue = 7,
16 Magenta = 8,
17 Cyan = 9,
18 White = 10,
19 LightBlack = 11,
20 LightRed = 12,
21 LightGreen = 13,
22 LightYellow = 14,
23 LightBlue = 15,
24 LightMagenta = 16,
25 LightCyan = 17,
26 LightWhite = 18,
27}
28
29impl AsRef<str> for ColorTermusic {
30 fn as_ref(&self) -> &str {
31 match self {
32 ColorTermusic::Reset => "reset",
33 ColorTermusic::Foreground => "foreground",
34 ColorTermusic::Background => "background",
35 ColorTermusic::Black => "black",
36 ColorTermusic::Red => "red",
37 ColorTermusic::Green => "green",
38 ColorTermusic::Yellow => "yellow",
39 ColorTermusic::Blue => "blue",
40 ColorTermusic::Magenta => "magenta",
41 ColorTermusic::Cyan => "cyan",
42 ColorTermusic::White => "white",
43 ColorTermusic::LightBlack => "bright_black",
44 ColorTermusic::LightRed => "bright_red",
45 ColorTermusic::LightGreen => "bright_green",
46 ColorTermusic::LightYellow => "bright_yellow",
47 ColorTermusic::LightBlue => "bright_blue",
48 ColorTermusic::LightMagenta => "bright_magenta",
49 ColorTermusic::LightCyan => "bright_cyan",
50 ColorTermusic::LightWhite => "bright_white",
51 }
52 }
53}
54
55impl ColorTermusic {
56 #[must_use]
57 pub const fn as_usize(self) -> usize {
58 self as usize
59 }
60}
61
62impl From<ColorTermusic> for Color {
63 fn from(value: ColorTermusic) -> Self {
64 match value {
65 ColorTermusic::Reset => Color::Reset,
66 ColorTermusic::Background | ColorTermusic::Black => Color::Black,
67 ColorTermusic::Red => Color::Red,
68 ColorTermusic::Green => Color::Green,
69 ColorTermusic::Yellow => Color::Yellow,
70 ColorTermusic::Blue => Color::Blue,
71 ColorTermusic::Magenta => Color::Magenta,
72 ColorTermusic::Cyan => Color::Cyan,
73 ColorTermusic::White => Color::Gray,
74 ColorTermusic::LightBlack => Color::DarkGray,
75 ColorTermusic::LightRed => Color::LightRed,
76 ColorTermusic::LightGreen => Color::LightGreen,
77 ColorTermusic::LightYellow => Color::LightYellow,
78 ColorTermusic::LightBlue => Color::LightBlue,
79 ColorTermusic::LightMagenta => Color::LightMagenta,
80 ColorTermusic::LightCyan => Color::LightCyan,
81 ColorTermusic::Foreground | ColorTermusic::LightWhite => Color::White,
82 }
83 }
84}
85
86#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Default)]
88#[serde(default)] pub struct Styles {
90 pub library: StyleLibrary,
91 pub playlist: StylePlaylist,
92 pub lyric: StyleLyric,
93 pub progress: StyleProgress,
94 pub important_popup: StyleImportantPopup,
95 pub fallback: StyleFallback,
96}
97
98#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
100#[serde(default)] pub struct StyleLibrary {
102 pub foreground_color: ColorTermusic,
104 pub background_color: ColorTermusic,
106 pub border_color: ColorTermusic,
108 pub highlight_color: ColorTermusic,
110
111 pub highlight_symbol: String,
113}
114
115impl Default for StyleLibrary {
116 fn default() -> Self {
117 Self {
118 foreground_color: ColorTermusic::Foreground,
119 background_color: ColorTermusic::Reset,
120 border_color: ColorTermusic::Blue,
121 highlight_color: ColorTermusic::LightYellow,
122
123 highlight_symbol: "🦄".into(),
124 }
125 }
126}
127
128#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
130#[serde(default)] pub struct StylePlaylist {
132 pub foreground_color: ColorTermusic,
134 pub background_color: ColorTermusic,
136 pub border_color: ColorTermusic,
138 pub highlight_color: ColorTermusic,
140
141 pub highlight_symbol: String,
143 pub current_track_symbol: String,
145
146 pub use_loop_mode_symbol: bool,
150}
151
152impl Default for StylePlaylist {
153 fn default() -> Self {
154 Self {
155 foreground_color: ColorTermusic::Foreground,
156 background_color: ColorTermusic::Reset,
157 border_color: ColorTermusic::Blue,
158 highlight_color: ColorTermusic::LightYellow,
159
160 highlight_symbol: "🚀".into(),
161 current_track_symbol: "►".into(),
162
163 use_loop_mode_symbol: true,
164 }
165 }
166}
167
168#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
170#[serde(default)] pub struct StyleLyric {
172 pub foreground_color: ColorTermusic,
174 pub background_color: ColorTermusic,
176 pub border_color: ColorTermusic,
178}
179
180impl Default for StyleLyric {
181 fn default() -> Self {
182 Self {
183 foreground_color: ColorTermusic::Foreground,
184 background_color: ColorTermusic::Reset,
185 border_color: ColorTermusic::Blue,
186 }
187 }
188}
189
190#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
192#[serde(default)] pub struct StyleProgress {
194 pub foreground_color: ColorTermusic,
196 pub background_color: ColorTermusic,
198 pub border_color: ColorTermusic,
200}
201
202impl Default for StyleProgress {
203 fn default() -> Self {
204 Self {
205 foreground_color: ColorTermusic::LightBlack,
206 background_color: ColorTermusic::Reset,
207 border_color: ColorTermusic::Blue,
208 }
209 }
210}
211
212#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
214#[serde(default)] pub struct StyleImportantPopup {
216 pub foreground_color: ColorTermusic,
218 pub background_color: ColorTermusic,
220 pub border_color: ColorTermusic,
222}
223
224impl Default for StyleImportantPopup {
225 fn default() -> Self {
226 Self {
227 foreground_color: ColorTermusic::Yellow,
228 background_color: ColorTermusic::Reset,
229 border_color: ColorTermusic::Yellow,
230 }
231 }
232}
233
234#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
236#[serde(default)] pub struct StyleFallback {
238 pub foreground_color: ColorTermusic,
240 pub background_color: ColorTermusic,
242 pub border_color: ColorTermusic,
244 pub highlight_color: ColorTermusic,
246}
247
248impl Default for StyleFallback {
249 fn default() -> Self {
250 Self {
251 foreground_color: ColorTermusic::Foreground,
252 background_color: ColorTermusic::Reset,
253 border_color: ColorTermusic::Blue,
254 highlight_color: ColorTermusic::LightYellow,
255 }
256 }
257}
258
259mod v1_interop {
260 use super::{
261 ColorTermusic, StyleFallback, StyleImportantPopup, StyleLibrary, StyleLyric, StylePlaylist,
262 StyleProgress, Styles,
263 };
264 use crate::config::v1;
265
266 impl From<v1::ColorTermusic> for ColorTermusic {
267 fn from(value: v1::ColorTermusic) -> Self {
268 match value {
269 v1::ColorTermusic::Reset => Self::Reset,
270 v1::ColorTermusic::Foreground => Self::Foreground,
271 v1::ColorTermusic::Background => Self::Background,
272 v1::ColorTermusic::Black => Self::Black,
273 v1::ColorTermusic::Red => Self::Red,
274 v1::ColorTermusic::Green => Self::Green,
275 v1::ColorTermusic::Yellow => Self::Yellow,
276 v1::ColorTermusic::Blue => Self::Blue,
277 v1::ColorTermusic::Magenta => Self::Magenta,
278 v1::ColorTermusic::Cyan => Self::Cyan,
279 v1::ColorTermusic::White => Self::White,
280 v1::ColorTermusic::LightBlack => Self::LightBlack,
281 v1::ColorTermusic::LightRed => Self::LightRed,
282 v1::ColorTermusic::LightGreen => Self::LightGreen,
283 v1::ColorTermusic::LightYellow => Self::LightYellow,
284 v1::ColorTermusic::LightBlue => Self::LightBlue,
285 v1::ColorTermusic::LightMagenta => Self::LightMagenta,
286 v1::ColorTermusic::LightCyan => Self::LightCyan,
287 v1::ColorTermusic::LightWhite => Self::LightWhite,
288 }
289 }
290 }
291
292 impl From<&v1::StyleColorSymbol> for StyleLibrary {
293 fn from(value: &v1::StyleColorSymbol) -> Self {
294 Self {
295 foreground_color: value.library_foreground.into(),
296 background_color: value.library_background.into(),
297 border_color: value.library_border.into(),
298 highlight_color: value.library_highlight.into(),
299
300 highlight_symbol: value.library_highlight_symbol.clone(),
301 }
302 }
303 }
304
305 impl From<&v1::Settings> for StylePlaylist {
306 fn from(value: &v1::Settings) -> Self {
307 let use_loop_mode_symbol = value.playlist_display_symbol;
308 let value = &value.style_color_symbol;
309 Self {
310 foreground_color: value.playlist_foreground.into(),
311 background_color: value.playlist_background.into(),
312 border_color: value.playlist_border.into(),
313 highlight_color: value.playlist_highlight.into(),
314 highlight_symbol: value.playlist_highlight_symbol.clone(),
315 current_track_symbol: value.currently_playing_track_symbol.clone(),
316 use_loop_mode_symbol,
317 }
318 }
319 }
320
321 impl From<&v1::StyleColorSymbol> for StyleLyric {
322 fn from(value: &v1::StyleColorSymbol) -> Self {
323 Self {
324 foreground_color: value.lyric_foreground.into(),
325 background_color: value.lyric_background.into(),
326 border_color: value.lyric_border.into(),
327 }
328 }
329 }
330
331 impl From<&v1::StyleColorSymbol> for StyleProgress {
332 fn from(value: &v1::StyleColorSymbol) -> Self {
333 Self {
334 foreground_color: value.progress_foreground.into(),
335 background_color: value.progress_background.into(),
336 border_color: value.progress_border.into(),
337 }
338 }
339 }
340
341 impl From<&v1::StyleColorSymbol> for StyleImportantPopup {
342 fn from(value: &v1::StyleColorSymbol) -> Self {
343 Self {
344 foreground_color: value.important_popup_foreground.into(),
345 background_color: value.important_popup_background.into(),
346 border_color: value.important_popup_border.into(),
347 }
348 }
349 }
350
351 impl From<&v1::StyleColorSymbol> for StyleFallback {
352 fn from(value: &v1::StyleColorSymbol) -> Self {
353 Self {
354 foreground_color: value.fallback_foreground.into(),
355 background_color: value.fallback_background.into(),
356 border_color: value.fallback_border.into(),
357 highlight_color: value.fallback_highlight.into(),
358 }
359 }
360 }
361
362 impl From<&v1::Settings> for Styles {
363 fn from(value: &v1::Settings) -> Self {
364 let playlist = value.into();
365 let value = &value.style_color_symbol;
366 Self {
367 library: value.into(),
368 playlist,
369 lyric: value.into(),
370 progress: value.into(),
371 important_popup: value.into(),
372 fallback: value.into(),
373 }
374 }
375 }
376
377 #[cfg(test)]
378 mod tests {
379 use super::*;
380
381 #[test]
382 fn should_convert_default_without_error() {
383 let converted: Styles = (&v1::Settings::default()).into();
384
385 let expected_library = StyleLibrary {
386 foreground_color: ColorTermusic::Foreground,
387 background_color: ColorTermusic::Reset,
388 border_color: ColorTermusic::Blue,
389 highlight_color: ColorTermusic::LightYellow,
390
391 highlight_symbol: "🦄".into(),
392 };
393 assert_eq!(converted.library, expected_library);
394
395 let expected_playlist = StylePlaylist {
396 foreground_color: ColorTermusic::Foreground,
397 background_color: ColorTermusic::Reset,
398 border_color: ColorTermusic::Blue,
399 highlight_color: ColorTermusic::LightYellow,
400
401 highlight_symbol: "🚀".into(),
402 current_track_symbol: "►".into(),
403 use_loop_mode_symbol: true,
404 };
405 assert_eq!(converted.playlist, expected_playlist);
406
407 let expected_lyric = StyleLyric {
408 foreground_color: ColorTermusic::Foreground,
409 background_color: ColorTermusic::Reset,
410 border_color: ColorTermusic::Blue,
411 };
412 assert_eq!(converted.lyric, expected_lyric);
413
414 let expected_progress = StyleProgress {
415 foreground_color: ColorTermusic::LightBlack,
416 background_color: ColorTermusic::Reset,
417 border_color: ColorTermusic::Blue,
418 };
419 assert_eq!(converted.progress, expected_progress);
420
421 let expected_important_popup = StyleImportantPopup {
422 foreground_color: ColorTermusic::Yellow,
423 background_color: ColorTermusic::Reset,
424 border_color: ColorTermusic::Yellow,
425 };
426 assert_eq!(converted.important_popup, expected_important_popup);
427
428 let expected_fallback = StyleFallback {
429 foreground_color: ColorTermusic::Foreground,
430 background_color: ColorTermusic::Reset,
431 border_color: ColorTermusic::Blue,
432 highlight_color: ColorTermusic::LightYellow,
433 };
434 assert_eq!(converted.fallback, expected_fallback);
435
436 assert_eq!(
437 converted,
438 Styles {
439 library: expected_library,
440 playlist: expected_playlist,
441 lyric: expected_lyric,
442 progress: expected_progress,
443 important_popup: expected_important_popup,
444 fallback: expected_fallback
445 }
446 );
447 }
448 }
449}