dreamio/docs/native-player-ux-audit.md

6.5 KiB
Raw Blame History

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.

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.