import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../library/database.dart'; import '../library/category_service.dart'; import '../library/playlist_service.dart'; import '../library/song_media.dart'; import '../player/audio_handler.dart'; import '../playlists/create_playlist_dialog.dart'; import '../settings/app_settings.dart'; import 'auswahl.dart'; import 'theme.dart'; /// Kopfzeile im Auswahl-Modus: Anzahl und die beiden Stapel-Aktionen. /// /// Gemeinsam für alle Songlisten, die Mehrfachauswahl anbieten — sie ersetzt /// die sonst dort stehende Zeile, statt darunter zu erscheinen. class AuswahlLeiste extends StatelessWidget { const AuswahlLeiste({ super.key, required this.anzahl, required this.onAbbrechen, required this.onWiedergabeliste, required this.onWarteschlange, }); final int anzahl; final VoidCallback onAbbrechen; final VoidCallback onWiedergabeliste; final VoidCallback onWarteschlange; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB( MeloSpace.sm, MeloSpace.xs, MeloSpace.sm, MeloSpace.xs), child: Row( children: [ IconButton( tooltip: 'Auswahl beenden', icon: const Icon(Icons.close), onPressed: onAbbrechen, ), Expanded( child: Text( auswahlText(anzahl), maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.w600), ), ), IconButton( tooltip: 'Zur Warteschlange hinzufügen', icon: const Icon(Icons.queue), onPressed: onWarteschlange, ), IconButton( tooltip: 'Zu Wiedergabeliste hinzufügen', icon: const Icon(Icons.playlist_add), onPressed: onWiedergabeliste, ), ], ), ); } } /// Legt [gewaehlte] in eine (neue oder bestehende) Wiedergabeliste, mit /// Rückmeldung über Neues/schon-Vorhandenes/Fehler. Future fuegeZuWiedergabelisteHinzu( BuildContext context, List gewaehlte) async { final db = context.read(); final dienst = context.read(); final messenger = ScaffoldMessenger.of(context); final ziel = await showModalBottomSheet( context: context, builder: (sheetContext) => SafeArea( child: StreamBuilder>( stream: db.watchPlaylists(), builder: (context, snapshot) { final listen = snapshot.data ?? const []; return Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( leading: const Icon(Icons.add), title: const Text('Neue Wiedergabeliste'), onTap: () async { final neu = await showDialog( context: sheetContext, builder: (_) => const CreatePlaylistDialog(), ); if (neu != null && sheetContext.mounted) { Navigator.pop(sheetContext, neu); } }, ), for (final liste in listen) ListTile( leading: const Icon(Icons.playlist_play), title: Text(liste.name), onTap: () => Navigator.pop(sheetContext, liste.id), ), ], ); }, ), ), ); if (ziel == null) return; final vorhanden = await db.watchPlaylistSongs(ziel).first; // Wer schon drin ist, bleibt, wo er ist. Ein erneutes Einfügen würde ihn // wegen des Primärschlüssels nur verschieben und Lücken hinterlassen. final bekannt = {for (final s in vorhanden) s.id}; var position = vorhanden.length; var neu = 0; String? fehler; for (final song in gewaehlte) { if (bekannt.contains(song.id)) continue; try { await dienst.addSongToPlaylist(ziel, song.id, position++); neu++; } catch (e) { fehler = '$e'; break; } } if (!context.mounted) return; messenger.showSnackBar(SnackBar( content: Text(playlistMeldung( neu: neu, schonDa: gewaehlte.length - neu, fehler: fehler, )), )); } /// Hängt [gewaehlte] ans Ende der Warteschlange, mit Rückmeldung, falls /// nicht alle Titel angehängt werden konnten (z. B. offline). Future fuegeZuWarteschlangeHinzu( BuildContext context, List gewaehlte) async { final handler = context.read(); final categories = context.read(); final settings = context.read(); final messenger = ScaffoldMessenger.of(context); var angehaengt = 0; for (final song in gewaehlte) { final ok = await handler.addToQueue(songToMediaItem( song, cover: categories.coverFor(song, groupByCategory: settings.groupCoversByCategory), )); if (ok) angehaengt++; } if (!context.mounted) return; messenger.showSnackBar(SnackBar( content: Text(angehaengt == gewaehlte.length ? '$angehaengt Titel in der Warteschlange' : '$angehaengt von ${gewaehlte.length} Titeln angehängt'), )); }