feat: add persistent theme cycling
Closes #1
diff --git a/src/main.rs b/src/main.rs
@@ -85,12 +85,12 @@ struct AppState {
likes: HashMap<i64, LikedSong>, likes_file: PathBuf, status_message: String, is_muted: bool,
mode: AppMode, liked_list_state: ListState, selected_art: Option<StatefulProtocol>,
show_help_overlay: bool, show_unlike_confirm: Option<i64>, show_song_info: bool,
- theme_color: Color, available_colors: Vec<Color>, color_idx: usize,
+ theme_color: Color, available_colors: Vec<Color>, color_idx: usize, theme_file: PathBuf,
}
impl AppState {
fn new() -> Self {
- let config_dir = PathBuf::from(env::var("HOME").unwrap_or_default()).join(".config/gr-tui");
+ let config_dir = PathBuf::from(env::var("HOME").unwrap_or_default()).join(".config/grrs");
fs::create_dir_all(&config_dir).ok();
let likes_file = config_dir.join("likes.json");
@@ -102,12 +102,31 @@ impl AppState {
Color::Gray, Color::White,
];
+ let cache_dir = env::var("XDG_CACHE_HOME")
+ .map(PathBuf::from)
+ .unwrap_or_else(|_| PathBuf::from(env::var("HOME").unwrap_or_default()).join(".cache"))
+ .join("grrs");
+ fs::create_dir_all(&cache_dir).ok();
+ let theme_file = cache_dir.join("theme.txt");
+
+ let mut theme_color = SEAFOAM;
+ let mut color_idx = 0;
+
+ if let Ok(idx_str) = fs::read_to_string(&theme_file) {
+ if let Ok(idx) = idx_str.trim().parse::<usize>() {
+ if idx < available_colors.len() {
+ color_idx = idx;
+ theme_color = available_colors[color_idx];
+ }
+ }
+ }
+
Self {
song: SongData::default(), song_start_time: Instant::now(), art_protocol: None, live_art_bytes: None,
likes, likes_file, status_message: "Connecting to Gensokyo Radio...".to_string(), is_muted: false,
mode: AppMode::Playing, liked_list_state: ListState::default(), selected_art: None,
show_help_overlay: false, show_unlike_confirm: None, show_song_info: false,
- theme_color: SEAFOAM, available_colors, color_idx: 0,
+ theme_color, available_colors, color_idx, theme_file,
}
}
@@ -134,6 +153,7 @@ impl AppState {
fn cycle_theme(&mut self) {
self.color_idx = (self.color_idx + 1) % self.available_colors.len();
self.theme_color = self.available_colors[self.color_idx];
+ let _ = fs::write(&self.theme_file, self.color_idx.to_string());
}
}
@@ -473,7 +493,7 @@ async fn handle_input(evt: CEvent, state: &mut AppState, tx: &mpsc::Sender<AppEv
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
- let socket_path = "/tmp/gr-tui-rs.sock";
+ let socket_path = "/tmp/grrs.sock";
let _ = fs::remove_file(socket_path);
let mpv_process = Command::new("mpv")
@@ -490,7 +510,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, mut rx) = mpsc::channel(32);
let mut state = AppState::new();
- let mut controls = MediaControls::new(PlatformConfig { dbus_name: "gr-tui", display_name: "Gensokyo Radio TUI", hwnd: None }).ok();
+ let mut controls = MediaControls::new(PlatformConfig { dbus_name: "grrs", display_name: "Gensokyo Radio TUI", hwnd: None }).ok();
if let Some(ref mut c) = controls {
let tx_media = tx.clone();
c.attach(move |event| { let _ = tx_media.blocking_send(AppEvent::MediaControl(event)); }).ok();