Fix: PlayerExpansionController oberhalb des Navigators bereitstellen
Bug (Code-Review, P0 — blockierte den Push): PlayerExpansionController wurde bisher nur INNERHALB von HomeShell.build() bereitgestellt. Per Navigator.push geöffnete Screens (PlaylistDetailScreen, ServerTitelScreen) sind im Widget-Baum aber Geschwister von HomeShell im selben Navigator/Overlay, keine Nachfahren — sie sahen den Provider nicht. context.read<PlayerExpansionController>().open(context) warf dort zur Laufzeit ProviderNotFoundException, vom bestehenden try/catch abgefangen zu einer "Wiedergabe fehlgeschlagen"-Snackbar — der Player öffnete sich nie. MeloApp ist jetzt ein StatefulWidget (TickerProviderStateMixin), erzeugt PlayerExpansionController in initState() und stellt ihn in seiner MultiProvider-Liste bereit — oberhalb von MaterialApp/Navigator, wie alle anderen App-weiten Provider. HomeShell erzeugt keinen eigenen mehr, sondern liest die Referenz per context.read<PlayerExpansionController>() einmalig (keine Subscription) und reicht sie an seine AnimatedBuilder weiter, die weiterhin direkt am Controller lauschen — die bewusste "Consumer nur um PopScope"-Optimierung (Scaffold wird nicht bei jedem progress-Tick neu gebaut) bleibt dabei erhalten. Test zuerst (RED mit der heutigen, echten ProviderNotFoundException reproduziert — via echtem HomeShell + echtem Navigator.push, nicht dem bisherigen Kurzschluss-Testaufbau, der den Provider manuell direkt neben das Test-Widget klebt): test/player/provider_scope_navigator_push_test.dart. Bestehende Tests, die HomeShell direkt aufbauen (hauptmenue_test.dart, home_shell_test.dart, home_shell_real_expansion_test.dart), an die neue Verdrahtung angepasst — der Controller kommt jetzt aus ihrer eigenen MultiProvider-Liste statt aus HomeShell selbst. Volle Suite (625 Tests) grün. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SM6e73V9ZethPiqHSocxUA
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
6687f2f67c
commit
0fe624d1e8
@@ -7,6 +7,7 @@ import 'package:melo/library/library_service.dart';
|
||||
import 'package:melo/library/playlist_service.dart';
|
||||
import 'package:melo/main.dart';
|
||||
import 'package:melo/player/audio_handler.dart';
|
||||
import 'package:melo/player/player_expansion_controller.dart';
|
||||
import 'package:melo/services/baka_auth.dart';
|
||||
import 'package:melo/services/download_service.dart';
|
||||
import 'package:melo/services/melo_cloud_service.dart';
|
||||
@@ -39,6 +40,7 @@ void main() {
|
||||
final playlists = PlaylistService(db);
|
||||
final handler = MeloAudioHandler(db: db);
|
||||
final auth = BakaAuth(speicher: _MemorySpeicher());
|
||||
final expansion = PlayerExpansionController(vsync: tester);
|
||||
|
||||
await tester.pumpWidget(MultiProvider(
|
||||
providers: [
|
||||
@@ -59,6 +61,8 @@ void main() {
|
||||
ChangeNotifierProvider<SyncService>(
|
||||
create: (_) => SyncService(
|
||||
db: db, cloud: MeloCloudService(auth: auth))),
|
||||
ChangeNotifierProvider<PlayerExpansionController>.value(
|
||||
value: expansion),
|
||||
],
|
||||
child: const MaterialApp(home: HomeShell()),
|
||||
));
|
||||
@@ -70,6 +74,7 @@ void main() {
|
||||
['Meine Musik', 'Suchen', 'Download', 'Favoriten', 'YT-Suche']);
|
||||
|
||||
handler.dispose();
|
||||
expansion.dispose();
|
||||
await db.close();
|
||||
});
|
||||
|
||||
@@ -80,6 +85,7 @@ void main() {
|
||||
final playlists = PlaylistService(db);
|
||||
final handler = MeloAudioHandler(db: db);
|
||||
final auth = BakaAuth(speicher: _MemorySpeicher());
|
||||
final expansion = PlayerExpansionController(vsync: tester);
|
||||
|
||||
await tester.pumpWidget(MultiProvider(
|
||||
providers: [
|
||||
@@ -100,6 +106,8 @@ void main() {
|
||||
ChangeNotifierProvider<SyncService>(
|
||||
create: (_) => SyncService(
|
||||
db: db, cloud: MeloCloudService(auth: auth))),
|
||||
ChangeNotifierProvider<PlayerExpansionController>.value(
|
||||
value: expansion),
|
||||
],
|
||||
child: const MaterialApp(home: HomeShell()),
|
||||
));
|
||||
@@ -137,6 +145,7 @@ void main() {
|
||||
// einem tester.tap.
|
||||
await tester.pumpWidget(const SizedBox());
|
||||
handler.dispose();
|
||||
expansion.dispose();
|
||||
await tester.pump(const Duration(milliseconds: 1));
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user