Commit 3d3f2d8

mo khan <mo@mokhan.ca>
2025-06-25 05:23:42
feat: load podcasts from feed configuration
1 parent a6a6bd6
src/config.rs
@@ -25,8 +25,16 @@ impl Config {
         let content = fs::read_to_string(&config_path)
             .with_context(|| format!("Failed to read config file: {:?}", config_path))?;
         
+        eprintln!("Loading config from: {:?}", config_path);
+        eprintln!("Config content preview: {}", &content[0..content.len().min(200)]);
+        
         let config: Config = serde_yaml::from_str(&content)
-            .with_context(|| "Failed to parse config file")?;
+            .with_context(|| format!("Failed to parse config file: {:?}", config_path))?;
+
+        eprintln!("Loaded {} feeds", config.feeds.len());
+        for (name, url) in &config.feeds {
+            eprintln!("  Feed: {} -> {}", name, url);
+        }
 
         Ok(config)
     }
@@ -49,6 +57,23 @@ impl Config {
     }
 
     fn config_path() -> Result<PathBuf> {
+        // First check for XDG config directory (preferred)
+        if let Ok(xdg_config) = std::env::var("XDG_CONFIG_HOME") {
+            let path = PathBuf::from(xdg_config).join("ghetto-blaster.yml");
+            if path.exists() {
+                return Ok(path);
+            }
+        }
+        
+        // Then check ~/.config/ghetto-blaster.yml (Unix standard)
+        if let Some(home_dir) = dirs::home_dir() {
+            let path = home_dir.join(".config").join("ghetto-blaster.yml");
+            if path.exists() {
+                return Ok(path);
+            }
+        }
+        
+        // Fall back to platform-specific config directory
         let config_dir = dirs::config_dir()
             .with_context(|| "Failed to find config directory")?;
         
src/main.rs
@@ -1,4 +1,4 @@
-use anyhow::Result;
+use anyhow::{Context, Result};
 use crossterm::{
     event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
     execute,
@@ -22,15 +22,58 @@ mod player;
 use app::{App, CurrentScreen};
 
 fn main() -> Result<()> {
-    // Setup terminal
-    enable_raw_mode()?;
+    // Create app first
+    let mut app = App::new()?;
+
+    // Check if we're in a proper terminal environment
+    // Note: Temporarily disabled TTY check for debugging
+    // if !atty::is(atty::Stream::Stdout) {
+    //     return Err(anyhow::anyhow!("This application requires a terminal/TTY to run"));
+    // }
+
+    // Try different approach for macOS compatibility
     let mut stdout = io::stdout();
-    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
+    
+    // Set up panic handler to cleanup terminal
+    std::panic::set_hook(Box::new(|_| {
+        let _ = disable_raw_mode();
+        let _ = execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture);
+    }));
+    
+    // Try to enable raw mode with a fallback
+    let raw_mode_enabled = match enable_raw_mode() {
+        Ok(()) => true,
+        Err(e) => {
+            eprintln!("Warning: Could not enable raw mode: {}", e);
+            eprintln!("This is a known issue on some terminal environments.");
+            eprintln!("Common solutions:");
+            eprintln!("  1. Run in Terminal.app or iTerm2 directly");
+            eprintln!("  2. Check terminal permissions in System Preferences");
+            eprintln!("  3. Try running with: script -q /dev/null cargo run");
+            eprintln!("");
+            eprintln!("For testing purposes, we'll continue without raw mode...");
+            false
+        }
+    };
+    
+    if !raw_mode_enabled {
+        // Simple mode - just show the config and exit
+        println!("\n=== GHETTO-BLASTER CONFIG TEST ===");
+        println!("App initialized successfully!");
+        println!("Loaded {} feeds:", app.feeds.len());
+        for (i, feed) in app.feeds.iter().enumerate() {
+            println!("  {}. {}", i + 1, feed.name);
+            println!("     Episodes loaded: {}", feed.episodes.len());
+        }
+        println!("\nTo use the full TUI interface, run this app in a proper terminal.");
+        return Ok(());
+    }
+    
+    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)
+        .with_context(|| "Failed to setup terminal screen")?;
     let backend = CrosstermBackend::new(stdout);
-    let mut terminal = Terminal::new(backend)?;
-
-    // Create app
-    let mut app = App::new()?;
+    let mut terminal = Terminal::new(backend)
+        .with_context(|| "Failed to create terminal")?;
 
     // Main loop
     let res = run_app(&mut terminal, &mut app);
Cargo.toml
@@ -23,6 +23,9 @@ chrono = { version = "0.4", features = ["serde"] }
 # Error handling
 anyhow = "1.0"
 
+# TTY detection
+atty = "0.2"
+
 # Audio playback (using std::process)
 
 # Async runtime