Playback Control Fix: - Changed from player_command to player_queues API - Use player_queues/play, pause, next, previous - Changed player_id to queue_id parameter - Fixes "Invalid command: player_command/*" errors - Playback controls (play/pause/next/previous) now work correctly Button Animations: - Created AnimatedIconButton widget with scale-down animation - Added press animations to all playback control buttons - Mini player: previous, play/pause, next buttons - Now playing screen: previous, play/pause, next buttons - Buttons scale to 85% when pressed for tactile feedback - Custom _AnimatedPlayButton for the circular play/pause button - Maintains white circular background - Smooth scale animation on press Buttons now feel responsive and provide visual feedback on tap. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
74 lines
1.7 KiB
Dart
74 lines
1.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// An IconButton that scales down when pressed for tactile feedback
|
|
class AnimatedIconButton extends StatefulWidget {
|
|
final IconData icon;
|
|
final VoidCallback? onPressed;
|
|
final Color? color;
|
|
final double? iconSize;
|
|
|
|
const AnimatedIconButton({
|
|
super.key,
|
|
required this.icon,
|
|
this.onPressed,
|
|
this.color,
|
|
this.iconSize,
|
|
});
|
|
|
|
@override
|
|
State<AnimatedIconButton> createState() => _AnimatedIconButtonState();
|
|
}
|
|
|
|
class _AnimatedIconButtonState extends State<AnimatedIconButton>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
late Animation<double> _scaleAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
duration: const Duration(milliseconds: 100),
|
|
vsync: this,
|
|
);
|
|
_scaleAnimation = Tween<double>(begin: 1.0, end: 0.85).animate(
|
|
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
Future<void> _handleTap() async {
|
|
if (widget.onPressed == null) return;
|
|
|
|
// Animate press
|
|
await _controller.forward();
|
|
await _controller.reverse();
|
|
|
|
// Call the callback
|
|
widget.onPressed!();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GestureDetector(
|
|
onTapDown: (_) => _controller.forward(),
|
|
onTapUp: (_) => _controller.reverse(),
|
|
onTapCancel: () => _controller.reverse(),
|
|
child: ScaleTransition(
|
|
scale: _scaleAnimation,
|
|
child: IconButton(
|
|
icon: Icon(widget.icon),
|
|
color: widget.color,
|
|
iconSize: widget.iconSize,
|
|
onPressed: _handleTap,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|