Ejemplos de Características Móviles Web Rust

Ejemplos de características móviles Web Rust incluyendo información del dispositivo, estado de red y retroalimentación háptica

💻 Información del Dispositivo rust

🟢 simple ⭐⭐⭐

Obtener información del dispositivo usando APIs del navegador

⏱️ 20 min 🏷️ rust, web, mobile features
Prerequisites: Basic Rust, Understanding of Web APIs
// Web Rust Device Information Examples
// Device information detection using browser Web APIs
//
// This demonstrates device info detection that would work in WebAssembly (WASM) context
//
// In WASM, you would use JavaScript interop with:
// - navigator.userAgent
// - window.screen
// - navigator.deviceMemory
// - navigator.hardwareConcurrency
// - window.matchMedia

use serde::{Deserialize, Serialize};

// 1. Device Information Structure

/// Device information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct DeviceInfo {
    user_agent: String,
    platform: String,
    vendor: String,
    language: String,
    cookies_enabled: bool,
    on_line: bool,
    hardware_concurrency: u32,
    device_memory: Option<u32>,
    max_touch_points: u32,
}

/// Screen information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ScreenInfo {
    width: u32,
    height: u32,
    avail_width: u32,
    avail_height: u32,
    color_depth: u32,
    pixel_depth: u32,
    device_pixel_ratio: f64,
    orientation: String,
}

/// Viewport information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ViewportInfo {
    width: u32,
    height: u32,
    scroll_x: f64,
    scroll_y: f64,
}

// 2. Device Detection

/// Detect if device is mobile
fn is_mobile(user_agent: &str) -> bool {
    let mobile_keywords = [
        "android", "iphone", "ipad", "ipod", "windows phone",
        "blackberry", "mobile", "webos", "opera mini"
    ];

    let lower = user_agent.to_lowercase();
    mobile_keywords.iter().any(|&keyword| lower.contains(keyword))
}

/// Detect device type
#[derive(Debug, Clone, PartialEq, Eq)]
enum DeviceType {
    Desktop,
    Mobile,
    Tablet,
    Unknown,
}

fn detect_device_type(user_agent: &str, screen_width: u32) -> DeviceType {
    let lower = user_agent.to_lowercase();

    if lower.contains("ipad") || lower.contains("tablet") {
        DeviceType::Tablet
    } else if is_mobile(user_agent) {
        // Check screen size for better tablet detection
        if screen_width >= 768 {
            DeviceType::Tablet
        } else {
            DeviceType::Mobile
        }
    } else {
        DeviceType::Desktop
    }
}

/// Detect operating system
#[derive(Debug, Clone, PartialEq, Eq)]
enum OperatingSystem {
    Windows,
    MacOS,
    Linux,
    Android,
    IOS,
    Unknown,
}

fn detect_os(user_agent: &str) -> OperatingSystem {
    let lower = user_agent.to_lowercase();

    if lower.contains("windows") {
        OperatingSystem::Windows
    } else if lower.contains("mac os x") || lower.contains("macos") {
        OperatingSystem::MacOS
    } else if lower.contains("linux") && !lower.contains("android") {
        OperatingSystem::Linux
    } else if lower.contains("android") {
        OperatingSystem::Android
    } else if lower.contains("iphone") || lower.contains("ipad") || lower.contains("ipod") {
        OperatingSystem::IOS
    } else {
        OperatingSystem::Unknown
    }
}

/// Detect browser
#[derive(Debug, Clone, PartialEq, Eq)]
enum Browser {
    Chrome,
    Firefox,
    Safari,
    Edge,
    Opera,
    Unknown,
}

fn detect_browser(user_agent: &str) -> Browser {
    let lower = user_agent.to_lowercase();

    if lower.contains("edg") {
        Browser::Edge
    } else if lower.contains("opr") || lower.contains("opera") {
        Browser::Opera
    } else if lower.contains("chrome") && !lower.contains("edg") {
        Browser::Chrome
    } else if lower.contains("firefox") {
        Browser::Firefox
    } else if lower.contains("safari") && !lower.contains("chrome") {
        Browser::Safari
    } else {
        Browser::Unknown
    }
}

// 3. Feature Detection

/// Check for touch support
fn has_touch_support() -> bool {
    // In WASM, would check: ('ontouchstart' in window) || (navigator.maxTouchPoints > 0)
    true // Simulated
}

/// Check for WebGL support
fn has_webgl_support() -> bool {
    // In WASM, would check for WebGL context
    true // Simulated
}

/// Check for localStorage support
fn has_local_storage() -> bool {
    // In WASM, would try to access localStorage
    true // Simulated
}

/// Check for service worker support
fn has_service_worker() -> bool {
    // In WASM, would check: 'serviceWorker' in navigator
    true // Simulated
}

/// Check for web worker support
fn has_web_worker() -> bool {
    // In WASM, would check: 'Worker' in window
    true // Simulated
}

/// Check for geolocation support
fn has_geolocation() -> bool {
    // In WASM, would check: 'geolocation' in navigator
    true // Simulated
}

// 4. Capability Information

/// Device capabilities
#[derive(Debug, Clone, Serialize, Deserialize)]
struct DeviceCapabilities {
    touch_support: bool,
    webgl: bool,
    local_storage: bool,
    session_storage: bool,
    service_worker: bool,
    web_worker: bool,
    geolocation: bool,
    web_socket: bool,
    webrtc: bool,
}

impl DeviceCapabilities {
    fn new() -> Self {
        DeviceCapabilities {
            touch_support: has_touch_support(),
            webgl: has_webgl_support(),
            local_storage: has_local_storage(),
            session_storage: has_local_storage(), // Usually same as localStorage
            service_worker: has_service_worker(),
            web_worker: has_web_worker(),
            geolocation: has_geolocation(),
            web_socket: true, // Generally available
            webrtc: true,     // Would need actual check
        }
    }
}

// 5. Battery Information

/// Battery information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct BatteryInfo {
    level: f64,
    charging: bool,
    charging_time: Option<i32>,
    discharging_time: Option<i32>,
}

// Battery API is not available in all browsers, this is a mock
fn get_battery_info() -> Option<BatteryInfo> {
    // In WASM, would use: navigator.getBattery()
    Some(BatteryInfo {
        level: 0.85,
        charging: true,
        charging_time: Some(3600),
        discharging_time: None,
    })
}

// 6. Network Information

/// Connection type
#[derive(Debug, Clone, PartialEq, Eq)]
enum ConnectionType {
    Bluetooth,
    Cellular,
    Ethernet,
    None,
    Wifi,
    Wimax,
    Other,
    Unknown,
}

/// Network information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct NetworkInfo {
    type_: ConnectionType,
    effective_type: String,
    downlink: f64,
    rtt: u32,
    save_data: bool,
}

// Network Information API is experimental
fn get_network_info() -> Option<NetworkInfo> {
    // In WASM, would use: navigator.connection
    Some(NetworkInfo {
        type_: ConnectionType::Wifi,
        effective_type: "4g".to_string(),
        downlink: 10.0,
        rtt: 50,
        save_data: false,
    })
}

// 7. Media Devices

/// Media device information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct MediaDevices {
    has_camera: bool,
    has_microphone: bool,
    has_speakers: bool,
    camera_count: u32,
    microphone_count: u32,
}

// Media Devices API requires permissions
async fn get_media_devices() -> MediaDevices {
    // In WASM, would use: navigator.mediaDevices.enumerateDevices()
    MediaDevices {
        has_camera: true,
        has_microphone: true,
        has_speakers: true,
        camera_count: 1,
        microphone_count: 1,
    }
}

// 8. Orientation Detection

/// Device orientation
#[derive(Debug, Clone, PartialEq, Eq)]
enum Orientation {
    Portrait,
    Landscape,
}

fn get_orientation(screen_width: u32, screen_height: u32) -> Orientation {
    if screen_width > screen_height {
        Orientation::Landscape
    } else {
        Orientation::Portrait
    }
}

// 9. Device Information Collector

/// Complete device information
#[derive(Debug, Clone, Serialize, Deserialize)]
struct CompleteDeviceInfo {
    device: DeviceInfo,
    screen: ScreenInfo,
    viewport: ViewportInfo,
    device_type: DeviceType,
    os: OperatingSystem,
    browser: Browser,
    capabilities: DeviceCapabilities,
    battery: Option<BatteryInfo>,
    network: Option<NetworkInfo>,
}

impl CompleteDeviceInfo {
    fn collect() -> Self {
        // Simulated data - in WASM would use actual browser APIs
        CompleteDeviceInfo {
            device: DeviceInfo {
                user_agent: "Mozilla/5.0 (WebAssembly Simulator)".to_string(),
                platform: "Web".to_string(),
                vendor: "Unknown".to_string(),
                language: "en-US".to_string(),
                cookies_enabled: true,
                on_line: true,
                hardware_concurrency: 8,
                device_memory: Some(8),
                max_touch_points: 5,
            },
            screen: ScreenInfo {
                width: 1920,
                height: 1080,
                avail_width: 1920,
                avail_height: 1050,
                color_depth: 24,
                pixel_depth: 24,
                device_pixel_ratio: 1.0,
                orientation: "landscape-primary".to_string(),
            },
            viewport: ViewportInfo {
                width: 1920,
                height: 1080,
                scroll_x: 0.0,
                scroll_y: 0.0,
            },
            device_type: DeviceType::Desktop,
            os: OperatingSystem::Unknown,
            browser: Browser::Unknown,
            capabilities: DeviceCapabilities::new(),
            battery: get_battery_info(),
            network: get_network_info(),
        }
    }
}

// 10. User Preference Detection

/// Color scheme preference
#[derive(Debug, Clone, PartialEq, Eq)]
enum ColorScheme {
    Light,
    Dark,
    NoPreference,
}

fn get_preferred_color_scheme() -> ColorScheme {
    // In WASM, would use: window.matchMedia('(prefers-color-scheme: dark)').matches
    ColorScheme::NoPreference
}

/// Reduced motion preference
fn prefers_reduced_motion() -> bool {
    // In WASM, would use: window.matchMedia('(prefers-reduced-motion: reduce)').matches
    false
}

/// High contrast preference
fn prefers_high_contrast() -> bool {
    // In WASM, would use: window.matchMedia('(prefers-contrast: high)').matches
    false
}

// Usage Examples
fn main() {
    println!("=== Web Rust Device Information Examples ===\n");

    // 1. Device detection
    println!("--- 1. Device Detection ---");
    let user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)";
    println!("Is mobile: {}", is_mobile(user_agent));
    println!("Device type: {:?}", detect_device_type(user_agent, 375));
    println!("OS: {:?}", detect_os(user_agent));
    println!("Browser: {:?}", detect_browser(user_agent));

    // 2. Complete device info
    println!("
--- 2. Complete Device Info ---");
    let device_info = CompleteDeviceInfo::collect();
    println!("{:?}", device_info);

    // 3. Capabilities
    println!("
--- 3. Device Capabilities ---");
    let caps = DeviceCapabilities::new();
    println!("Touch support: {}", caps.touch_support);
    println!("WebGL: {}", caps.webgl);
    println!("Service Worker: {}", caps.service_worker);
    println!("Geolocation: {}", caps.geolocation);

    // 4. Battery
    println!("
--- 4. Battery Information ---");
    if let Some(battery) = get_battery_info() {
        println!("Level: {}%", battery.level * 100.0);
        println!("Charging: {}", battery.charging);
    }

    // 5. Network
    println!("
--- 5. Network Information ---");
    if let Some(network) = get_network_info() {
        println!("Type: {:?}", network.type_);
        println!("Effective type: {}", network.effective_type);
        println!("Downlink: {} Mbps", network.downlink);
    }

    // 6. Orientation
    println!("
--- 6. Orientation ---");
    println!("Current orientation: {:?}", get_orientation(1920, 1080));
    println!("Portrait orientation: {:?}", get_orientation(375, 667));

    // 7. User preferences
    println!("
--- 7. User Preferences ---");
    println!("Color scheme: {:?}", get_preferred_color_scheme());
    println!("Reduced motion: {}", prefers_reduced_motion());
    println!("High contrast: {}", prefers_high_contrast());

    println!("
=== Note ===");
    println!("These examples demonstrate API patterns for WASM environments.");
    println!("Actual implementation requires JavaScript interop with browser APIs.");

    println!("
=== All Device Information Examples Completed ===");
}

💻 Retroalimentación Háptica rust

🟢 simple ⭐⭐⭐

Vibración y retroalimentación háptica usando la API de Vibración del navegador

⏱️ 20 min 🏷️ rust, web, mobile features
Prerequisites: Basic Rust, Understanding of Web APIs
// Web Rust Haptic Feedback Examples
// Vibration and haptic feedback using browser Vibration API
//
// This demonstrates haptic feedback that would work in WebAssembly (WASM) context
//
// In WASM, you would use JavaScript interop with:
// - navigator.vibrate()
// - navigator.vibrate([pattern])
//
// Note: Vibration API is not available in all browsers and platforms

use std::time::Duration;

// 1. Vibration Patterns

/// Simple vibration
pub fn vibrate(duration_ms: u32) -> bool {
    // In WASM: navigator.vibrate(duration_ms)
    println!("Vibrating for {}ms", duration_ms);
    true // Simulated success
}

/// Vibration pattern (on/off in milliseconds)
pub fn vibrate_pattern(pattern: &[u32]) -> bool {
    // In WASM: navigator.vibrate(pattern)
    println!("Vibrating with pattern: {:?}", pattern);
    true // Simulated success
}

/// Stop vibration
pub fn stop_vibration() -> bool {
    // In WASM: navigator.vibrate(0)
    println!("Stopping vibration");
    true // Simulated success
}

// 2. Common Haptic Patterns

/// Success notification
pub fn vibrate_success() -> bool {
    // Two short pulses
    vibrate_pattern(&[100, 50, 100])
}

/// Error notification
pub fn vibrate_error() -> bool {
    // Three short pulses
    vibrate_pattern(&[100, 50, 100, 50, 100])
}

/// Warning notification
pub fn vibrate_warning() -> bool {
    // Long pulse
    vibrate(500)
}

/// Notification (default)
pub fn vibrate_notification() -> bool {
    // Short pulse
    vibrate(200)
}

// 3. Feedback Types

/// Type of haptic feedback
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FeedbackType {
    LightTap,
    MediumTap,
    HeavyTap,
    Success,
    Warning,
    Error,
    SelectionChanged,
    Confirm,
    Cancel,
}

impl FeedbackType {
    /// Get vibration pattern for feedback type
    pub fn pattern(&self) -> Vec<u32> {
        match self {
            FeedbackType::LightTap => vec![10],
            FeedbackType::MediumTap => vec![30],
            FeedbackType::HeavyTap => vec![50],
            FeedbackType::Success => vec![100, 50, 100],
            FeedbackType::Warning => vec![500],
            FeedbackType::Error => vec![100, 50, 100, 50, 100],
            FeedbackType::SelectionChanged => vec![20],
            FeedbackType::Confirm => vec![100, 50, 100],
            FeedbackType::Cancel => vec![50, 30, 50],
        }
    }

    /// Execute the feedback
    pub fn execute(&self) -> bool {
        vibrate_pattern(&self.pattern())
    }
}

// 4. Haptic Feedback Manager

/// Manager for haptic feedback
pub struct HapticManager {
    enabled: bool,
    intensity: f64, // 0.0 to 1.0
}

impl HapticManager {
    pub fn new() -> Self {
        HapticManager {
            enabled: true,
            intensity: 1.0,
        }
    }

    /// Enable or disable haptics
    pub fn set_enabled(&mut self, enabled: bool) {
        self.enabled = enabled;
    }

    /// Set intensity (0.0 to 1.0)
    pub fn set_intensity(&mut self, intensity: f64) {
        self.intensity = intensity.max(0.0).min(1.0);
    }

    /// Execute feedback with intensity adjustment
    pub fn feedback(&self, feedback_type: FeedbackType) -> bool {
        if !self.enabled {
            return false;
        }

        let mut pattern = feedback_type.pattern();
        // Adjust pattern based on intensity
        for duration in &mut pattern {
            *duration = (*duration as f64 * self.intensity) as u32;
        }

        vibrate_pattern(&pattern)
    }

    /// Tap feedback
    pub fn tap(&self, strength: u32) -> bool {
        if !self.enabled {
            return false;
        }
        let duration = (strength as f64 * self.intensity) as u32;
        vibrate(duration)
    }
}

impl Default for HapticManager {
    fn default() -> Self {
        Self::new()
    }
}

// 5. Advanced Patterns

/// Heartbeat pattern
pub fn vibrate_heartbeat(count: u32) -> bool {
    let mut pattern = Vec::new();
    for _ in 0..count {
        pattern.extend_from_slice(&[50, 50, 100, 200]);
    }
    vibrate_pattern(&pattern)
}

/// Rising intensity
pub fn vibrate_rising() -> bool {
    vibrate_pattern(&[50, 50, 100, 50, 150, 50, 200, 50, 250])
}

/// Falling intensity
pub fn vibrate_falling() -> bool {
    vibrate_pattern(&[250, 50, 200, 50, 150, 50, 100, 50, 50])
}

/// SOS pattern (three short, three long, three short)
pub fn vibrate_sos() -> bool {
    vibrate_pattern(&[
        100, 50, 100, 50, 100, 100,
        300, 100, 300, 100, 300, 100,
        100, 50, 100, 50, 100, 200,
    ])
}

/// Double tap
pub fn vibrate_double_tap() -> bool {
    vibrate_pattern(&[50, 100, 50])
}

/// Triple tap
pub fn vibrate_triple_tap() -> bool {
    vibrate_pattern(&[50, 50, 50, 50, 50])
}

/// Tick-tock (clock-like)
pub fn vibrate_tick_tock() -> bool {
    let mut pattern = Vec::new();
    for _ in 0..5 {
        pattern.extend_from_slice(&[50, 150]);
    }
    vibrate_pattern(&pattern)
}

/// Knock (door knock)
pub fn vibrate_knock() -> bool {
    vibrate_pattern(&[100, 100, 100, 200, 300, 300])
}

/// Typing rhythm
pub fn vibrate_typing() -> bool {
    vibrate_pattern(&[30, 50, 30, 50, 30, 50, 30])
}

/// Alarm-like
pub fn vibrate_alarm(count: u32) -> bool {
    let mut pattern = Vec::new();
    for _ in 0..count {
        pattern.extend_from_slice(&[500, 500]);
    }
    vibrate_pattern(&pattern)
}

// 6. Contextual Feedback

/// UI interaction feedback
pub struct UIFeedback {
    manager: HapticManager,
}

impl UIFeedback {
    pub fn new() -> Self {
        UIFeedback {
            manager: HapticManager::new(),
        }
    }

    /// Button press
    pub fn button_press(&self) -> bool {
        self.manager.feedback(FeedbackType::MediumTap)
    }

    /// Toggle on
    pub fn toggle_on(&self) -> bool {
        self.manager.feedback(FeedbackType::Success)
    }

    /// Toggle off
    pub fn toggle_off(&self) -> bool {
        self.manager.feedback(FeedbackType::LightTap)
    }

    /// Selection changed
    pub fn selection_changed(&self) -> bool {
        self.manager.feedback(FeedbackType::SelectionChanged)
    }

    /// Confirm action
    pub fn confirm(&self) -> bool {
        self.manager.feedback(FeedbackType::Confirm)
    }

    /// Cancel action
    pub fn cancel(&self) -> bool {
        self.manager.feedback(FeedbackType::Cancel)
    }

    /// Invalid action
    pub fn invalid(&self) -> bool {
        self.manager.feedback(FeedbackType::Error)
    }
}

impl Default for UIFeedback {
    fn default() -> Self {
        Self::new()
    }
}

// 7. Gaming Feedback

/// Gaming haptic feedback
pub struct GameHaptics {
    manager: HapticManager,
}

impl GameHaptics {
    pub fn new() -> Self {
        GameHaptics {
            manager: HapticManager::new(),
        }
    }

    /// Button tap
    pub fn button_tap(&self) -> bool {
        self.manager.tap(30)
    }

    /// Action button
    pub fn action_button(&self) -> bool {
        self.manager.tap(50)
    }

    /// Impact (collision, etc.)
    pub fn impact(&self, strength: u32) -> bool {
        self.manager.tap(strength)
    }

    /// Power-up
    pub fn powerup(&self) -> bool {
        vibrate_rising()
    }

    /// Achievement unlocked
    pub fn achievement(&self) -> bool {
        self.manager.feedback(FeedbackType::Success)
    }

    /// Damage received
    pub fn damage(&self) -> bool {
        self.manager.feedback(FeedbackType::HeavyTap)
    }

    /// Death
    pub fn death(&self) -> bool {
        self.manager.feedback(FeedbackType::Error)
    }
}

impl Default for GameHaptics {
    fn default() -> Self {
        Self::new()
    }
}

// 8. Notification Feedback

/// Notification haptic patterns
pub struct NotificationHaptics {
    manager: HapticManager,
}

impl NotificationHaptics {
    pub fn new() -> Self {
        NotificationHaptics {
            manager: HapticManager::new(),
        }
    }

    /// Incoming message
    pub fn message(&self) -> bool {
        vibrate_double_tap()
    }

    /// Incoming call
    pub fn call(&self) -> bool {
        vibrate_pattern(&[200, 200, 200])
    }

    /// Calendar reminder
    pub fn reminder(&self) -> bool {
        self.manager.feedback(FeedbackType::Warning)
    }

    /// Download complete
    pub fn download_complete(&self) -> bool {
        self.manager.feedback(FeedbackType::Success)
    }

    /// Download failed
    pub fn download_failed(&self) -> bool {
        self.manager.feedback(FeedbackType::Error)
    }

    /// Battery low
    pub fn battery_low(&self) -> bool {
        vibrate_pattern(&[100, 200, 100, 200, 100, 200, 500])
    }
}

impl Default for NotificationHaptics {
    fn default() -> Self {
        Self::new()
    }
}

// 9. Accessibility Feedback

/// Accessibility haptic feedback
pub struct AccessibilityHaptics {
    manager: HapticManager,
}

impl AccessibilityHaptics {
    pub fn new() -> Self {
        AccessibilityHaptics {
            manager: HapticManager::new(),
        }
    }

    /// Focus gained
    pub fn focus_gained(&self) -> bool {
        self.manager.tap(20)
    }

    /// Boundary reached
    pub fn boundary(&self) -> bool {
        self.manager.tap(40)
    }

    /// Error occurred
    pub fn error(&self) -> bool {
        self.manager.feedback(FeedbackType::Error)
    }

    /// Success feedback
    pub fn success(&self) -> bool {
        self.manager.feedback(FeedbackType::Success)
    }

    /// Warning feedback
    pub fn warning(&self) -> bool {
        self.manager.feedback(FeedbackType::Warning)
    }
}

impl Default for AccessibilityHaptics {
    fn default() -> Self {
        Self::new()
    }
}

// 10. Vibration Utilities

/// Check if vibration is supported
pub fn is_vibration_supported() -> bool {
    // In WASM: 'vibrate' in navigator
    true // Simulated
}

/// Continuous vibration (until stopped)
pub fn vibrate_continuous() -> bool {
    // Long vibration that should be stopped manually
    vibrate_pattern(&[10000])
}

/// Morse code vibration
pub fn vibrate_morse_code(message: &str) -> bool {
    let mut pattern = Vec::new();
    let unit = 100; // Base time unit in ms

    for ch in message.to_uppercase().chars() {
        match ch {
            '.' => pattern.extend_from_slice(&[unit, unit]),
            '-' => pattern.extend_from_slice(&[3 * unit, unit]),
            ' ' => pattern.push(3 * unit), // Letter space
            '/' => pattern.push(7 * unit), // Word space
            _ => {},
        }
    }

    vibrate_pattern(&pattern)
}

// Usage Examples
fn main() {
    println!("=== Web Rust Haptic Feedback Examples ===\n");

    // 1. Basic vibration
    println!("--- 1. Basic Vibration ---");
    vibrate(200);
    println!("Short vibration: 200ms");
    std::thread::sleep(std::time::Duration::from_millis(300));

    // 2. Patterns
    println!("
--- 2. Vibration Patterns ---");
    vibrate_pattern(&[100, 50, 200, 50, 300]);
    println!("Pattern: 100ms, pause, 200ms, pause, 300ms");

    // 3. Common patterns
    println!("
--- 3. Common Patterns ---");
    println!("Success:");
    vibrate_success();
    std::thread::sleep(std::time::Duration::from_millis(500));

    println!("Error:");
    vibrate_error();
    std::thread::sleep(std::time::Duration::from_millis(500));

    println!("Warning:");
    vibrate_warning();

    // 4. Feedback types
    println!("
--- 4. Feedback Types ---");
    for feedback in [
        FeedbackType::LightTap,
        FeedbackType::MediumTap,
        FeedbackType::HeavyTap,
        FeedbackType::Success,
    ] {
        println!("{:?}:", feedback);
        feedback.execute();
        std::thread::sleep(std::time::Duration::from_millis(300));
    }

    // 5. Haptic manager
    println!("
--- 5. Haptic Manager ---");
    let mut manager = HapticManager::new();
    manager.set_intensity(0.5);
    println!("Intensity set to 50%");
    manager.feedback(FeedbackType::Confirm);

    // 6. Advanced patterns
    println!("
--- 6. Advanced Patterns ---");
    println!("Heartbeat:");
    vibrate_heartbeat(2);
    std::thread::sleep(std::time::Duration::from_millis(1000));

    println!("Rising:");
    vibrate_rising();
    std::thread::sleep(std::time::Duration::from_millis(1000));

    println!("SOS:");
    vibrate_sos();

    // 7. UI feedback
    println!("
--- 7. UI Feedback ---");
    let ui = UIFeedback::new();
    ui.button_press();
    std::thread::sleep(std::time::Duration::from_millis(200));
    ui.toggle_on();
    std::thread::sleep(std::time::Duration::from_millis(200));
    ui.confirm();

    // 8. Gaming feedback
    println!("
--- 8. Gaming Feedback ---");
    let game = GameHaptics::new();
    game.button_tap();
    std::thread::sleep(std::time::Duration::from_millis(200));
    game.impact(50);
    std::thread::sleep(std::time::Duration::from_millis(200));
    game.achievement();

    // 9. Notification feedback
    println!("
--- 9. Notification Feedback ---");
    let notif = NotificationHaptics::new();
    notif.message();
    std::thread::sleep(std::time::Duration::from_millis(500));
    notif.call();

    // 10. Morse code
    println!("
--- 10. Morse Code ---");
    println!("SOS in morse code:");
    vibrate_morse_code("... --- ...");

    println!("
=== IMPORTANT NOTE ===");
    println!("Vibration API is not available in all browsers and platforms.");
    println!("Desktop browsers typically don't support vibration.");
    println!("Mobile browsers (especially Android) have better support.");
    println!("iOS Safari has limited or no vibration support.");
    println!("");
    println!("In WASM, actual implementation requires JavaScript interop.");
    println!("Example: navigator.vibrate([200, 100, 200]);");

    println!("
=== All Haptic Feedback Examples Completed ===");
}

💻 Estado de Red rust

🟡 intermediate ⭐⭐⭐

Verificar el estado y tipo de conexión de red usando APIs del navegador

⏱️ 25 min 🏷️ rust, web, mobile features
Prerequisites: Intermediate Rust, Understanding of Web APIs
// Web Rust Network Status Examples
// Network status monitoring using browser Web APIs
//
// This demonstrates network status detection that would work in WebAssembly (WASM) context
//
// In WASM, you would use JavaScript interop with:
// - navigator.onLine
// - window.addEventListener('online')
// - window.addEventListener('offline')
// - navigator.connection (Network Information API)

use std::time::{SystemTime, UNIX_EPOCH};

// 1. Network Status Types

/// Connection state
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionState {
    Online,
    Offline,
    Unknown,
}

/// Connection type
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionType {
    Wifi,
    Cellular,
    Ethernet,
    Bluetooth,
    None,
    Other,
    Unknown,
}

/// Effective connection type (speed)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EffectiveConnectionType {
    Slow2G,
    TwoG,
    ThreeG,
    FourG,
    Unknown,
}

// 2. Network Status Information

/// Current network status
#[derive(Debug, Clone)]
pub struct NetworkStatus {
    pub state: ConnectionState,
    pub connection_type: ConnectionType,
    pub effective_type: EffectiveConnectionType,
    pub downlink: f64,        // Mbps
    pub rtt: u32,             // Round-trip time in ms
    pub save_data: bool,      // Data saver mode
    pub last_updated: u64,    // Timestamp
}

impl NetworkStatus {
    pub fn new() -> Self {
        NetworkStatus {
            state: ConnectionState::Online,
            connection_type: ConnectionType::Unknown,
            effective_type: EffectiveConnectionType::Unknown,
            downlink: 0.0,
            rtt: 0,
            save_data: false,
            last_updated: current_timestamp(),
        }
    }

    pub fn is_online(&self) -> bool {
        self.state == ConnectionState::Online
    }

    pub fn is_slow(&self) -> bool {
        matches!(
            self.effective_type,
            EffectiveConnectionType::Slow2G | EffectiveConnectionType::TwoG
        )
    }

    pub fn is_metered(&self) -> bool {
        matches!(
            self.connection_type,
            ConnectionType::Cellular
        )
    }
}

fn current_timestamp() -> u64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs()
}

// 3. Network Monitor

/// Network event types
#[derive(Debug, Clone)]
pub enum NetworkEvent {
    Online,
    Offline,
    ConnectionChange(ConnectionType),
    SpeedChange(EffectiveConnectionType),
}

/// Network event handler
pub type NetworkEventHandler = Box<dyn Fn(NetworkEvent) + Send>;

/// Network monitor (simplified for demonstration)
pub struct NetworkMonitor {
    status: NetworkStatus,
    handlers: Vec<NetworkEventHandler>,
}

impl NetworkMonitor {
    pub fn new() -> Self {
        NetworkMonitor {
            status: NetworkStatus::new(),
            handlers: Vec::new(),
        }
    }

    /// Register event handler
    pub fn on_event<F>(&mut self, handler: F)
    where
        F: Fn(NetworkEvent) + Send + 'static,
    {
        self.handlers.push(Box::new(handler));
    }

    /// Update network status
    pub fn update_status(&mut self, new_status: NetworkStatus) {
        let old_state = self.status.state;
        let old_type = self.status.connection_type;
        let old_speed = self.status.effective_type;

        self.status = new_status;

        // Trigger events
        if old_state != new_status.state {
            let event = match new_status.state {
                ConnectionState::Online => NetworkEvent::Online,
                ConnectionState::Offline => NetworkEvent::Offline,
                _ => return,
            };
            self.notify(event);
        }

        if old_type != new_status.connection_type {
            self.notify(NetworkEvent::ConnectionChange(new_status.connection_type));
        }

        if old_speed != new_status.effective_type {
            self.notify(NetworkEvent::SpeedChange(new_status.effective_type));
        }
    }

    /// Get current status
    pub fn status(&self) -> &NetworkStatus {
        &self.status
    }

    /// Check if online
    pub fn is_online(&self) -> bool {
        self.status.is_online()
    }

    /// Notify all handlers
    fn notify(&self, event: NetworkEvent) {
        for handler in &self.handlers {
            handler(event.clone());
        }
    }
}

impl Default for NetworkMonitor {
    fn default() -> Self {
        Self::new()
    }
}

// 4. Connection Quality

/// Connection quality assessment
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionQuality {
    Excellent,
    Good,
    Fair,
    Poor,
}

impl ConnectionQuality {
    pub fn from_status(status: &NetworkStatus) -> Self {
        match (status.effective_type, status.downlink, status.rtt) {
            (EffectiveConnectionType::FourG, dl, rtt) if dl >= 10.0 && rtt < 100 => {
                ConnectionQuality::Excellent
            },
            (EffectiveConnectionType::FourG, _, _) |
            (EffectiveConnectionType::ThreeG, dl, _) if dl >= 5.0 => {
                ConnectionQuality::Good
            },
            (EffectiveConnectionType::ThreeG, _, _) => ConnectionQuality::Fair,
            _ => ConnectionQuality::Poor,
        }
    }

    pub fn is_good_for_video(&self) -> bool {
        matches!(self, ConnectionQuality::Excellent | ConnectionQuality::Good)
    }

    pub fn is_good_for_audio(&self) -> bool {
        !matches!(self, ConnectionQuality::Poor)
    }
}

// 5. Adaptive Loading

/// Resource loading strategy based on network
#[derive(Debug, Clone)]
pub enum LoadingStrategy {
    HighQuality,     // Load full resources
    Balanced,        // Load optimized resources
    DataSaver,       // Load minimal resources
}

impl LoadingStrategy {
    pub fn from_status(status: &NetworkStatus) -> Self {
        if status.save_data || status.is_metered() {
            LoadingStrategy::DataSaver
        } else if status.is_slow() {
            LoadingStrategy::Balanced
        } else {
            LoadingStrategy::HighQuality
        }
    }
}

// 6. Request Optimization

/// Optimize requests based on network
#[derive(Debug, Clone)]
pub struct RequestConfig {
    pub timeout: u32,        // milliseconds
    pub retry_count: u32,
    pub use_compression: bool,
    pub batch_size: usize,
}

impl RequestConfig {
    pub fn from_status(status: &NetworkStatus) -> Self {
        let quality = ConnectionQuality::from_status(status);

        match quality {
            ConnectionQuality::Excellent => RequestConfig {
                timeout: 5000,
                retry_count: 3,
                use_compression: false,
                batch_size: 100,
            },
            ConnectionQuality::Good => RequestConfig {
                timeout: 10000,
                retry_count: 2,
                use_compression: true,
                batch_size: 50,
            },
            ConnectionQuality::Fair => RequestConfig {
                timeout: 15000,
                retry_count: 2,
                use_compression: true,
                batch_size: 25,
            },
            ConnectionQuality::Poor => RequestConfig {
                timeout: 30000,
                retry_count: 1,
                use_compression: true,
                batch_size: 10,
            },
        }
    }
}

// 7. Offline Detection

/// Check if currently offline
pub fn is_offline() -> bool {
    // In WASM: !navigator.onLine
    false // Simulated
}

/// Check if currently online
pub fn is_online() -> bool {
    // In WASM: navigator.onLine
    true // Simulated
}

// 8. Bandwidth Estimation

/// Estimate available bandwidth
pub fn estimate_bandwidth(downlink: f64, rtt: u32) -> f64 {
    // Rough estimation in Mbps
    if rtt == 0 {
        return downlink;
    }

    // Consider latency
    let latency_factor = 1000.0 / (rtt as f64);
    downlink * latency_factor.min(1.0)
}

/// Calculate optimal chunk size for file uploads
pub fn calculate_upload_chunk_size(status: &NetworkStatus) -> usize {
    match status.effective_type {
        EffectiveConnectionType::Slow2G => 32 * 1024,      // 32 KB
        EffectiveConnectionType::TwoG => 64 * 1024,        // 64 KB
        EffectiveConnectionType::ThreeG => 256 * 1024,     // 256 KB
        EffectiveConnectionType::FourG => 1024 * 1024,     // 1 MB
        EffectiveConnectionType::Unknown => 512 * 1024,    // 512 KB
    }
}

// 9. Retry Strategy

/// Retry strategy based on network
#[derive(Debug, Clone)]
pub struct RetryStrategy {
    pub max_attempts: u32,
    pub base_delay_ms: u32,
    pub max_delay_ms: u32,
    pub exponential_backoff: bool,
}

impl RetryStrategy {
    pub fn from_status(status: &NetworkStatus) -> Self {
        if status.is_slow() {
            RetryStrategy {
                max_attempts: 5,
                base_delay_ms: 1000,
                max_delay_ms: 10000,
                exponential_backoff: true,
            }
        } else {
            RetryStrategy {
                max_attempts: 3,
                base_delay_ms: 500,
                max_delay_ms: 5000,
                exponential_backoff: true,
            }
        }
    }

    pub fn calculate_delay(&self, attempt: u32) -> u32 {
        if self.exponential_backoff {
            let delay = self.base_delay_ms * 2_u32.pow(attempt.min(5));
            delay.min(self.max_delay_ms)
        } else {
            self.base_delay_ms
        }
    }
}

// 10. Network Utilities

/// Check if should use offline mode
pub fn should_use_offline_mode(status: &NetworkStatus) -> bool {
    !status.is_online() || status.is_slow() || status.save_data
}

/// Get recommended image quality based on network
pub fn get_image_quality(status: &NetworkStatus) -> u8 {
    match ConnectionQuality::from_status(status) {
        ConnectionQuality::Excellent => 100,
        ConnectionQuality::Good => 85,
        ConnectionQuality::Fair => 70,
        ConnectionQuality::Poor => 50,
    }
}

/// Calculate if should preload resources
pub fn should_preload(status: &NetworkStatus) -> bool {
    status.is_online() && !status.save_data && !status.is_metered()
}

// Usage Examples
fn main() {
    println!("=== Web Rust Network Status Examples ===\n");

    // 1. Basic status check
    println!("--- 1. Basic Status ---");
    println!("Is online: {}", is_online());
    println!("Is offline: {}", is_offline());

    // 2. Create network monitor
    println!("
--- 2. Network Monitor ---");
    let mut monitor = NetworkMonitor::new();

    // Add event handler
    monitor.on_event(|event| {
        println!("Network event: {:?}", event);
    });

    // Update status
    let new_status = NetworkStatus {
        state: ConnectionState::Online,
        connection_type: ConnectionType::Wifi,
        effective_type: EffectiveConnectionType::FourG,
        downlink: 50.0,
        rtt: 20,
        save_data: false,
        last_updated: current_timestamp(),
    };
    monitor.update_status(new_status);

    println!("Current status: {:?}", monitor.status());

    // 3. Connection quality
    println!("
--- 3. Connection Quality ---");
    let status = monitor.status();
    let quality = ConnectionQuality::from_status(status);
    println!("Quality: {:?}", quality);
    println!("Good for video: {}", quality.is_good_for_video());
    println!("Good for audio: {}", quality.is_good_for_audio());

    // 4. Loading strategy
    println!("
--- 4. Loading Strategy ---");
    let strategy = LoadingStrategy::from_status(status);
    println!("Strategy: {:?}", strategy);

    // 5. Request config
    println!("
--- 5. Request Configuration ---");
    let config = RequestConfig::from_status(status);
    println!("Timeout: {}ms", config.timeout);
    println!("Retry count: {}", config.retry_count);
    println!("Use compression: {}", config.use_compression);
    println!("Batch size: {}", config.batch_size);

    // 6. Bandwidth estimation
    println!("
--- 6. Bandwidth ---");
    let bandwidth = estimate_bandwidth(status.downlink, status.rtt);
    println!("Estimated bandwidth: {:.2} Mbps", bandwidth);

    // 7. Upload chunk size
    println!("
--- 7. Upload Optimization ---");
    let chunk_size = calculate_upload_chunk_size(status);
    println!("Chunk size: {} bytes", chunk_size);

    // 8. Retry strategy
    println!("
--- 8. Retry Strategy ---");
    let retry = RetryStrategy::from_status(status);
    println!("Max attempts: {}", retry.max_attempts);
    println!("Base delay: {}ms", retry.base_delay_ms);
    for i in 0..retry.max_attempts {
        println!("Attempt {} delay: {}ms", i + 1, retry.calculate_delay(i));
    }

    // 9. Image quality
    println!("
--- 9. Image Optimization ---");
    let quality = get_image_quality(status);
    println!("Recommended image quality: {}%", quality);

    // 10. Offline mode
    println!("
--- 10. Offline Detection ---");
    println!("Should use offline mode: {}", should_use_offline_mode(status));
    println!("Should preload: {}", should_preload(status));

    // 11. Different connection types
    println!("
--- 11. Connection Types ---");
    let types = [
        (ConnectionType::Wifi, EffectiveConnectionType::FourG, 100.0, 10),
        (ConnectionType::Cellular, EffectiveConnectionType::ThreeG, 5.0, 150),
        (ConnectionType::Cellular, EffectiveConnectionType::TwoG, 0.5, 500),
    ];

    for (conn_type, eff_type, dl, rtt) in types {
        let test_status = NetworkStatus {
            state: ConnectionState::Online,
            connection_type: conn_type,
            effective_type: eff_type,
            downlink: dl,
            rtt,
            save_data: false,
            last_updated: current_timestamp(),
        };

        println!("
{:?} - {:?}:", conn_type, eff_type);
        println!("  Quality: {:?}", ConnectionQuality::from_status(&test_status));
        println!("  Image quality: {}%", get_image_quality(&test_status));
        println!("  Chunk size: {} bytes", calculate_upload_chunk_size(&test_status));
    }

    println!("
=== Note ===");
    println!("Network Information API is experimental and not available in all browsers.");
    println!("Actual implementation requires JavaScript interop in WASM.");

    println!("
=== All Network Status Examples Completed ===");
}