Load the database asynchronously

Now the backend has multiple states including loading and the toplevel
app widget was adapted accordingly.
This commit is contained in:
Elias Projahn 2020-03-28 09:16:42 +01:00
parent 3f0567e688
commit 87582f200d
2 changed files with 82 additions and 43 deletions

View file

@ -6,12 +6,48 @@ import 'backend.dart';
import 'screens/home.dart'; import 'screens/home.dart';
import 'widgets/player_bar.dart'; import 'widgets/player_bar.dart';
class App extends StatefulWidget { class App extends StatelessWidget {
@override @override
_AppState createState() => _AppState(); Widget build(BuildContext context) {
final backend = Backend.of(context);
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,
),
fontFamily: 'Libertinus Sans',
),
home: Builder(
builder: (context) {
if (backend.status == BackendStatus.loading) {
return Container(
color: Theme.of(context).scaffoldBackgroundColor,
);
} else {
return Content();
}
},
),
);
}
} }
class _AppState extends State<App> with SingleTickerProviderStateMixin { class Content extends StatefulWidget {
@override
_ContentState createState() => _ContentState();
}
class _ContentState extends State<Content> with SingleTickerProviderStateMixin {
final nestedNavigator = GlobalKey<NavigatorState>(); final nestedNavigator = GlobalKey<NavigatorState>();
AnimationController playerBarAnimation; AnimationController playerBarAnimation;
@ -45,46 +81,29 @@ class _AppState extends State<App> with SingleTickerProviderStateMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( // The nested Navigator is for every screen from which the player bar at
title: 'Musicus', // the bottom should be accessible. The WillPopScope widget intercepts
theme: ThemeData( // taps on the system back button and redirects them to the nested
brightness: Brightness.dark, // navigator.
accentColor: Colors.amber, return WillPopScope(
textSelectionColor: Colors.grey[600], onWillPop: () async => !(await nestedNavigator.currentState.maybePop()),
cursorColor: Colors.amber, child: Scaffold(
textSelectionHandleColor: Colors.amber, body: Navigator(
toggleableActiveColor: Colors.amber, key: nestedNavigator,
// Added for sliders and FABs. Not everything seems to obey this. onGenerateRoute: (settings) => settings.name == '/'
colorScheme: ColorScheme.dark( ? MaterialPageRoute(
primary: Colors.amber, builder: (context) => HomeScreen(),
secondary: Colors.amber, )
: null,
initialRoute: '/',
), ),
fontFamily: 'Libertinus Sans', bottomNavigationBar: SizeTransition(
), sizeFactor: CurvedAnimation(
// The nested Navigator is for every screen from which the player bar at curve: Curves.easeOut,
// the bottom should be accessible. The WillPopScope widget intercepts parent: playerBarAnimation,
// taps on the system back button and redirects them to the nested
// navigator.
home: WillPopScope(
onWillPop: () async => !(await nestedNavigator.currentState.maybePop()),
child: Scaffold(
body: Navigator(
key: nestedNavigator,
onGenerateRoute: (settings) => settings.name == '/'
? MaterialPageRoute(
builder: (context) => HomeScreen(),
)
: null,
initialRoute: '/',
),
bottomNavigationBar: SizeTransition(
sizeFactor: CurvedAnimation(
curve: Curves.easeOut,
parent: playerBarAnimation,
),
axisAlignment: -1.0,
child: PlayerBar(),
), ),
axisAlignment: -1.0,
child: PlayerBar(),
), ),
), ),
); );

View file

@ -3,6 +3,11 @@ import 'package:rxdart/rxdart.dart';
import 'database.dart'; import 'database.dart';
enum BackendStatus {
loading,
ready,
}
class Backend extends StatefulWidget { class Backend extends StatefulWidget {
final Widget child; final Widget child;
@ -18,12 +23,19 @@ class Backend extends StatefulWidget {
} }
class BackendState extends State<Backend> { class BackendState extends State<Backend> {
final db = Database('musicus.sqlite');
final playerActive = BehaviorSubject.seeded(false); final playerActive = BehaviorSubject.seeded(false);
final playing = BehaviorSubject.seeded(false); final playing = BehaviorSubject.seeded(false);
final position = BehaviorSubject.seeded(0.0); final position = BehaviorSubject.seeded(0.0);
Database db;
BackendStatus status = BackendStatus.loading;
@override
void initState() {
super.initState();
_load();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _InheritedBackend( return _InheritedBackend(
@ -32,6 +44,14 @@ class BackendState extends State<Backend> {
); );
} }
Future<void> _load() async {
db = Database('musicus.sqlite');
setState(() {
status = BackendStatus.ready;
});
}
void startPlayer() { void startPlayer() {
playerActive.add(true); playerActive.add(true);
} }