feat: Improve media play button

This commit is contained in:
PartyDonut 2025-10-09 14:11:55 +02:00
parent 9a6202bd0b
commit 5722defe34
3 changed files with 82 additions and 58 deletions

View file

@ -74,6 +74,7 @@ class OverviewHeader extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: crossAlignment,
mainAxisSize: MainAxisSize.min,
spacing: 16,
children: [
Flexible(
child: ExcludeFocus(
@ -194,7 +195,7 @@ class OverviewHeader extends ConsumerWidget {
],
),
),
].addInBetween(const SizedBox(height: 21)),
],
),
),
);

View file

@ -5,7 +5,6 @@ import 'package:iconsax_plus/iconsax_plus.dart';
import 'package:fladder/models/item_base_model.dart';
import 'package:fladder/screens/shared/animated_fade_size.dart';
import 'package:fladder/theme.dart';
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
import 'package:fladder/util/focus_provider.dart';
import 'package:fladder/widgets/shared/ensure_visible.dart';
@ -25,8 +24,8 @@ class MediaPlayButton extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final progress = (item?.progress ?? 0) / 100.0;
final padding = 3.0;
final radius = FladderTheme.smallShape.borderRadius.subtract(BorderRadius.circular(padding));
final radius = BorderRadius.circular(16);
final smallRadius = const Radius.circular(4);
final theme = Theme.of(context);
Widget buttonTitle(Color contentColor) {
@ -39,8 +38,8 @@ class MediaPlayButton extends ConsumerWidget {
Flexible(
child: Text(
item?.playButtonLabel(context) ?? "",
maxLines: 2,
overflow: TextOverflow.clip,
maxLines: 1,
overflow: TextOverflow.fade,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w700,
color: contentColor,
@ -63,55 +62,19 @@ class MediaPlayButton extends ConsumerWidget {
? const SizedBox.shrink(key: ValueKey('empty'))
: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
spacing: 4,
children: [
FocusButton(
onTap: () => onPressed?.call(false),
onLongPress: () => onLongPressed?.call(false),
autoFocus: AdaptiveLayout.inputDeviceOf(context) == InputDevice.dPad,
darkOverlay: false,
onFocusChanged: (value) {
if (value) {
context.ensureVisible(
alignment: 1.0,
);
}
},
child: Stack(
alignment: Alignment.center,
children: [
// Progress background
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
color: theme.colorScheme.primaryContainer,
borderRadius: radius,
),
),
),
// Button content
buttonTitle(theme.colorScheme.onPrimaryContainer),
Positioned.fill(
child: ClipRect(
clipper: _ProgressClipper(
progress,
),
child: DecoratedBox(
decoration: BoxDecoration(
color: theme.colorScheme.primary,
borderRadius: radius,
),
child: buttonTitle(theme.colorScheme.onPrimary),
),
),
),
],
),
),
if (progress != 0)
FocusButton(
onTap: () => onPressed?.call(true),
onLongPress: () => onLongPressed?.call(true),
Flexible(
child: FocusButton(
onTap: () => onPressed?.call(false),
onLongPress: () => onLongPressed?.call(false),
autoFocus: AdaptiveLayout.inputDeviceOf(context) == InputDevice.dPad,
borderRadius: radius.copyWith(
topRight: progress != 0 ? smallRadius : radius.topRight,
bottomRight: progress != 0 ? smallRadius : radius.bottomRight,
),
darkOverlay: false,
onFocusChanged: (value) {
if (value) {
context.ensureVisible(
@ -119,11 +82,69 @@ class MediaPlayButton extends ConsumerWidget {
);
}
},
child: Card(
color: theme.colorScheme.primaryContainer,
shadowColor: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
// Progress background
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
color: theme.colorScheme.primaryContainer,
borderRadius: radius.copyWith(
topRight: progress != 0 ? smallRadius : radius.topRight,
bottomRight: progress != 0 ? smallRadius : radius.bottomRight,
),
),
),
),
// Button content
buttonTitle(theme.colorScheme.onPrimaryContainer),
Positioned.fill(
child: ClipRect(
clipper: _ProgressClipper(
progress,
),
child: DecoratedBox(
decoration: BoxDecoration(
color: theme.colorScheme.primary,
borderRadius: radius.copyWith(
topRight: progress != 0 ? smallRadius : radius.topRight,
bottomRight: progress != 0 ? smallRadius : radius.bottomRight,
),
),
child: buttonTitle(theme.colorScheme.onPrimary),
),
),
),
],
),
),
),
if (progress != 0)
FocusButton(
onTap: () => onPressed?.call(true),
onLongPress: () => onLongPressed?.call(true),
borderRadius: radius.copyWith(
topLeft: progress != 0 ? smallRadius : radius.topLeft,
bottomLeft: progress != 0 ? smallRadius : radius.bottomLeft,
),
onFocusChanged: (value) {
if (value) {
context.ensureVisible(
alignment: 1.0,
);
}
},
child: Container(
decoration: BoxDecoration(
color: theme.colorScheme.primaryContainer,
borderRadius: radius.copyWith(
topLeft: progress != 0 ? smallRadius : radius.topLeft,
bottomLeft: progress != 0 ? smallRadius : radius.bottomLeft,
),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(7.5),
child: Icon(
IconsaxPlusBold.refresh,
size: 29,

View file

@ -52,6 +52,7 @@ class FocusButton extends StatefulWidget {
final Function(TapDownDetails)? onSecondaryTapDown;
final bool darkOverlay;
final Function(bool focus)? onFocusChanged;
final BorderRadiusGeometry? borderRadius;
const FocusButton({
this.child,
@ -63,6 +64,7 @@ class FocusButton extends StatefulWidget {
this.onSecondaryTapDown,
this.darkOverlay = true,
this.onFocusChanged,
this.borderRadius,
super.key,
});
@ -176,7 +178,7 @@ class FocusButtonState extends State<FocusButton> {
.primaryContainer
.withValues(alpha: widget.darkOverlay ? 0.1 : 0),
border: Border.all(width: 3, color: Theme.of(context).colorScheme.onPrimaryContainer),
borderRadius: FladderTheme.smallShape.borderRadius,
borderRadius: widget.borderRadius ?? FladderTheme.smallShape.borderRadius,
),
),
),