fix(player): fit the performance overlay on short screens
Anchor the overlay to the screen and seekbar clearance, widen the card on height-limited screens so sections pack side by side, and scale down as a last resort instead of clipping the bottom sections. close #1469
This commit is contained in:
@@ -981,10 +981,19 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
|
||||
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)
|
||||
|
||||
@@ -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<PlayerPerformanceOverlay> {
|
||||
]),
|
||||
];
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user