import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:media_kit/media_kit.dart'; import 'services/audio_service.dart'; import 'services/playback_service.dart'; import 'services/app_lifecycle_service.dart'; import 'services/webdav_service.dart'; import 'pages/home_page.dart'; import 'pages/player_page.dart'; import 'pages/playlist_page.dart'; import 'widgets/global_mini_player.dart'; final GlobalKey navigatorKey = GlobalKey(); void main() { WidgetsFlutterBinding.ensureInitialized(); runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => AudioService()), ChangeNotifierProvider(create: (_) => AppLifecycleService()), ], child: const QTPlayerApp(), ), ); // ⭐ 首帧渲染完成后才执行初始化 WidgetsBinding.instance.addPostFrameCallback((_) { _initializeServices(); }); } void _initializeServices() async { final lifecycle = AppLifecycleService(); try { // 1. MediaKit lifecycle.updateStatus(AppStatus.mediaKitInitializing); MediaKit.ensureInitialized(); lifecycle.updateStatus(AppStatus.mediaKitReady); // 2. PlaybackService lifecycle.updateStatus(AppStatus.playerInitializing); PlaybackService().init(); lifecycle.updateStatus(AppStatus.playerReady); // 3. WebDAV lifecycle.updateStatus(AppStatus.webdavChecking); final hasCred = await WebDAVService.instance.loadCredentials(); if (hasCred) { lifecycle.updateStatus(AppStatus.webdavReady); } else { lifecycle.updateStatus(AppStatus.webdavMissing); } lifecycle.updateStatus(AppStatus.fullReady); } catch (e) { debugPrint('❌ 初始化错误: $e'); lifecycle.updateStatus(AppStatus.error); } } // ═══════════════════════════════════════════════════ // RouteManager // ═══════════════════════════════════════════════════ class RouteManager extends ChangeNotifier { static final RouteManager _instance = RouteManager._internal(); factory RouteManager() => _instance; RouteManager._internal(); String _currentRoute = '/'; String get currentRoute => _currentRoute; bool get showMiniPlayer => _currentRoute != '/player' && _currentRoute != '/playlist'; void updateRoute(String route) { if (_currentRoute != route) { _currentRoute = route; debugPrint('📌 路由更新: $route'); notifyListeners(); } } } // ═══════════════════════════════════════════════════ // 导航观察者 // ═══════════════════════════════════════════════════ class MiniPlayerNavigatorObserver extends NavigatorObserver { void _updateRoute(Route? route) { final name = route?.settings.name ?? '/'; RouteManager().updateRoute(name); } @override void didPush(Route route, Route? previousRoute) { _updateRoute(route); } @override void didPop(Route route, Route? previousRoute) { _updateRoute(previousRoute); } @override void didReplace({Route? newRoute, Route? oldRoute}) { _updateRoute(newRoute); } } // ═══════════════════════════════════════════════════ // QTPlayerApp - 无状态,只负责组装 // ═══════════════════════════════════════════════════ class QTPlayerApp extends StatelessWidget { const QTPlayerApp({super.key}); @override Widget build(BuildContext context) { debugPrint('🔥 QTPlayerApp.build() 执行,首帧即将渲染'); return MaterialApp( title: '清听', theme: ThemeData( brightness: Brightness.dark, primaryColor: const Color(0xFF7C9A9E), colorScheme: const ColorScheme.dark( primary: Color(0xFF7C9A9E), secondary: Color(0xFFB8D4D0), surface: Color(0xFF1A1F1E), onSurface: Colors.white, ), useMaterial3: true, ), navigatorKey: navigatorKey, navigatorObservers: [MiniPlayerNavigatorObserver()], routes: { '/': (context) => const HomePage(), '/player': (context) => const PlayerPage(), '/playlist': (context) => const PlaylistPage(), }, builder: (context, child) { return Stack( fit: StackFit.expand, children: [ if (child != null) child, AnimatedBuilder( animation: RouteManager(), builder: (context, _) { if (!RouteManager().showMiniPlayer) { return const SizedBox.shrink(); } return const Align( alignment: Alignment.bottomCenter, child: GlobalMiniPlayer(), ); }, ), ], ); }, ); } }