New icon, banner, New font, Player UI fixes, Details UI fixed

This commit is contained in:
exttex 2020-07-18 23:45:48 +02:00
parent 4b3d264e2a
commit 691f7865d5
32 changed files with 516 additions and 329 deletions

View file

@ -43,6 +43,10 @@ class _FreezerAppState extends State<FreezerApp> {
void initState() {
//Make update theme global
updateTheme = _updateTheme;
//Precache placeholder
precacheImage(imagesDatabase.placeholderThumb, context);
super.initState();
}

View file

@ -67,11 +67,13 @@ class Settings {
Settings({this.downloadPath, this.arl});
static const deezerBg = Color(0xFF1F1A16);
static const font = 'MabryPro';
ThemeData get themeData {
switch (theme??Themes.Light) {
case Themes.Light:
return ThemeData(
fontFamily: 'Montserrat',
fontFamily: font,
primaryColor: primaryColor,
accentColor: primaryColor,
sliderTheme: _sliderTheme,
@ -79,16 +81,33 @@ class Settings {
);
case Themes.Dark:
return ThemeData(
fontFamily: 'Montserrat',
fontFamily: font,
brightness: Brightness.dark,
primaryColor: primaryColor,
accentColor: primaryColor,
sliderTheme: _sliderTheme,
toggleableActiveColor: primaryColor,
);
case Themes.Deezer:
return ThemeData(
fontFamily: font,
brightness: Brightness.dark,
primaryColor: primaryColor,
accentColor: primaryColor,
sliderTheme: _sliderTheme,
toggleableActiveColor: primaryColor,
backgroundColor: deezerBg,
scaffoldBackgroundColor: deezerBg,
bottomAppBarColor: deezerBg,
dialogBackgroundColor: deezerBg,
bottomSheetTheme: BottomSheetThemeData(
backgroundColor: deezerBg
),
cardColor: deezerBg
);
case Themes.Black:
return ThemeData(
fontFamily: 'Montserrat',
fontFamily: font,
brightness: Brightness.dark,
primaryColor: primaryColor,
accentColor: primaryColor,
@ -185,10 +204,12 @@ enum AudioQuality {
enum Themes {
Light,
Dark,
Deezer,
Black
}
enum DownloadNaming {
DEFAULT,
STANDALONE
STANDALONE,
}

View file

@ -99,5 +99,6 @@ const _$DownloadNamingEnumMap = {
const _$ThemesEnumMap = {
Themes.Light: 'Light',
Themes.Dark: 'Dark',
Themes.Deezer: 'Deezer',
Themes.Black: 'Black',
};

View file

@ -27,6 +27,8 @@ class ImagesDatabase {
Database db;
String imagesPath;
ImageProvider placeholderThumb = new AssetImage('assets/cover_thumb.jpg');
//Prepare database
Future init() async {
String dir = await getDatabasesPath();
@ -82,7 +84,7 @@ class ImagesDatabase {
Future<PaletteGenerator> getPaletteGenerator(String url) async {
String path = await getImage(url);
//Get image provider
ImageProvider provider = AssetImage('assets/cover.jpg');
ImageProvider provider = placeholderThumb;
if (path != null) {
provider = FileImage(File(path));
}
@ -120,8 +122,7 @@ class CachedImage extends StatefulWidget {
class _CachedImageState extends State<CachedImage> {
final ImageProvider _placeholder = AssetImage('assets/cover.jpg');
ImageProvider _image = AssetImage('assets/cover.jpg');
ImageProvider _image = imagesDatabase.placeholderThumb;
double _opacity = 0.0;
bool _disposed = false;
String _prevUrl;
@ -135,7 +136,7 @@ class _CachedImageState extends State<CachedImage> {
}
//Load image from db
String path = await imagesDatabase.getImage(widget.url);
if (path == null) return _placeholder;
if (path == null) return imagesDatabase.placeholderThumb;
return FileImage(File(path));
}
@ -177,10 +178,10 @@ class _CachedImageState extends State<CachedImage> {
widget.circular ?
CircleAvatar(
radius: (widget.width??widget.height),
backgroundImage: _placeholder,
backgroundImage: imagesDatabase.placeholderThumb,
):
Image(
image: _placeholder,
image: imagesDatabase.placeholderThumb,
height: widget.height,
width: widget.width,
),

View file

@ -48,7 +48,7 @@ class AlbumDetails extends StatelessWidget {
Container(height: 8.0,),
CachedImage(
url: album.art.full,
height: 256.0,
width: MediaQuery.of(context).size.width / 2
),
Container(height: 8,),
Text(
@ -259,11 +259,10 @@ class ArtistDetails extends StatelessWidget {
children: <Widget>[
CachedImage(
url: artist.picture.full,
height: 200,
width: MediaQuery.of(context).size.width / 2 - 8,
),
Container(
width: 200.0,
height: 220,
width: MediaQuery.of(context).size.width / 2 - 8,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
@ -500,11 +499,10 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
children: <Widget>[
CachedImage(
url: playlist.image.full,
height: 180.0,
height: MediaQuery.of(context).size.width / 2 - 8,
),
Container(
width: 180,
height: 200, //Card padding
width: MediaQuery.of(context).size.width / 2 - 8,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,

View file

@ -11,19 +11,18 @@ import '../settings.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
//TODO: SingleChildScrollView vs ListView speed/perf
return SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
SafeArea(
child: FreezerTitle(),
),
Flexible(child: HomePageScreen(),)
],
),
);
/*
return ListView(
children: <Widget>[
@ -34,22 +33,33 @@ class HomeScreen extends StatelessWidget {
HomePageScreen()
],
);
*/
*/
}
}
class FreezerTitle extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
'freezer',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Jost',
fontSize: 75,
fontStyle: FontStyle.italic,
letterSpacing: 7
return Padding(
padding: EdgeInsets.fromLTRB(0, 24, 0, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset('assets/icon.png', width: 64, height: 64),
Text(
'freezer',
style: TextStyle(
fontSize: 56,
fontWeight: FontWeight.w900
),
)
],
)
],
),
);
}
@ -158,7 +168,10 @@ class _HomePageScreenState extends State<HomePageScreen> {
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 24.0),
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold
),
),
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0)
),

View file

@ -121,40 +121,45 @@ class PlayPauseButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
//Playing
if (AudioService.playbackState?.playing??false) {
return IconButton(
iconSize: this.size,
icon: Icon(Icons.pause),
onPressed: () => AudioService.pause()
);
}
return StreamBuilder(
stream: AudioService.playbackStateStream,
builder: (context, snapshot) {
//Playing
if (AudioService.playbackState?.playing??false) {
return IconButton(
iconSize: this.size,
icon: Icon(Icons.pause),
onPressed: () => AudioService.pause()
);
}
//Paused
if ((!AudioService.playbackState.playing &&
AudioService.playbackState.processingState == AudioProcessingState.ready) ||
//None state (stopped)
AudioService.playbackState.processingState == AudioProcessingState.none) {
return IconButton(
iconSize: this.size,
icon: Icon(Icons.play_arrow),
onPressed: () => AudioService.play()
);
}
//Paused
if ((!AudioService.playbackState.playing &&
AudioService.playbackState.processingState == AudioProcessingState.ready) ||
//None state (stopped)
AudioService.playbackState.processingState == AudioProcessingState.none) {
return IconButton(
iconSize: this.size,
icon: Icon(Icons.play_arrow),
onPressed: () => AudioService.play()
);
}
switch (AudioService.playbackState.processingState) {
//Stopped/Error
case AudioProcessingState.error:
case AudioProcessingState.none:
case AudioProcessingState.stopped:
return Container(width: this.size, height: this.size);
//Loading, connecting, rewinding...
default:
return Container(
width: this.size,
height: this.size,
child: CircularProgressIndicator(),
);
}
switch (AudioService.playbackState.processingState) {
//Stopped/Error
case AudioProcessingState.error:
case AudioProcessingState.none:
case AudioProcessingState.stopped:
return Container(width: this.size, height: this.size);
//Loading, connecting, rewinding...
default:
return Container(
width: this.size,
height: this.size,
child: CircularProgressIndicator(),
);
}
},
);
}
}

View file

@ -3,9 +3,11 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:audio_service/audio_service.dart';
import 'package:flutter_screenutil/screenutil.dart';
import 'package:freezer/api/deezer.dart';
import 'package:freezer/api/player.dart';
import 'package:freezer/ui/menu.dart';
import 'package:freezer/ui/settings_screen.dart';
import 'package:freezer/ui/tiles.dart';
import 'package:async/async.dart';
@ -13,9 +15,6 @@ import 'cached_image.dart';
import '../api/definitions.dart';
import 'player_bar.dart';
class PlayerScreen extends StatefulWidget {
@override
_PlayerScreenState createState() => _PlayerScreenState();
@ -23,242 +22,35 @@ class PlayerScreen extends StatefulWidget {
class _PlayerScreenState extends State<PlayerScreen> {
double iconSize = 48;
bool _lyrics = false;
@override
Widget build(BuildContext context) {
//Responsive
ScreenUtil.init(context, allowFontScaling: true);
return Scaffold(
body: SafeArea(
child: StreamBuilder(
stream: StreamZip([AudioService.playbackStateStream, AudioService.currentMediaItemStream]),
builder: (BuildContext context, AsyncSnapshot snapshot) {
//Disable lyrics when skipping songs, loading
if (snapshot.data is PlaybackState &&
snapshot.data.processingState != AudioProcessingState.ready &&
snapshot.data.processingState != AudioProcessingState.buffering) _lyrics = false;
//When disconnected
if (AudioService.currentMediaItem == null) {
playerHelper.startService();
return Center(child: CircularProgressIndicator(),);
}
return OrientationBuilder(
builder: (context, orientation) {
//Landscape
if (orientation == Orientation.landscape) {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(16, 0, 16, 8),
child: Container(
width: 320,
child: Stack(
children: <Widget>[
CachedImage(
url: AudioService.currentMediaItem.artUri,
),
if (_lyrics) LyricsWidget(
artUri: AudioService.currentMediaItem.artUri,
trackId: AudioService.currentMediaItem.id,
lyrics: Track.fromMediaItem(AudioService.currentMediaItem).lyrics,
height: 320.0,
),
],
),
)
),
SizedBox(
width: MediaQuery.of(context).size.width / 2 - 32,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(8, 16, 8, 0),
child: Container(
width: 300,
child: PlayerScreenTopRow(),
)
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
AudioService.currentMediaItem.displayTitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold
),
),
Container(height: 4,),
Text(
AudioService.currentMediaItem.displaySubtitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 18.0,
color: Theme.of(context).primaryColor,
),
),
],
),
Container(
width: 320,
child: SeekBar(),
),
Container(
width: 320,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
PrevNextButton(iconSize, prev: true,),
PlayPauseButton(iconSize),
PrevNextButton(iconSize)
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(8, 0, 8, 16),
child: Container(
width: 300,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.subtitles),
onPressed: () {
setState(() => _lyrics = !_lyrics);
},
),
Text(
AudioService.currentMediaItem.extras['qualityString']
),
IconButton(
icon: Icon(Icons.more_vert),
onPressed: () {
Track t = Track.fromMediaItem(AudioService.currentMediaItem);
MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(t);
},
)
],
),
)
)
],
),
)
],
);
}
return OrientationBuilder(
builder: (context, orientation) {
//Landscape
if (orientation == Orientation.landscape) {
return PlayerScreenHorizontal();
}
//Portrait
return PlayerScreenVertical();
},
);
//Portrait
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(28, 12, 28, 4),
child: PlayerScreenTopRow()
),
Padding(
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Container(
height: 360,
child: Stack(
children: <Widget>[
CachedImage(
url: AudioService.currentMediaItem.artUri,
),
if (_lyrics) LyricsWidget(
artUri: AudioService.currentMediaItem.artUri,
trackId: AudioService.currentMediaItem.id,
lyrics: Track.fromMediaItem(AudioService.currentMediaItem).lyrics,
height: 360.0,
),
],
),
)
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
AudioService.currentMediaItem.displayTitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold
),
),
Container(height: 4,),
Text(
AudioService.currentMediaItem.displaySubtitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 18.0,
color: Theme.of(context).primaryColor,
),
),
],
),
SeekBar(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
PrevNextButton(iconSize, prev: true,),
PlayPauseButton(iconSize),
PrevNextButton(iconSize)
],
),
//Container(height: 8.0,),
Padding(
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 16.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.subtitles),
onPressed: () {
setState(() => _lyrics = !_lyrics);
},
),
Text(
AudioService.currentMediaItem.extras['qualityString']
),
IconButton(
icon: Icon(Icons.more_vert),
onPressed: () {
Track t = Track.fromMediaItem(AudioService.currentMediaItem);
MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(t);
},
)
],
),
)
],
);
},
);
},
),
)
@ -266,6 +58,265 @@ class _PlayerScreenState extends State<PlayerScreen> {
}
}
//Landscape
class PlayerScreenHorizontal extends StatefulWidget {
@override
_PlayerScreenHorizontalState createState() => _PlayerScreenHorizontalState();
}
class _PlayerScreenHorizontalState extends State<PlayerScreenHorizontal> {
double iconSize = ScreenUtil().setWidth(64);
bool _lyrics = false;
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(16, 0, 16, 8),
child: Container(
width: ScreenUtil().setWidth(500),
child: Stack(
children: <Widget>[
CachedImage(
url: AudioService.currentMediaItem.artUri,
),
if (_lyrics) LyricsWidget(
artUri: AudioService.currentMediaItem.artUri,
trackId: AudioService.currentMediaItem.id,
lyrics: Track.fromMediaItem(AudioService.currentMediaItem).lyrics,
height: ScreenUtil().setWidth(500),
),
],
),
)
),
//Right side
SizedBox(
width: ScreenUtil().setWidth(500),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(8, 16, 8, 0),
child: Container(
child: PlayerScreenTopRow(
textSize: ScreenUtil().setSp(26),
iconSize: ScreenUtil().setSp(32),
textWidth: ScreenUtil().setWidth(256),
short: true
),
)
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
AudioService.currentMediaItem.displayTitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: ScreenUtil().setSp(40),
fontWeight: FontWeight.bold
),
),
Container(height: 4,),
Text(
AudioService.currentMediaItem.displaySubtitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: ScreenUtil().setSp(32),
color: Theme.of(context).primaryColor,
),
),
],
),
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: SeekBar(),
),
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
PrevNextButton(iconSize, prev: true,),
PlayPauseButton(iconSize),
PrevNextButton(iconSize)
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(8, 0, 8, 16),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 2.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.subtitles, size: ScreenUtil().setWidth(32)),
onPressed: () {
setState(() => _lyrics = !_lyrics);
},
),
FlatButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => QualitySettings())
),
child: Text(
AudioService.currentMediaItem.extras['qualityString'],
style: TextStyle(fontSize: ScreenUtil().setSp(24)),
),
),
IconButton(
icon: Icon(Icons.more_vert, size: ScreenUtil().setWidth(32)),
onPressed: () {
Track t = Track.fromMediaItem(AudioService.currentMediaItem);
MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(t);
},
)
],
),
)
)
],
),
)
],
);
}
}
//Portrait
class PlayerScreenVertical extends StatefulWidget {
@override
_PlayerScreenVerticalState createState() => _PlayerScreenVerticalState();
}
class _PlayerScreenVerticalState extends State<PlayerScreenVertical> {
double iconSize = ScreenUtil().setWidth(100);
bool _lyrics = false;
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(28, 10, 28, 0),
child: PlayerScreenTopRow()
),
Padding(
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Container(
height: ScreenUtil().setHeight(1050),
child: Stack(
children: <Widget>[
CachedImage(
url: AudioService.currentMediaItem.artUri,
),
if (_lyrics) LyricsWidget(
artUri: AudioService.currentMediaItem.artUri,
trackId: AudioService.currentMediaItem.id,
lyrics: Track.fromMediaItem(AudioService.currentMediaItem).lyrics,
height: ScreenUtil().setHeight(1050),
),
],
),
)
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
AudioService.currentMediaItem.displayTitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: ScreenUtil().setSp(64),
fontWeight: FontWeight.bold
),
),
Container(height: 4,),
Text(
AudioService.currentMediaItem.displaySubtitle,
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: ScreenUtil().setSp(52),
color: Theme.of(context).primaryColor,
),
),
],
),
SeekBar(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
PrevNextButton(iconSize, prev: true,),
PlayPauseButton(iconSize),
PrevNextButton(iconSize)
],
),
//Container(height: 8.0,),
Padding(
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 16.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.subtitles, size: ScreenUtil().setWidth(46)),
onPressed: () {
setState(() => _lyrics = !_lyrics);
},
),
FlatButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => QualitySettings())
),
child: Text(
AudioService.currentMediaItem.extras['qualityString'],
style: TextStyle(
fontSize: ScreenUtil().setSp(32),
),
),
),
IconButton(
icon: Icon(Icons.more_vert, size: ScreenUtil().setWidth(46)),
onPressed: () {
Track t = Track.fromMediaItem(AudioService.currentMediaItem);
MenuSheet m = MenuSheet(context);
m.defaultTrackMenu(t);
},
)
],
),
)
],
);
}
}
class LyricsWidget extends StatefulWidget {
final Lyrics lyrics;
@ -287,8 +338,11 @@ class _LyricsWidgetState extends State<LyricsWidget> {
Timer _timer;
int _currentIndex;
double _boxHeight;
String _trackId;
Future _load() async {
_trackId = widget.trackId;
//Get text color by album art (black or white)
if (widget.artUri != null) {
bool bw = await imagesDatabase.isDark(widget.artUri);
@ -298,7 +352,7 @@ class _LyricsWidgetState extends State<LyricsWidget> {
if (widget.lyrics.lyrics == null || widget.lyrics.lyrics.length == 0) {
//Load from api
try {
_l = await deezerAPI.lyrics(widget.trackId);
_l = await deezerAPI.lyrics(_trackId);
setState(() => _loading = false);
} catch (e) {
//Error Lyrics
@ -315,6 +369,7 @@ class _LyricsWidgetState extends State<LyricsWidget> {
void initState() {
this._boxHeight = widget.height??400.0;
_load();
Timer.periodic(Duration(milliseconds: 500), (timer) {
_timer = timer;
if (_loading) return;
@ -340,6 +395,18 @@ class _LyricsWidgetState extends State<LyricsWidget> {
super.dispose();
}
@override
void didUpdateWidget(LyricsWidget oldWidget) {
if (this._trackId != widget.trackId) {
setState(() {
_loading = true;
this._trackId = widget.trackId;
});
_load();
}
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return Container(
@ -360,15 +427,31 @@ class _LyricsWidgetState extends State<LyricsWidget> {
return Container(
height: _boxHeight,
child: Center(
child: Text(
_l.lyrics[i].text,
textAlign: TextAlign.center,
style: TextStyle(
color: _textColor,
fontSize: 40.0,
fontWeight: (_currentIndex == i)?FontWeight.bold:FontWeight.normal
),
),
child: Stack(
children: <Widget>[
Text(
_l.lyrics[i].text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 36.0,
fontWeight: (_currentIndex == i)?FontWeight.bold:FontWeight.normal,
foreground: Paint()
..strokeWidth = 6
..style = PaintingStyle.stroke
..color = (_textColor==Colors.black)?Colors.white:Colors.black,
),
),
Text(
_l.lyrics[i].text,
textAlign: TextAlign.center,
style: TextStyle(
color: _textColor,
fontSize: 36.0,
fontWeight: (_currentIndex == i)?FontWeight.bold:FontWeight.normal
),
),
],
)
)
);
}),
@ -382,26 +465,55 @@ class _LyricsWidgetState extends State<LyricsWidget> {
//Top row containing QueueSource, queue...
class PlayerScreenTopRow extends StatelessWidget {
double textSize;
double iconSize;
double textWidth;
bool short;
PlayerScreenTopRow({this.textSize, this.iconSize, this.textWidth, this.short});
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Playing from: ' + playerHelper.queueSource.text,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.right,
style: TextStyle(fontSize: 16.0),
Row(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 8, 0),
child: InkWell(
child: Container(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.keyboard_arrow_down, size: this.iconSize??ScreenUtil().setWidth(46)),
),
onTap: () {
Navigator.of(context).pop();
},
),
),
Container(
width: this.textWidth??ScreenUtil().setWidth(600),
child: Text(
(short??false)?playerHelper.queueSource.text:'Playing from: ' + playerHelper.queueSource.text,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
style: TextStyle(fontSize: this.textSize??ScreenUtil().setSp(34)),
),
)
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RepeatButton(),
RepeatButton(size: this.iconSize),
Container(width: 16.0,),
InkWell(
child: Icon(Icons.menu),
child: Container(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.menu, size: this.iconSize??ScreenUtil().setWidth(46)),
),
onTap: (){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => QueueScreen()
@ -418,25 +530,33 @@ class PlayerScreenTopRow extends StatelessWidget {
class RepeatButton extends StatefulWidget {
double size;
RepeatButton({this.size, Key key}): super(key: key);
@override
_RepeatButtonState createState() => _RepeatButtonState();
}
class _RepeatButtonState extends State<RepeatButton> {
double _size = ScreenUtil().setWidth(46);
Icon get icon {
switch (playerHelper.repeatType) {
case RepeatType.NONE:
return Icon(Icons.repeat);
return Icon(Icons.repeat, size: widget.size??_size);
case RepeatType.LIST:
return Icon(
Icons.repeat,
color: Theme.of(context).primaryColor,
size: widget.size??_size
);
case RepeatType.TRACK:
return Icon(
Icons.repeat_one,
color: Theme.of(context).primaryColor,
size: widget.size??_size
);
}
}
@ -453,7 +573,10 @@ class _RepeatButtonState extends State<RepeatButton> {
await playerHelper.changeRepeat();
setState(() {});
},
child: icon,
child: Container(
padding: EdgeInsets.all(8.0),
child: icon,
),
);
}
}
@ -505,13 +628,13 @@ class _SeekBarState extends State<SeekBar> {
Text(
_timeString(position),
style: TextStyle(
fontSize: 14.0
fontSize: ScreenUtil().setSp(35)
),
),
Text(
_timeString(duration),
style: TextStyle(
fontSize: 14.0
fontSize: ScreenUtil().setSp(35)
),
)
],

View file

@ -126,7 +126,8 @@ class SearchResultsScreen extends StatelessWidget {
'Tracks',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26.0
fontSize: 26.0,
fontWeight: FontWeight.bold
),
),
...List.generate(3, (i) {
@ -170,7 +171,8 @@ class SearchResultsScreen extends StatelessWidget {
'Albums',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26.0
fontSize: 26.0,
fontWeight: FontWeight.bold
),
),
...List.generate(3, (i) {
@ -208,7 +210,8 @@ class SearchResultsScreen extends StatelessWidget {
'Artists',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26.0
fontSize: 26.0,
fontWeight: FontWeight.bold
),
),
Container(height: 4),
@ -243,7 +246,8 @@ class SearchResultsScreen extends StatelessWidget {
'Playlists',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26.0
fontSize: 26.0,
fontWeight: FontWeight.bold
),
),
...List.generate(3, (i) {

View file

@ -136,7 +136,16 @@ class _AppearanceSettingsState extends State<AppearanceSettings> {
updateTheme();
Navigator.of(context).pop();
},
)
),
SimpleDialogOption(
child: Text('Deezer (Dark)'),
onPressed: () {
setState(() => settings.theme = Themes.Deezer);
settings.save();
updateTheme();
Navigator.of(context).pop();
},
),
],
);
}
@ -274,9 +283,13 @@ class _QualityPickerState extends State<QualityPicker> {
});
switch (widget.field) {
case 'mobile':
settings.mobileQuality = _quality; break;
settings.mobileQuality = _quality;
settings.updateAudioServiceQuality();
break;
case 'wifi':
settings.wifiQuality = _quality; break;
settings.wifiQuality = _quality;
settings.updateAudioServiceQuality();
break;
case 'download':
settings.downloadQuality = _quality; break;
case 'offline':

View file

@ -129,7 +129,7 @@ class ArtistTile extends StatelessWidget {
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16.0
fontSize: 14.0
),
),
Container(height: 4,),
@ -228,7 +228,7 @@ class PlaylistCardTile extends StatelessWidget {
maxLines: 1,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 16.0),
style: TextStyle(fontSize: 14.0),
),
),
Container(height: 8.0,)
@ -271,7 +271,7 @@ class SmartTrackListTile extends StatelessWidget {
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16.0
fontSize: 14.0
),
),
),
@ -315,7 +315,7 @@ class AlbumCard extends StatelessWidget {
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16.0
fontSize: 14.0
),
),
),