Document native player UX baseline audit

This commit is contained in:
dirtydishes 2026-05-26 21:50:38 -04:00
parent 59ecafd948
commit dbe9f1ca26
3 changed files with 151 additions and 0 deletions

View file

@ -0,0 +1,124 @@
# 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 Apples 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 5458 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.