presentation stuff
This commit is contained in:
parent
0c66eb006c
commit
72b26274d6
9 changed files with 236 additions and 145 deletions
|
@ -1,8 +1,15 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_audio_query/flutter_audio_query.dart';
|
||||
import 'package:mosh/system/datasources/local_music_fetcher.dart';
|
||||
import 'package:mosh/system/datasources/moor_music_data_source.dart';
|
||||
import 'package:mosh/system/repositories/music_data_repository_impl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'presentation/pages/home.dart';
|
||||
import 'presentation/pages/library.dart';
|
||||
import 'presentation/pages/settings.dart';
|
||||
import 'presentation/pages/home_page.dart';
|
||||
import 'presentation/pages/library_page.dart';
|
||||
import 'presentation/pages/settings_page.dart';
|
||||
import 'presentation/state/music_store.dart';
|
||||
import 'presentation/theming.dart';
|
||||
import 'presentation/widgets/navbar.dart';
|
||||
|
||||
void main() => runApp(MyApp());
|
||||
|
@ -12,28 +19,23 @@ class MyApp extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
// Define the default brightness and colors.
|
||||
brightness: Brightness.dark,
|
||||
primaryColor: Colors.amber,
|
||||
accentColor: Colors.amberAccent,
|
||||
// https://api.flutter.dev/flutter/material/TextTheme-class.html
|
||||
textTheme: TextTheme(
|
||||
headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
|
||||
title: const TextStyle(fontSize: 20.0), //, fontWeight: FontWeight.w300),
|
||||
body1: const TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
|
||||
title: 'mosh',
|
||||
theme: theme(),
|
||||
home: Provider<MusicStore>(
|
||||
child: RootPage(),
|
||||
create: (BuildContext context) => MusicStore(
|
||||
MusicDataRepositoryImpl(
|
||||
localMusicFetcher: LocalMusicFetcherImpl(FlutterAudioQuery()),
|
||||
musicDataSource: MoorMusicDataSource(),
|
||||
),
|
||||
),
|
||||
),
|
||||
home: RootPage(title: 'Flutter Demo Home Page'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RootPage extends StatefulWidget {
|
||||
RootPage({Key key, this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
RootPage({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_RootPageState createState() => _RootPageState();
|
||||
|
@ -42,7 +44,21 @@ class RootPage extends StatefulWidget {
|
|||
class _RootPageState extends State<RootPage> {
|
||||
var navIndex = 0;
|
||||
|
||||
final _pages = <Widget>[HomePage(), LibraryPage(), SettingsPage()];
|
||||
List<Widget> _pages;
|
||||
MusicStore _musicStore;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
_musicStore = Provider.of<MusicStore>(context);
|
||||
_musicStore.fetchAlbums();
|
||||
|
||||
_pages = <Widget>[
|
||||
HomePage(),
|
||||
LibraryPage(store: _musicStore),
|
||||
SettingsPage(store: _musicStore),
|
||||
];
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mosh/presentation/theming.dart';
|
||||
|
||||
import '../widgets/album_art.dart';
|
||||
import '../widgets/queue_card.dart';
|
||||
|
@ -17,95 +18,98 @@ class _CurrentlyPlayingPageState extends State<CurrentlyPlayingPage> {
|
|||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => Stack(children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 12.0,
|
||||
right: 12.0,
|
||||
top: 8.0,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.expand_more),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.more_vert),
|
||||
onPressed: () {},
|
||||
)
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
),
|
||||
Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: AlbumArt(),
|
||||
),
|
||||
Spacer(
|
||||
flex: 3,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.link,
|
||||
size: 20.0,
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
),
|
||||
Icon(
|
||||
Icons.favorite,
|
||||
size: 20.0,
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
),
|
||||
Icon(
|
||||
Icons.remove_circle_outline,
|
||||
size: 20.0,
|
||||
),
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
),
|
||||
Container(
|
||||
height: 24,
|
||||
),
|
||||
TimeProgressIndicator(),
|
||||
Container(
|
||||
height: 20,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Row(
|
||||
builder: (BuildContext context, BoxConstraints constraints) => Stack(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 12.0,
|
||||
right: 12.0,
|
||||
top: 8.0,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.repeat, size: 20.0),
|
||||
Icon(Icons.skip_previous, size: 40.0),
|
||||
Icon(
|
||||
Icons.play_circle_filled,
|
||||
size: 64.0,
|
||||
IconButton(
|
||||
icon: Icon(Icons.expand_more),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
Icon(Icons.skip_next, size: 40.0),
|
||||
Icon(Icons.shuffle, size: 20.0),
|
||||
IconButton(
|
||||
icon: Icon(Icons.more_vert),
|
||||
onPressed: () {},
|
||||
)
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 72,
|
||||
),
|
||||
],
|
||||
Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: AlbumArt(),
|
||||
),
|
||||
Spacer(
|
||||
flex: 3,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.link,
|
||||
size: 20.0,
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
),
|
||||
Icon(
|
||||
Icons.favorite,
|
||||
size: 20.0,
|
||||
color: RASPBERRY,
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
),
|
||||
Icon(
|
||||
Icons.remove_circle_outline,
|
||||
size: 20.0,
|
||||
),
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
),
|
||||
Container(
|
||||
height: 24,
|
||||
),
|
||||
TimeProgressIndicator(),
|
||||
Container(
|
||||
height: 20,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.repeat, size: 20.0),
|
||||
Icon(Icons.skip_previous, size: 40.0),
|
||||
Icon(
|
||||
Icons.play_circle_filled,
|
||||
size: 64.0,
|
||||
),
|
||||
Icon(Icons.skip_next, size: 40.0),
|
||||
Icon(Icons.shuffle, size: 20.0),
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 72,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
QueueCard(
|
||||
boxConstraints: constraints,
|
||||
),
|
||||
]),
|
||||
QueueCard(
|
||||
boxConstraints: constraints,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class LibraryPage extends StatefulWidget {
|
||||
LibraryPage({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LibraryPageState createState() => _LibraryPageState();
|
||||
}
|
||||
|
||||
class _LibraryPageState extends State<LibraryPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Center(child: Text("Library Page"),),
|
||||
);
|
||||
}
|
||||
}
|
69
lib/presentation/pages/library_page.dart
Normal file
69
lib/presentation/pages/library_page.dart
Normal file
|
@ -0,0 +1,69 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:mosh/domain/entities/album.dart';
|
||||
|
||||
import '../state/music_store.dart';
|
||||
|
||||
class LibraryPage extends StatelessWidget {
|
||||
const LibraryPage({Key key, @required this.store}) : super(key: key);
|
||||
|
||||
final MusicStore store;
|
||||
|
||||
Image getAlbumImage(Album album) {
|
||||
if (album.albumArtPath == null || !File(album.albumArtPath).existsSync()) {
|
||||
return Image.asset('assets/no_cover.jpg');
|
||||
}
|
||||
return Image.file(File(album.albumArtPath));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Observer(builder: (_) {
|
||||
final ObservableFuture<List<Album>> future = store.albumsFuture;
|
||||
|
||||
switch (future.status) {
|
||||
case FutureStatus.pending:
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
CircularProgressIndicator(),
|
||||
Text('Loading items...'),
|
||||
],
|
||||
);
|
||||
|
||||
case FutureStatus.rejected:
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
'Failed to load items.',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
case FutureStatus.fulfilled:
|
||||
final List<Album> albums = future.result as List<Album>;
|
||||
return ListView.builder(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemCount: albums.length,
|
||||
itemBuilder: (_, index) {
|
||||
final album = albums[index];
|
||||
return ListTile(
|
||||
leading: Card(
|
||||
child: getAlbumImage(album),
|
||||
),
|
||||
title: Text(
|
||||
'${album.title}, ${album.artist}, ${album.year}',
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return Center(
|
||||
child: Text('Library Page'),
|
||||
);
|
||||
});
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class SettingsPage extends StatefulWidget {
|
||||
SettingsPage({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SettingsPageState createState() => _SettingsPageState();
|
||||
}
|
||||
|
||||
class _SettingsPageState extends State<SettingsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Update database"),
|
||||
onTap: () {
|
||||
print("Hello World");
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
23
lib/presentation/pages/settings_page.dart
Normal file
23
lib/presentation/pages/settings_page.dart
Normal file
|
@ -0,0 +1,23 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../state/music_store.dart';
|
||||
|
||||
class SettingsPage extends StatelessWidget {
|
||||
const SettingsPage({Key key, @required this.store}) : super(key: key);
|
||||
|
||||
final MusicStore store;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
title: const Text('Update database'),
|
||||
onTap: () {
|
||||
store.updateDatabase();
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
20
lib/presentation/theming.dart
Normal file
20
lib/presentation/theming.dart
Normal file
|
@ -0,0 +1,20 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
const Color RASPBERRY = Color(0xFFea0367);
|
||||
const Color TURQUOISE = Color(0xFF30d8f3);
|
||||
const Color CRAYOLA = Color(0xfffde189);
|
||||
const Color PINEAPPLE = Color(0xff56365e);
|
||||
const Color MIDNIGHT = Color(0xff622371);
|
||||
const Color MIDDLE_RED_PURPLE = Color(0xff0f0127);
|
||||
|
||||
ThemeData theme() => ThemeData(
|
||||
brightness: Brightness.dark,
|
||||
primaryColor: Colors.amber,
|
||||
accentColor: Colors.amberAccent,
|
||||
// https://api.flutter.dev/flutter/material/TextTheme-class.html
|
||||
textTheme: TextTheme(
|
||||
headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
|
||||
title: const TextStyle(fontSize: 20.0),
|
||||
body1: const TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
|
||||
),
|
||||
);
|
|
@ -10,8 +10,8 @@ class QueueCard extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _QueueCardState extends State<QueueCard> {
|
||||
final title = "Fire";
|
||||
final artist = "Beartooth";
|
||||
final title = 'Fire';
|
||||
final artist = 'Beartooth';
|
||||
final height = 64.0;
|
||||
|
||||
bool _first = true;
|
||||
|
|
Loading…
Add table
Reference in a new issue