fido 0.1.6

A blazing-fast, keyboard-driven social platform for developers
Documentation
mod api;
mod app;
mod auth;
mod config;
mod debug_log;
mod emoji;
mod event_loop;
#[macro_use]
mod logging;
#[macro_use]
mod reply_debug_log;
mod session;
mod terminal;
mod text_wrapper;
mod ui;

use anyhow::Result;
use app::App;
use clap::Parser;

/// Fido - A blazing-fast, keyboard-driven social platform for developers
#[derive(Parser)]
#[command(name = "fido")]
#[command(about = "A terminal-based social network for developers")]
#[command(version)]
struct Cli {
    /// Server URL to connect to
    #[arg(long, short, env = "FIDO_SERVER_URL")]
    server: Option<String>,

    /// Enable verbose logging
    #[arg(long, short)]
    verbose: bool,
}

// Load environment variables from .env file
// This allows FIDO_SERVER_URL and other config to be set without command-line args
fn load_env() {
    // Load from workspace root .env file (fido/.env)
    let _ = dotenv::dotenv();
}

// Performance optimization notes:
// - Lazy rendering: Only visible posts/messages are rendered (not all 1000+)
// - Virtual scrolling: Empty lines represent off-screen content
// - Viewport caching: Terminal size changes trigger viewport recalculation
// - Smooth scrolling: Scroll margin keeps selected item in middle third
// - Minimal redraws: Only changed portions trigger re-render
//
// Performance testing recommendations:
// 1. Test with 1000+ posts: Create test data with large post count
// 2. Monitor frame rate: Should maintain 60fps even with large datasets
// 3. Memory usage: Should remain constant regardless of post count
// 4. Scroll responsiveness: j/k navigation should feel instant

#[tokio::main]
async fn main() -> Result<()> {
    // Parse command-line arguments
    let cli = Cli::parse();

    // Load environment variables from .env file
    load_env();

    // Initialize logging system
    // Only enable logging if --verbose flag is passed (production default: disabled)
    let log_config = if cli.verbose {
        logging::LogConfig::verbose()
    } else {
        logging::LogConfig::disabled()
    };
    logging::init_logging(&log_config)?;

    // Initialize terminal
    let mut tui = terminal::init()?;

    // Check if running in demo mode
    let is_demo_mode = std::env::var("FIDO_DEMO_MODE").is_ok();

    // Create app based on mode
    let mut app = if is_demo_mode {
        // Demo mode - use MockBackend
        log::info!("Starting in DEMO MODE with MockBackend");
        App::demo()
    } else if let Some(server_url) = cli.server {
        // Custom server URL
        App::with_server_url(server_url)
    } else {
        // Default mode
        App::new()
    };
    
    app.log_config = log_config;

    // Check if running in web mode (for web terminal interface)
    let is_web_mode = std::env::var("FIDO_WEB_MODE").is_ok();

    // In web mode or demo mode, hide GitHub OAuth option (test users only)
    if is_web_mode || is_demo_mode {
        app.auth_state.show_github_option = false;
    }

    // Check for existing session on startup (skip in web mode and demo mode)
    let mut auth_flow = auth::AuthFlow::new(app.api_client.clone())?;
    if !is_web_mode && !is_demo_mode {
        if let Ok(Some(user)) = auth_flow.check_existing_session().await {
            log::info!("Restored session for user: {}", user.username);
            app.auth_state.current_user = Some(user);
            app.current_screen = app::Screen::Main;

            // Update API client with session token
            app.api_client = auth_flow.api_client().clone();

            // Load initial data
            let _ = app.load_settings().await;
            app.load_filter_preference();
            let _ = app.load_posts().await;
        } else {
            log::info!("No valid session found, showing authentication screen");
            // Load test users for authentication screen
            let _ = app.load_test_users().await;
        }
    } else {
        if is_demo_mode {
            log::info!("Running in demo mode, loading test users only");
        } else {
            log::info!("Running in web mode, loading test users only");
        }
        // In web mode or demo mode, always show test users (no GitHub OAuth, no session restore)
        let _ = app.load_test_users().await;
    }

    // Main event loop
    let mut event_loop = event_loop::EventLoop::new();

    event_loop.run(&mut app, &mut auth_flow, &mut tui).await?;

    // Restore terminal
    terminal::restore()?;

    Ok(())
}