import 'package:flutter/material.dart'; import '../services/player_service.dart'; import '../models/song.dart'; import '../utils/farb_theme.dart'; /// Bottom-Sheet mit der aktuellen Warteschlange: /// aktueller Song markiert, Tipp = abspielen, Drag-and-Drop = umsortieren. class WarteschlangeSheet extends StatefulWidget { const WarteschlangeSheet({super.key}); @override State createState() => _WarteschlangeSheetState(); } class _WarteschlangeSheetState extends State { final PlayerService _player = PlayerService(); @override Widget build(BuildContext context) { return ListenableBuilder( listenable: _player, builder: (context, _) { final queue = _player.warteschlange; final aktueller = _player.aktuellerIndex; return SafeArea( child: Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), child: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.75, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Griff Container( width: 36, height: 4, margin: const EdgeInsets.only(top: 10, bottom: 4), decoration: BoxDecoration( color: MeloTheme.dunkel2, borderRadius: BorderRadius.circular(2), ), ), // Kopfzeile Padding( padding: const EdgeInsets.fromLTRB(20, 8, 8, 4), child: Row( children: [ const Icon(Icons.queue_music, size: 18, color: MeloTheme.rot), const SizedBox(width: 8), Text( 'Warteschlange', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, ), ), const SizedBox(width: 8), Text( '${queue.length} Titel', style: const TextStyle( fontSize: 12, color: MeloTheme.textSekundaer, ), ), const Spacer(), IconButton( icon: const Icon(Icons.close, size: 18, color: MeloTheme.textSekundaer), onPressed: () => Navigator.pop(context), tooltip: 'Schließen', ), ], ), ), const Divider(height: 1, color: MeloTheme.dunkel2), // Liste if (queue.isEmpty) const Expanded( child: Center( child: Text( 'Keine Songs in der Warteschlange', style: TextStyle(fontSize: 13, color: MeloTheme.textSekundaer), ), ), ) else Flexible( child: ReorderableListView.builder( shrinkWrap: true, padding: const EdgeInsets.fromLTRB(8, 4, 8, 16), itemCount: queue.length, // onReorderItem liefert den newIndex bereits angepasst onReorderItem: (alt, neu) => _player.verschiebeInWarteschlange(alt, neu), itemBuilder: (_, i) => _eintrag(queue[i], i, aktueller), ), ), ], ), ), ), ); }, ); } Widget _eintrag(Song song, int index, int aktueller) { final istAktuell = index == aktueller; return ListTile( key: ValueKey('$index-${song.id ?? song.titel}'), dense: true, leading: istAktuell ? const Icon(Icons.play_arrow, color: MeloTheme.rot, size: 18) : SizedBox( width: 18, child: Text( '${index + 1}', textAlign: TextAlign.center, style: const TextStyle(fontSize: 11, color: MeloTheme.textSekundaer), ), ), title: Text( song.titel, style: TextStyle( fontSize: 13, fontWeight: istAktuell ? FontWeight.w700 : FontWeight.w400, color: istAktuell ? MeloTheme.rot : Colors.white, ), ), subtitle: Text( song.kuenstler, style: const TextStyle(fontSize: 11, color: MeloTheme.textSekundaer), ), trailing: Text( song.dauerFormatiert, style: const TextStyle(fontSize: 11, color: MeloTheme.textSekundaer), ), onTap: () => _player.spiele(song), ); } }