diff --git a/lib/widgets/video_controls/video_controls.dart b/lib/widgets/video_controls/video_controls.dart index 3b2efb3a..7900b05e 100644 --- a/lib/widgets/video_controls/video_controls.dart +++ b/lib/widgets/video_controls/video_controls.dart @@ -981,10 +981,19 @@ class _PlexVideoControlsState extends State curve: Curves.easeInOut, top: _showControls ? (isMobile ? 100.0 : 60.0) : 16.0, left: 16, - child: AnimatedOpacity( - opacity: (!_autoHidePerformanceOverlay || _showControls) ? 1.0 : 0.0, - duration: const Duration(milliseconds: 200), - child: IgnorePointer(child: PlayerPerformanceOverlay(player: widget.player)), + right: 16, + // Clear the bottom controls (same clearance as the skip button) so the + // overlay can shrink to fit instead of being clipped by the screen edge. + bottom: !_showControls ? 16.0 : (isMobile ? 80.0 : 115.0), + // Align loosens the tight constraints from the fully-anchored Positioned; + // without it the card would stretch to fill the whole region. + child: Align( + alignment: Alignment.topLeft, + child: AnimatedOpacity( + opacity: (!_autoHidePerformanceOverlay || _showControls) ? 1.0 : 0.0, + duration: const Duration(milliseconds: 200), + child: IgnorePointer(child: PlayerPerformanceOverlay(player: widget.player)), + ), ), ), if (_isScreenLocked) diff --git a/lib/widgets/video_controls/widgets/performance_overlay/performance_overlay.dart b/lib/widgets/video_controls/widgets/performance_overlay/performance_overlay.dart index 06be9806..30558c66 100644 --- a/lib/widgets/video_controls/widgets/performance_overlay/performance_overlay.dart +++ b/lib/widgets/video_controls/widgets/performance_overlay/performance_overlay.dart @@ -1,3 +1,5 @@ +import 'dart:math' as math; + import 'package:flutter/material.dart'; import 'package:material_symbols_icons/symbols.dart'; @@ -111,15 +113,34 @@ class _PlayerPerformanceOverlayState extends State { ]), ]; - return Container( - constraints: const BoxConstraints(maxWidth: 400), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.black.withValues(alpha: 0.8), - borderRadius: const BorderRadius.all(Radius.circular(8)), - boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 4)], - ), - child: Wrap(spacing: 24, runSpacing: 12, children: sections), + return LayoutBuilder( + builder: (context, constraints) { + // On height-limited screens (landscape phones) widen the card so the Wrap + // packs sections side by side instead of stacking into an off-screen column. + final compactHeight = constraints.hasBoundedHeight && constraints.maxHeight < 500; + final cardMaxWidth = compactHeight && constraints.hasBoundedWidth ? math.min(constraints.maxWidth, 560.0) : 400.0; + + // Text scaling only inflates the intrinsic size that FittedBox scales right + // back down, trading layout sharpness for nothing on this diagnostics card. + return MediaQuery.withNoTextScaling( + // scaleDown is a no-op when the content fits; it only shrinks the card when + // it would otherwise be clipped by the bounds set at the embed site. + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.topLeft, + child: Container( + constraints: BoxConstraints(maxWidth: cardMaxWidth), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.8), + borderRadius: const BorderRadius.all(Radius.circular(8)), + boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 4)], + ), + child: Wrap(spacing: 24, runSpacing: 12, children: sections), + ), + ), + ); + }, ); }