waterui-media
Media components for WaterUI providing reactive photo, video, and Live Photo display with native platform rendering.
Overview
waterui-media delivers a comprehensive media handling system for the WaterUI framework. It bridges Rust's type safety with platform-native media rendering (AVFoundation on Apple platforms, ExoPlayer on Android) while maintaining WaterUI's reactive programming model. The crate supports static images, video playback with controls, Apple Live Photos, and platform-native media picking.
Key features include reactive volume control with mute state preservation, configurable aspect ratios, event-driven loading states, and seamless integration with WaterUI's environment system. Media components automatically render to native widgets: AVPlayerViewController on iOS, AVPlayerLayer for raw video views, and ExoPlayer with PlayerView on Android.
Installation
Add to your Cargo.toml:
[]
= "0.1.0"
Quick Start
use ;
use *;
Core Concepts
URL Handling
The crate uses waterui_url::Url for type-safe resource addressing. URLs support web resources, local file paths, data URLs, and blob URLs:
use Url;
// Compile-time web URLs
const REMOTE: Url = new;
// Runtime parsing
let local: Url = "/path/to/video.mp4".parse.unwrap;
let data_url = from_data;
Video Components: Raw vs Player
waterui-media provides two distinct video components:
Video: Raw video view using AVPlayerLayer/SurfaceView without controls - ideal for custom UIsVideoPlayer: Full-featured player with native platform controls (play/pause, seek, fullscreen)
Volume Control System
Video components use a special volume encoding that preserves the original level when muting:
- Positive values (
> 0): Audible volume level (0.0-1.0) - Negative values (
< 0): Muted state storing the original volume as the absolute value - When unmuting, the absolute value is restored
This approach eliminates the need for separate mute flags while maintaining volume memory.
Reactive State Integration
All media components integrate with WaterUI's reactive system via Binding and Computed signals. Changes to bindings automatically propagate to native platform components through the FFI layer.
Examples
Photo with Loading Events
use ;
let photo = new
.on_event;
Reactive Video Volume Control
use ;
use ;
use Toggle;
Raw Video View with Custom Controls
use ;
use binding;
let video = new
.aspect_ratio
.loops
.on_event;
Live Photo Display
use ;
let source = new;
let live_photo = new;
Media Picker
use ;
use ;
Unified Media Type
use ;
use *;
let image = Image;
let video = Video;
API Overview
Components
Photo- Display static images with event callbacks for load/error statesVideo- Raw video view without controls (AVPlayerLayer/SurfaceView)VideoPlayer- Full-featured video player with native controlsLivePhoto- Apple Live Photo display combining image and videoMediaPicker- Platform-native media selection UI
Types
Url- Type-safe URL representation (web, local, data, blob)Media- Unified enum for Image, Video, or LivePhotoLivePhotoSource- Pairing of image and video URLs for Live PhotosAspectRatio- Video scaling modes: Fit, Fill, StretchVolume- f32 type with special encoding for mute stateEvent- Photo and video event types (loaded, error, buffering, etc.)MediaFilter- Filters for media picker (Image, Video, LivePhoto, combinators)Selected- Selected media item with async loading capability
Image Processing (image module)
The Image type provides async image manipulation:
Image::new(mime, data)- Decode image from raw data on background threadresize(),resize_to_fit(),resize_to_fill(),resize_exact()- Resize operationsrotate(),rotate_90(),rotate_180(),rotate_270()- Rotationflip_horizontal(),flip_vertical()- Flippingcrop(),blur(),brighten(),adjust_contrast()- Filtersgrayscale(),invert(),huerotate()- Color adjustmentsencode_png(),encode_jpeg()- Export to bytesurl()- Generate base64 data URL
All processing operations run on background threads via blocking::unblock to prevent UI blocking.
Features
default- Enablesstdfeaturestd- Standard library support (enables file path handling)
Platform Implementation
iOS/macOS/tvOS
Photo: UsesAsyncImagewith URLSession for loadingVideo: UsesAVPlayerLayerdirectly for custom UIsVideoPlayer: UsesAVPlayerViewController(iOS/tvOS) orAVPlayerView(macOS)LivePhoto: UsesPHLivePhotoViewMediaPicker: UsesPHPickerViewControllerwithPHImageManagerfor loading
Android
Photo: Uses Coil image loading libraryVideo: Uses ExoPlayer with SurfaceViewVideoPlayer: Uses ExoPlayer with PlayerView (full controls)LivePhoto: Maps to Motion Photos via MediaStoreMediaPicker: UsesActivityResultContracts.PickVisualMediawith ContentResolver