Web Rust 移动端功能示例
Web Rust 移动端功能示例,包括设备信息、网络状态和触觉反馈
💻 设备信息 rust
🟢 simple
⭐⭐⭐
使用浏览器Web API获取设备信息
⏱️ 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 ===");
}
💻 触觉反馈 rust
🟢 simple
⭐⭐⭐
使用浏览器Vibration API进行振动和触觉反馈
⏱️ 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 ===");
}
💻 网络状态 rust
🟡 intermediate
⭐⭐⭐
使用浏览器API检查网络连接状态和类型
⏱️ 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 ===");
}