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/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/home_page.dart';
|
||||||
import 'presentation/pages/library.dart';
|
import 'presentation/pages/library_page.dart';
|
||||||
import 'presentation/pages/settings.dart';
|
import 'presentation/pages/settings_page.dart';
|
||||||
|
import 'presentation/state/music_store.dart';
|
||||||
|
import 'presentation/theming.dart';
|
||||||
import 'presentation/widgets/navbar.dart';
|
import 'presentation/widgets/navbar.dart';
|
||||||
|
|
||||||
void main() => runApp(MyApp());
|
void main() => runApp(MyApp());
|
||||||
|
@ -12,28 +19,23 @@ class MyApp extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Flutter Demo',
|
title: 'mosh',
|
||||||
theme: ThemeData(
|
theme: theme(),
|
||||||
// Define the default brightness and colors.
|
home: Provider<MusicStore>(
|
||||||
brightness: Brightness.dark,
|
child: RootPage(),
|
||||||
primaryColor: Colors.amber,
|
create: (BuildContext context) => MusicStore(
|
||||||
accentColor: Colors.amberAccent,
|
MusicDataRepositoryImpl(
|
||||||
// https://api.flutter.dev/flutter/material/TextTheme-class.html
|
localMusicFetcher: LocalMusicFetcherImpl(FlutterAudioQuery()),
|
||||||
textTheme: TextTheme(
|
musicDataSource: MoorMusicDataSource(),
|
||||||
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'),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
home: RootPage(title: 'Flutter Demo Home Page'),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RootPage extends StatefulWidget {
|
class RootPage extends StatefulWidget {
|
||||||
RootPage({Key key, this.title}) : super(key: key);
|
RootPage({Key key}) : super(key: key);
|
||||||
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_RootPageState createState() => _RootPageState();
|
_RootPageState createState() => _RootPageState();
|
||||||
|
@ -42,7 +44,21 @@ class RootPage extends StatefulWidget {
|
||||||
class _RootPageState extends State<RootPage> {
|
class _RootPageState extends State<RootPage> {
|
||||||
var navIndex = 0;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mosh/presentation/theming.dart';
|
||||||
|
|
||||||
import '../widgets/album_art.dart';
|
import '../widgets/album_art.dart';
|
||||||
import '../widgets/queue_card.dart';
|
import '../widgets/queue_card.dart';
|
||||||
|
@ -17,95 +18,98 @@ class _CurrentlyPlayingPageState extends State<CurrentlyPlayingPage> {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, constraints) => Stack(children: [
|
builder: (BuildContext context, BoxConstraints constraints) => Stack(
|
||||||
Padding(
|
children: <Widget>[
|
||||||
padding: const EdgeInsets.only(
|
Padding(
|
||||||
left: 12.0,
|
padding: const EdgeInsets.only(
|
||||||
right: 12.0,
|
left: 12.0,
|
||||||
top: 8.0,
|
right: 12.0,
|
||||||
),
|
top: 8.0,
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Row(
|
||||||
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(
|
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.repeat, size: 20.0),
|
IconButton(
|
||||||
Icon(Icons.skip_previous, size: 40.0),
|
icon: Icon(Icons.expand_more),
|
||||||
Icon(
|
onPressed: () {
|
||||||
Icons.play_circle_filled,
|
Navigator.pop(context);
|
||||||
size: 64.0,
|
},
|
||||||
),
|
),
|
||||||
Icon(Icons.skip_next, size: 40.0),
|
IconButton(
|
||||||
Icon(Icons.shuffle, size: 20.0),
|
icon: Icon(Icons.more_vert),
|
||||||
|
onPressed: () {},
|
||||||
|
)
|
||||||
],
|
],
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
),
|
),
|
||||||
),
|
Spacer(),
|
||||||
Container(
|
Padding(
|
||||||
height: 72,
|
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(
|
||||||
QueueCard(
|
boxConstraints: constraints,
|
||||||
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> {
|
class _QueueCardState extends State<QueueCard> {
|
||||||
final title = "Fire";
|
final title = 'Fire';
|
||||||
final artist = "Beartooth";
|
final artist = 'Beartooth';
|
||||||
final height = 64.0;
|
final height = 64.0;
|
||||||
|
|
||||||
bool _first = true;
|
bool _first = true;
|
||||||
|
|
Loading…
Add table
Reference in a new issue