Exemples de Fonctionnalités Mobiles Web Rust

Exemples de fonctionnalités mobiles Web Rust incluant les informations d'appareil, le statut réseau et le retour haptique

Key Facts

Category
Rust
Items
3
Format Families
sample

Sample Overview

Exemples de fonctionnalités mobiles Web Rust incluant les informations d'appareil, le statut réseau et le retour haptique This sample set belongs to Rust and can be used to test related workflows inside Elysia Tools.

💻 Informations sur l'Appareil rust

🟢 simple ⭐⭐⭐

Obtenir les informations sur l'appareil en utilisant les API du navigateur

⏱️ 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 ===");
}

💻 Retour Haptique rust

🟢 simple ⭐⭐⭐

Vibration et retour haptique en utilisant l'API de Vibration du navigateur

⏱️ 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 ===");
}

💻 Statut Réseau rust

🟡 intermediate ⭐⭐⭐

Vérifier le statut et le type de connexion réseau en utilisant les API du navigateur

⏱️ 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 != self.status.state {
            let event = match self.status.state {
                ConnectionState::Online => NetworkEvent::Online,
                ConnectionState::Offline => NetworkEvent::Offline,
                _ => return,
            };
            self.notify(event);
        }

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

        if old_speed != self.status.effective_type {
            self.notify(NetworkEvent::SpeedChange(self.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, _, _) => ConnectionQuality::Good,
            (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 ===");
}