import 'package:flutter/material.dart'; import 'package:flutter_lucide/flutter_lucide.dart'; import '../../theme/theme_extension.dart'; /// Always-visible 44dp circular play button overlaid on home-screen /// card art (AlbumCard / ArtistCard / PlaylistCard). Mirrors the /// hover-revealed `.play-overlay` on the web cards, but always shown /// because hover is not a real interaction on touch. /// /// Manages its own loading state via [_starting] so the caller's tap /// handler can be `Future Function()` without worrying about /// re-entrancy. Disabled state suppresses the tap (used for empty /// playlists). class PlayCircleButton extends StatefulWidget { const PlayCircleButton({ required this.onPressed, this.enabled = true, this.size = 44, super.key, }); /// Tap handler. Returns a Future so the button can show a spinner /// during the play setup (fetch detail tracks, etc.). final Future Function() onPressed; /// When false, the button is rendered semi-transparent and taps are /// ignored. Empty playlists / artists with no tracks should disable. final bool enabled; /// Outer diameter in logical pixels. 44 is the iOS / Android /// touch-target minimum; matches the design doc. final double size; @override State createState() => _PlayCircleButtonState(); } class _PlayCircleButtonState extends State { bool _starting = false; Future _handleTap() async { if (_starting || !widget.enabled) return; setState(() => _starting = true); try { await widget.onPressed(); } finally { if (mounted) setState(() => _starting = false); } } @override Widget build(BuildContext context) { final fs = Theme.of(context).extension()!; final iconSize = widget.size * 0.5; return Material( color: Colors.transparent, shape: const CircleBorder(), child: InkResponse( onTap: widget.enabled ? _handleTap : null, radius: widget.size / 2, containedInkWell: true, customBorder: const CircleBorder(), child: Container( width: widget.size, height: widget.size, decoration: BoxDecoration( color: fs.accent.withValues(alpha: widget.enabled ? 1.0 : 0.5), shape: BoxShape.circle, boxShadow: const [ BoxShadow( color: Color(0x66000000), blurRadius: 6, offset: Offset(0, 2), ), ], ), alignment: Alignment.center, child: _starting ? SizedBox( width: iconSize, height: iconSize, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(fs.parchment), ), ) : Icon( LucideIcons.play, color: fs.parchment, size: iconSize, ), ), ), ); } }