termusiclib/config/v2/tui/
mod.rsuse std::path::Path;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use super::server::ComSettings;
pub mod config_extra;
pub mod keys;
pub mod theme;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Default)]
#[serde(default)] #[allow(clippy::module_name_repetitions)]
pub struct TuiSettings {
pub com: MaybeComSettings,
#[serde(skip)]
pub com_resolved: Option<ComSettings>,
pub behavior: BehaviorSettings,
pub coverart: CoverArtPosition,
#[serde(flatten)]
pub theme: theme::ThemeWrap,
pub keys: keys::Keys,
}
impl TuiSettings {
pub fn resolve_com(&mut self, tui_path: &Path) -> Result<()> {
if self.com_resolved.is_some() {
return Ok(());
}
match self.com {
MaybeComSettings::ComSettings(ref v) => {
self.com_resolved = Some(*v);
return Ok(());
}
MaybeComSettings::Same => (),
}
let server_path = tui_path
.parent()
.context("tui_path should have a parent directory")?
.join(super::server::config_extra::FILE_NAME);
let server_settings =
super::server::config_extra::ServerConfigVersionedDefaulted::from_file(server_path)
.context("parsing server config")?;
self.com_resolved = Some(server_settings.into_settings().com);
Ok(())
}
pub fn get_com(&self) -> Option<&ComSettings> {
self.com_resolved.as_ref()
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct BehaviorSettings {
pub quit_server_on_exit: bool,
pub confirm_quit: bool,
}
impl Default for BehaviorSettings {
fn default() -> Self {
Self {
quit_server_on_exit: true,
confirm_quit: true,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum MaybeComSettings {
ComSettings(ComSettings),
#[default]
Same,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
#[serde(default)] #[derive(Default)]
pub struct CoverArtPosition {
pub align: Alignment,
pub size_scale: i8,
pub hidden: bool,
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, Default, PartialEq, Eq)]
pub enum Alignment {
#[serde(rename = "top right")]
TopRight,
#[serde(rename = "top left")]
TopLeft,
#[serde(rename = "bottom right")]
#[default]
BottomRight,
#[serde(rename = "bottom left")]
BottomLeft,
}
mod v1_interop {
use super::{Alignment, BehaviorSettings, CoverArtPosition, MaybeComSettings, TuiSettings};
use crate::config::v1;
impl From<v1::Alignment> for Alignment {
fn from(value: v1::Alignment) -> Self {
match value {
v1::Alignment::BottomRight => Self::BottomRight,
v1::Alignment::BottomLeft => Self::BottomLeft,
v1::Alignment::TopRight => Self::TopRight,
v1::Alignment::TopLeft => Self::TopLeft,
}
}
}
#[allow(clippy::cast_possible_truncation)] impl From<v1::Xywh> for CoverArtPosition {
fn from(value: v1::Xywh) -> Self {
Self {
align: value.align.into(),
size_scale: value.width_between_1_100.clamp(0, i8::MAX as u32) as i8,
hidden: Self::default().hidden,
}
}
}
impl From<v1::Settings> for TuiSettings {
fn from(value: v1::Settings) -> Self {
let theme = (&value).into();
Self {
com: MaybeComSettings::Same,
com_resolved: None,
behavior: BehaviorSettings {
quit_server_on_exit: value.kill_daemon_when_quit,
confirm_quit: value.enable_exit_confirmation,
},
coverart: value.album_photo_xywh.into(),
theme,
keys: value.keys.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_convert_default_without_error() {
let converted: TuiSettings = v1::Settings::default().into();
assert_eq!(converted.com, MaybeComSettings::Same);
assert_eq!(
converted.behavior,
BehaviorSettings {
quit_server_on_exit: true,
confirm_quit: true
}
);
assert_eq!(
converted.coverart,
CoverArtPosition {
align: Alignment::BottomRight,
size_scale: 20,
hidden: false
}
);
}
}
}