| 
									
										
										
										
											2019-12-03 12:23:41 +01:00
										 |  |  | import 'dart:async'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  | import 'package:flutter/services.dart'; | 
					
						
							|  |  |  | import 'package:musicus_common/musicus_common.dart'; | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import 'screens/home.dart'; | 
					
						
							|  |  |  | import 'widgets/player_bar.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  | class App extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |   static const _platform = MethodChannel('de.johrpan.musicus/platform'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  |   @override | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |     final backend = MusicusBackend.of(context); | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return MaterialApp( | 
					
						
							|  |  |  |       title: 'Musicus', | 
					
						
							|  |  |  |       theme: ThemeData( | 
					
						
							|  |  |  |         brightness: Brightness.dark, | 
					
						
							|  |  |  |         accentColor: Colors.amber, | 
					
						
							|  |  |  |         textSelectionColor: Colors.grey[600], | 
					
						
							|  |  |  |         cursorColor: Colors.amber, | 
					
						
							|  |  |  |         textSelectionHandleColor: Colors.amber, | 
					
						
							|  |  |  |         toggleableActiveColor: Colors.amber, | 
					
						
							|  |  |  |         // Added for sliders and FABs. Not everything seems to obey this.
 | 
					
						
							|  |  |  |         colorScheme: ColorScheme.dark( | 
					
						
							|  |  |  |           primary: Colors.amber, | 
					
						
							|  |  |  |           secondary: Colors.amber, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2020-04-26 18:29:21 +02:00
										 |  |  |         snackBarTheme: SnackBarThemeData( | 
					
						
							|  |  |  |           backgroundColor: Colors.grey[800], | 
					
						
							|  |  |  |           contentTextStyle: TextStyle( | 
					
						
							|  |  |  |             color: Colors.white, | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |           behavior: SnackBarBehavior.floating, | 
					
						
							|  |  |  |         ), | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |         fontFamily: 'Libertinus Sans', | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |       home: Builder( | 
					
						
							|  |  |  |         builder: (context) { | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |           if (backend.status == MusicusBackendStatus.loading) { | 
					
						
							| 
									
										
										
										
											2020-03-28 09:54:04 +01:00
										 |  |  |             return Material( | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |               color: Theme.of(context).scaffoldBackgroundColor, | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |           } else if (backend.status == MusicusBackendStatus.setup) { | 
					
						
							| 
									
										
										
										
											2020-03-28 10:18:52 +01:00
										 |  |  |             return Material( | 
					
						
							|  |  |  |               color: Theme.of(context).scaffoldBackgroundColor, | 
					
						
							|  |  |  |               child: Column( | 
					
						
							|  |  |  |                 mainAxisAlignment: MainAxisAlignment.center, | 
					
						
							|  |  |  |                 children: <Widget>[ | 
					
						
							|  |  |  |                   Text( | 
					
						
							|  |  |  |                     'Choose the base path for\nyour music library.', | 
					
						
							|  |  |  |                     textAlign: TextAlign.center, | 
					
						
							|  |  |  |                     style: Theme.of(context).textTheme.headline6, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                   SizedBox( | 
					
						
							|  |  |  |                     height: 16.0, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                   ListTile( | 
					
						
							|  |  |  |                     leading: const Icon(Icons.folder_open), | 
					
						
							|  |  |  |                     title: Text('Choose path'), | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |                     onTap: () async { | 
					
						
							|  |  |  |                       final uri = | 
					
						
							|  |  |  |                           await _platform.invokeMethod<String>('openTree'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                       if (uri != null) { | 
					
						
							|  |  |  |                         backend.settings.setMusicLibraryPath(uri); | 
					
						
							|  |  |  |                       } | 
					
						
							| 
									
										
										
										
											2020-03-28 10:18:52 +01:00
										 |  |  |                     }, | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |           } else { | 
					
						
							|  |  |  |             return Content(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  | class Content extends StatefulWidget { | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   _ContentState createState() => _ContentState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _ContentState extends State<Content> with SingleTickerProviderStateMixin { | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  |   final nestedNavigator = GlobalKey<NavigatorState>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   AnimationController playerBarAnimation; | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |   MusicusBackendState backend; | 
					
						
							| 
									
										
										
										
											2019-12-03 12:23:41 +01:00
										 |  |  |   StreamSubscription<bool> playerActiveSubscription; | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     playerBarAnimation = AnimationController( | 
					
						
							|  |  |  |       vsync: this, | 
					
						
							|  |  |  |       duration: Duration(milliseconds: 300), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void didChangeDependencies() { | 
					
						
							|  |  |  |     super.didChangeDependencies(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |     backend = MusicusBackend.of(context); | 
					
						
							|  |  |  |     playerBarAnimation.value = backend.playback.active.value ? 1.0 : 0.0; | 
					
						
							| 
									
										
										
										
											2019-12-03 12:23:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (playerActiveSubscription != null) { | 
					
						
							|  |  |  |       playerActiveSubscription.cancel(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-04 21:49:44 +02:00
										 |  |  |     playerActiveSubscription = backend.playback.active.listen((active) => | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  |         active ? playerBarAnimation.forward() : playerBarAnimation.reverse()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |     // The nested Navigator is for every screen from which the player bar at
 | 
					
						
							|  |  |  |     // the bottom should be accessible. The WillPopScope widget intercepts
 | 
					
						
							|  |  |  |     // taps on the system back button and redirects them to the nested
 | 
					
						
							|  |  |  |     // navigator.
 | 
					
						
							|  |  |  |     return WillPopScope( | 
					
						
							|  |  |  |       onWillPop: () async => !(await nestedNavigator.currentState.maybePop()), | 
					
						
							|  |  |  |       child: Scaffold( | 
					
						
							|  |  |  |         body: Navigator( | 
					
						
							|  |  |  |           key: nestedNavigator, | 
					
						
							|  |  |  |           onGenerateRoute: (settings) => settings.name == '/' | 
					
						
							|  |  |  |               ? MaterialPageRoute( | 
					
						
							|  |  |  |                   builder: (context) => HomeScreen(), | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |               : null, | 
					
						
							|  |  |  |           initialRoute: '/', | 
					
						
							| 
									
										
										
										
											2019-12-02 21:58:13 +01:00
										 |  |  |         ), | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |         bottomNavigationBar: SizeTransition( | 
					
						
							|  |  |  |           sizeFactor: CurvedAnimation( | 
					
						
							|  |  |  |             curve: Curves.easeOut, | 
					
						
							|  |  |  |             parent: playerBarAnimation, | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  |           ), | 
					
						
							| 
									
										
										
										
											2020-03-28 09:16:42 +01:00
										 |  |  |           axisAlignment: -1.0, | 
					
						
							|  |  |  |           child: PlayerBar(), | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  |         ), | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-12-03 12:23:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void dispose() { | 
					
						
							|  |  |  |     super.dispose(); | 
					
						
							|  |  |  |     playerActiveSubscription.cancel(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-12-02 21:05:49 +01:00
										 |  |  | } |