mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 13:37:24 +00:00
124 lines
6.5 KiB
Markdown
124 lines
6.5 KiB
Markdown
# Native Player UX Baseline Audit
|
||
|
||
Date: 2026-05-26 21:49 EDT
|
||
Issue: `dreamio-ee1`
|
||
|
||
## Scope
|
||
|
||
This audit covers the current VLC-backed native playback experience before Liquid Glass and broader UX changes. The primary implementation is `Dreamio/NativePlayerViewController.swift`, backed by `Dreamio/NativePlaybackBackend.swift` and `Dreamio/VLCNativePlaybackBackend.swift`.
|
||
|
||
## Current Experience Summary
|
||
|
||
Dreamio presents native playback as a full-screen black video surface with a compact bottom control tray, a top-right close button, a loading spinner, and a simple centered failure label. Controls are built directly in UIKit and are intentionally lightweight.
|
||
|
||
Current user-facing controls:
|
||
|
||
- Top-right close button.
|
||
- Bottom compact blur-backed tray capped at 430 points wide.
|
||
- Elapsed time, scrubber, and remaining time row.
|
||
- Audio menu button.
|
||
- 15-second jump back.
|
||
- Play/pause.
|
||
- 15-second jump forward.
|
||
- Captions menu button with subtitle delay controls.
|
||
- Tap anywhere on the playback surface to reveal or hide controls.
|
||
- Auto-hide while playing after 3 seconds.
|
||
|
||
## Existing Strengths
|
||
|
||
- **Minimal interruption:** The player is full-screen and hides chrome while playback is active.
|
||
- **Compact controls:** Recent work reduced the overlay footprint so video content stays dominant.
|
||
- **Core playback affordances exist:** Play/pause, seeking, jump controls, elapsed/remaining time, audio tracks, captions, and subtitle delay are present.
|
||
- **Backend-aware disabling:** Seek and jump controls disable when VLC reports a non-seekable stream.
|
||
- **Track menus are cached:** Audio and captions menus avoid unnecessary rebuilds through signature values.
|
||
- **Subtitle handoff exists:** The native player can receive subtitle candidates from the Stremio Web bridge and attach them through the backend.
|
||
- **Safe-area aware:** Close and controls are anchored to safe-area guides.
|
||
|
||
## Current UX Gaps
|
||
|
||
### Visual Treatment
|
||
|
||
- The control surface uses `UIBlurEffect(style: .systemUltraThinMaterialDark)` plus manual tint/border styling, not iOS 26 Liquid Glass.
|
||
- Buttons are individual translucent wells rather than an intentional grouped glass system.
|
||
- There is no bottom readability scrim; bright video frames could reduce time label and icon contrast.
|
||
- Loading and failure states are plain compared with the rest of the player chrome.
|
||
|
||
### Touch Targets and Hierarchy
|
||
|
||
- Secondary controls are 36×36 points, below Apple’s recommended 44×44 point minimum target.
|
||
- The play/pause button is only 42×42 points, so the primary action is not dominant enough.
|
||
- Audio and captions have the same visual weight as transport controls even when unavailable or secondary.
|
||
- Disabled captions do not currently mirror the explicit alpha treatment used by audio.
|
||
|
||
### Scrubbing
|
||
|
||
- The scrubber has a compact thumb and row, but no preview/target time bubble.
|
||
- During scrubbing, the elapsed label updates, but the user does not get a larger focused scrubbing affordance.
|
||
- There is no haptic feedback on scrub begin/end or jump actions.
|
||
|
||
### Gestures
|
||
|
||
- Single tap toggles controls, but no richer playback gestures exist.
|
||
- There is no double-tap left/right jump behavior.
|
||
- There is no center tap play/pause behavior separate from chrome visibility.
|
||
- Gesture conflict handling will need care because `tap.cancelsTouchesInView = false` currently allows control touches to pass through.
|
||
|
||
### Auto-Hide
|
||
|
||
- Controls hide after 3 seconds while playing, which can feel short for subtitle/audio menu interactions or careful scrubbing.
|
||
- The auto-hide timer only checks `backend.isPlaying`; future changes should explicitly protect menu presentation, scrubbing, loading, paused, and failure states.
|
||
|
||
### Loading and Failure
|
||
|
||
- Startup loading is only a white `UIActivityIndicatorView` over black.
|
||
- Failure is a plain text label with no retry, close action, or debug affordance.
|
||
- The 20-second startup timeout is useful, but the user receives little guidance after it fires.
|
||
|
||
### Accessibility
|
||
|
||
- Buttons have accessibility labels, but no accessibility hints.
|
||
- The scrubber has no dynamic accessibility value describing elapsed and remaining time.
|
||
- Jump actions are not exposed as custom accessibility actions on the player surface.
|
||
- Motion preferences are not checked before animations.
|
||
- Dynamic Type behavior for the compact controls has not been explicitly protected.
|
||
|
||
### Device Adaptation
|
||
|
||
- The bottom tray is capped at 430 points, which is good for phones but underuses iPad/large landscape space.
|
||
- Button sizing and row spacing are fixed; orientation-specific density has not been tuned.
|
||
- The supported orientations allow all but upside down, so landscape crowding should be part of validation.
|
||
|
||
## Implementation Constraints
|
||
|
||
- `NativePlaybackBackend` currently exposes no thumbnail/preview frames, so scrub previews should begin as a time bubble rather than video thumbnails.
|
||
- The backend exposes seekability, duration, position, audio tracks, subtitle tracks, and subtitle delay, which is enough for richer controls without backend changes.
|
||
- The app must preserve compatibility with builds where MobileVLCKit is unavailable through the existing fallback backend behavior.
|
||
- Liquid Glass APIs should be gated with iOS availability checks and keep the current blur/material implementation as fallback.
|
||
- Multiple glass controls should be grouped with container effects where possible to avoid expensive standalone glass rendering.
|
||
|
||
## Recommended Next Implementation Slice
|
||
|
||
Start with a low-risk visual and ergonomics pass:
|
||
|
||
1. Add iOS 26 Liquid Glass availability-gated styling for the main controls tray and interactive buttons, preserving the current blur fallback.
|
||
2. Increase button targets to at least 44×44 points and make play/pause 54–58 points.
|
||
3. Add a subtle bottom gradient scrim behind controls for contrast.
|
||
4. Extend auto-hide timing from 3 seconds to about 4.5 seconds and prevent hiding while scrubbing.
|
||
5. Add missing accessibility hints and scrubber accessibility value.
|
||
|
||
Defer until the second implementation slice:
|
||
|
||
- Scrubber target time bubble.
|
||
- Double-tap jump gestures.
|
||
- Center tap play/pause behavior.
|
||
- Glass-backed loading and failure cards with retry.
|
||
- iPad-specific wider layout.
|
||
|
||
## Validation Targets for Future Changes
|
||
|
||
- Build the workspace with Xcode command-line tools.
|
||
- Test seekable and non-seekable streams.
|
||
- Test streams with one audio track, multiple audio tracks, no captions, embedded captions, and external captions.
|
||
- Verify controls remain usable in portrait and landscape.
|
||
- Verify VoiceOver labels, hints, and scrubber values.
|
||
- Verify older iOS fallback styling still works when Liquid Glass is unavailable.
|