Focus chrome was implemented twice, once in the focusable wrapper and once in the focus builders; both now go through FocusChrome. TvColorPicker's channel row was a copy of TvNumberSpinner and is now that widget in compact density. Also trims unused helpers and fields and simplifies the Jellyfin browse paths.
60 lines
2.0 KiB
Dart
60 lines
2.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'card_focus_scope.dart';
|
|
import 'focus_glow_overlay.dart';
|
|
import 'focus_theme.dart';
|
|
|
|
/// Builds the focus border/glow chrome shared by [FocusableWrapper] and
|
|
/// [FocusBuilders.buildLockedFocusWrapper].
|
|
///
|
|
/// A function rather than a widget so it costs no element per card in dense TV
|
|
/// grids. Scale and input handling stay with the callers: the wrapper drives a
|
|
/// paint-only scale from its own controller and owns the [Focus] node, while
|
|
/// the locked builder scales implicitly and wraps gestures itself.
|
|
///
|
|
/// Callers pass the [duration] they already resolved via
|
|
/// [FocusTheme.getAnimationDuration] so a build resolves it once.
|
|
Widget buildFocusChrome(
|
|
BuildContext context, {
|
|
required bool showFocus,
|
|
required Duration duration,
|
|
double borderRadius = FocusTheme.defaultBorderRadius,
|
|
BorderRadius? borderRadii,
|
|
Color? focusColor,
|
|
bool useBackgroundFocus = false,
|
|
bool useFocusGlow = false,
|
|
bool delegateFocusBorder = false,
|
|
Size? glowSize,
|
|
required Widget child,
|
|
}) {
|
|
Widget card;
|
|
if (delegateFocusBorder) {
|
|
card = CardFocusScope(showFocus: showFocus, child: child);
|
|
} else {
|
|
final decoration = useBackgroundFocus
|
|
? FocusTheme.focusBackgroundDecoration(isFocused: showFocus, borderRadius: borderRadius, radii: borderRadii)
|
|
: FocusTheme.focusDecoration(
|
|
context,
|
|
isFocused: showFocus,
|
|
borderRadius: borderRadius,
|
|
radii: borderRadii,
|
|
color: focusColor,
|
|
);
|
|
card = AnimatedContainer(duration: duration, curve: Curves.easeOutCubic, decoration: decoration, child: child);
|
|
}
|
|
|
|
// Glow (full-bleed cards) renders in an overlay above siblings so it stays
|
|
// symmetric; the in-card decoration only carries the border.
|
|
if (useFocusGlow) {
|
|
card = FocusGlowOverlay(
|
|
isFocused: showFocus,
|
|
borderRadius: borderRadius,
|
|
color: focusColor ?? FocusTheme.getFocusBorderColor(context),
|
|
glowSize: glowSize,
|
|
child: card,
|
|
);
|
|
}
|
|
|
|
return card;
|
|
}
|