code fixes:
- remove unused imports - remove clipboard plugin and directly use flutter's clipboard class - replace deprecated stuff
This commit is contained in:
parent
3105ed6c1d
commit
519adc910f
|
|
@ -1,9 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:freezer/api/deezer.dart';
|
|
||||||
import 'package:freezer/api/definitions.dart';
|
import 'package:freezer/api/definitions.dart';
|
||||||
import 'package:freezer/ui/details_screens.dart';
|
|
||||||
import 'package:freezer/ui/library.dart';
|
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import 'package:freezer/api/spotify.dart';
|
||||||
import 'package:freezer/settings.dart';
|
import 'package:freezer/settings.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
|
@ -32,7 +31,7 @@ class DeezerAPI {
|
||||||
"Accept-Charset": "utf-8,ISO-8859-1;q=0.7,*;q=0.3",
|
"Accept-Charset": "utf-8,ISO-8859-1;q=0.7,*;q=0.3",
|
||||||
"Accept-Language": "${settings.deezerLanguage??"en"}-${settings.deezerCountry??'US'},${settings.deezerLanguage??"en"};q=0.9,en-US;q=0.8,en;q=0.7",
|
"Accept-Language": "${settings.deezerLanguage??"en"}-${settings.deezerCountry??'US'},${settings.deezerLanguage??"en"};q=0.9,en-US;q=0.8,en;q=0.7",
|
||||||
"Connection": "keep-alive",
|
"Connection": "keep-alive",
|
||||||
"Cookie": "arl=${arl}" + ((sid == null) ? '' : '; sid=${sid}')
|
"Cookie": "arl=$arl" + ((sid == null) ? '' : '; sid=$sid')
|
||||||
};
|
};
|
||||||
|
|
||||||
//Call private API
|
//Call private API
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ class Artist {
|
||||||
Map<dynamic, dynamic> json, {
|
Map<dynamic, dynamic> json, {
|
||||||
Map<dynamic, dynamic> albumsJson = const {},
|
Map<dynamic, dynamic> albumsJson = const {},
|
||||||
Map<dynamic, dynamic> topJson = const {},
|
Map<dynamic, dynamic> topJson = const {},
|
||||||
Map<dynamic, dynamic> highlight = null,
|
Map<dynamic, dynamic> highlight,
|
||||||
bool library = false
|
bool library = false
|
||||||
}) {
|
}) {
|
||||||
//Get wether radio is available
|
//Get wether radio is available
|
||||||
|
|
|
||||||
|
|
@ -373,14 +373,14 @@ class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateM
|
||||||
items: <BottomNavigationBarItem>[
|
items: <BottomNavigationBarItem>[
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Icon(Icons.home),
|
icon: Icon(Icons.home),
|
||||||
title: Text('Home'.i18n)),
|
label: 'Home'.i18n),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Icon(Icons.search),
|
icon: Icon(Icons.search),
|
||||||
title: Text('Search'.i18n),
|
label: 'Search'.i18n,
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Icon(Icons.library_music),
|
icon: Icon(Icons.library_music),
|
||||||
title: Text('Library'.i18n))
|
label: 'Library'.i18n)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -213,8 +213,8 @@ class Settings {
|
||||||
case AudioQuality.MP3_128: return 1;
|
case AudioQuality.MP3_128: return 1;
|
||||||
case AudioQuality.MP3_320: return 3;
|
case AudioQuality.MP3_320: return 3;
|
||||||
case AudioQuality.FLAC: return 9;
|
case AudioQuality.FLAC: return 9;
|
||||||
|
default: return 8;
|
||||||
}
|
}
|
||||||
return 8; //default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if is dark, can't use theme directly, because of system themes, and Theme.of(context).brightness broke
|
//Check if is dark, can't use theme directly, because of system themes, and Theme.of(context).brightness broke
|
||||||
|
|
@ -242,6 +242,7 @@ class Settings {
|
||||||
sliderTheme: _sliderTheme,
|
sliderTheme: _sliderTheme,
|
||||||
toggleableActiveColor: primaryColor,
|
toggleableActiveColor: primaryColor,
|
||||||
bottomAppBarColor: Color(0xfff5f5f5),
|
bottomAppBarColor: Color(0xfff5f5f5),
|
||||||
|
appBarTheme: AppBarTheme(brightness: Brightness.light),
|
||||||
),
|
),
|
||||||
Themes.Dark: ThemeData(
|
Themes.Dark: ThemeData(
|
||||||
textTheme: _textTheme,
|
textTheme: _textTheme,
|
||||||
|
|
@ -251,6 +252,7 @@ class Settings {
|
||||||
accentColor: primaryColor,
|
accentColor: primaryColor,
|
||||||
sliderTheme: _sliderTheme,
|
sliderTheme: _sliderTheme,
|
||||||
toggleableActiveColor: primaryColor,
|
toggleableActiveColor: primaryColor,
|
||||||
|
appBarTheme: AppBarTheme(brightness: Brightness.dark),
|
||||||
),
|
),
|
||||||
Themes.Deezer: ThemeData(
|
Themes.Deezer: ThemeData(
|
||||||
textTheme: _textTheme,
|
textTheme: _textTheme,
|
||||||
|
|
@ -267,6 +269,7 @@ class Settings {
|
||||||
bottomSheetTheme: BottomSheetThemeData(
|
bottomSheetTheme: BottomSheetThemeData(
|
||||||
backgroundColor: deezerBottom
|
backgroundColor: deezerBottom
|
||||||
),
|
),
|
||||||
|
appBarTheme: AppBarTheme(brightness: Brightness.dark),
|
||||||
cardColor: deezerBg
|
cardColor: deezerBg
|
||||||
),
|
),
|
||||||
Themes.Black: ThemeData(
|
Themes.Black: ThemeData(
|
||||||
|
|
@ -283,7 +286,8 @@ class Settings {
|
||||||
toggleableActiveColor: primaryColor,
|
toggleableActiveColor: primaryColor,
|
||||||
bottomSheetTheme: BottomSheetThemeData(
|
bottomSheetTheme: BottomSheetThemeData(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
)
|
),
|
||||||
|
appBarTheme: AppBarTheme(brightness: Brightness.dark),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
|
@ -114,7 +113,7 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ctx = context;
|
ctx = context;
|
||||||
return FlatButton(
|
return TextButton(
|
||||||
child: CachedImage(
|
child: CachedImage(
|
||||||
url: widget.url,
|
url: widget.url,
|
||||||
rounded: widget.rounded,
|
rounded: widget.rounded,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:fluttericon/font_awesome5_icons.dart';
|
import 'package:fluttericon/font_awesome5_icons.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
|
@ -21,7 +18,7 @@ import 'menu.dart';
|
||||||
|
|
||||||
class AlbumDetails extends StatefulWidget {
|
class AlbumDetails extends StatefulWidget {
|
||||||
|
|
||||||
Album album;
|
final Album album;
|
||||||
AlbumDetails(this.album, {Key key}): super(key: key);
|
AlbumDetails(this.album, {Key key}): super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -165,7 +162,7 @@ class _AlbumDetailsState extends State<AlbumDetails> {
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon((album.library??false)? Icons.favorite : Icons.favorite_border, size: 32),
|
Icon((album.library??false)? Icons.favorite : Icons.favorite_border, size: 32),
|
||||||
|
|
@ -196,7 +193,7 @@ class _AlbumDetailsState extends State<AlbumDetails> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
MakeAlbumOffline(album: album),
|
MakeAlbumOffline(album: album),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Icons.file_download, size: 32.0,),
|
Icon(Icons.file_download, size: 32.0,),
|
||||||
|
|
@ -248,7 +245,7 @@ class _AlbumDetailsState extends State<AlbumDetails> {
|
||||||
|
|
||||||
class MakeAlbumOffline extends StatefulWidget {
|
class MakeAlbumOffline extends StatefulWidget {
|
||||||
|
|
||||||
Album album;
|
final Album album;
|
||||||
MakeAlbumOffline({Key key, this.album}): super(key: key);
|
MakeAlbumOffline({Key key, this.album}): super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -266,6 +263,7 @@ class _MakeAlbumOfflineState extends State<MakeAlbumOffline> {
|
||||||
_offline = v;
|
_offline = v;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -399,7 +397,7 @@ class ArtistDetails extends StatelessWidget {
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Icons.favorite, size: 32),
|
Icon(Icons.favorite, size: 32),
|
||||||
|
|
@ -417,7 +415,7 @@ class ArtistDetails extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if ((artist.radio??false))
|
if ((artist.radio??false))
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Icons.radio, size: 32),
|
Icon(Icons.radio, size: 32),
|
||||||
|
|
@ -714,7 +712,7 @@ class _DiscographyScreenState extends State<DiscographyScreen> {
|
||||||
|
|
||||||
class PlaylistDetails extends StatefulWidget {
|
class PlaylistDetails extends StatefulWidget {
|
||||||
|
|
||||||
Playlist playlist;
|
final Playlist playlist;
|
||||||
PlaylistDetails(this.playlist, {Key key}): super(key: key);
|
PlaylistDetails(this.playlist, {Key key}): super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -1060,7 +1058,7 @@ class _PlaylistDetailsState extends State<PlaylistDetails> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MakePlaylistOffline extends StatefulWidget {
|
class MakePlaylistOffline extends StatefulWidget {
|
||||||
Playlist playlist;
|
final Playlist playlist;
|
||||||
MakePlaylistOffline(this.playlist, {Key key}): super(key: key);
|
MakePlaylistOffline(this.playlist, {Key key}): super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -1077,6 +1075,7 @@ class _MakePlaylistOfflineState extends State<MakePlaylistOffline> {
|
||||||
_offline = v;
|
_offline = v;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -1115,7 +1114,7 @@ class _MakePlaylistOfflineState extends State<MakePlaylistOffline> {
|
||||||
|
|
||||||
class ShowScreen extends StatefulWidget {
|
class ShowScreen extends StatefulWidget {
|
||||||
|
|
||||||
Show show;
|
final Show show;
|
||||||
ShowScreen(this.show, {Key key}): super(key: key);
|
ShowScreen(this.show, {Key key}): super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -239,11 +239,11 @@ class DownloadTile extends StatelessWidget {
|
||||||
title: Text('Delete'.i18n),
|
title: Text('Delete'.i18n),
|
||||||
content: Text('Are you sure you want to delete this download?'.i18n),
|
content: Text('Are you sure you want to delete this download?'.i18n),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Cancel'.i18n),
|
child: Text('Cancel'.i18n),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Delete'.i18n),
|
child: Text('Delete'.i18n),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await downloadManager.removeDownload(download.id);
|
await downloadManager.removeDownload(download.id);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:freezer/api/deezer.dart';
|
import 'package:freezer/api/deezer.dart';
|
||||||
import 'package:freezer/api/definitions.dart';
|
import 'package:freezer/api/definitions.dart';
|
||||||
import 'package:freezer/api/player.dart';
|
import 'package:freezer/api/player.dart';
|
||||||
import 'package:freezer/main.dart';
|
|
||||||
import 'package:freezer/ui/elements.dart';
|
import 'package:freezer/ui/elements.dart';
|
||||||
import 'package:freezer/ui/error.dart';
|
import 'package:freezer/ui/error.dart';
|
||||||
import 'package:freezer/ui/menu.dart';
|
import 'package:freezer/ui/menu.dart';
|
||||||
|
|
@ -180,7 +179,7 @@ class HomepageSectionWidget extends StatelessWidget {
|
||||||
//Has more items
|
//Has more items
|
||||||
if (j == section.items.length) {
|
if (j == section.items.length) {
|
||||||
if (section.hasMore ?? false) {
|
if (section.hasMore ?? false) {
|
||||||
return FlatButton(
|
return TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Show more'.i18n,
|
'Show more'.i18n,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
|
@ -217,7 +216,7 @@ class HomepageSectionWidget extends StatelessWidget {
|
||||||
|
|
||||||
class HomePageItemWidget extends StatelessWidget {
|
class HomePageItemWidget extends StatelessWidget {
|
||||||
|
|
||||||
HomePageItem item;
|
final HomePageItem item;
|
||||||
HomePageItemWidget(this.item);
|
HomePageItemWidget(this.item);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:freezer/api/deezer.dart';
|
import 'package:freezer/api/deezer.dart';
|
||||||
import 'package:freezer/api/definitions.dart';
|
import 'package:freezer/api/definitions.dart';
|
||||||
|
|
@ -141,9 +140,8 @@ class _ImporterWidgetState extends State<ImporterWidget> {
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RaisedButton(
|
ElevatedButton(
|
||||||
child: Text('Convert'.i18n),
|
child: Text('Convert'.i18n),
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
spotify.convertPlaylist(widget.playlist);
|
spotify.convertPlaylist(widget.playlist);
|
||||||
Navigator.of(context).pushReplacement(MaterialPageRoute(
|
Navigator.of(context).pushReplacement(MaterialPageRoute(
|
||||||
|
|
@ -151,9 +149,8 @@ class _ImporterWidgetState extends State<ImporterWidget> {
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
RaisedButton(
|
ElevatedButton(
|
||||||
child: Text('Download only'.i18n),
|
child: Text('Download only'.i18n),
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
//Ask for quality
|
//Ask for quality
|
||||||
AudioQuality quality;
|
AudioQuality quality;
|
||||||
|
|
@ -263,7 +260,7 @@ class CurrentlyImportingScreen extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (snapshot.data != null)
|
if (snapshot.data != null)
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Playlist menu'.i18n),
|
child: Text('Playlist menu'.i18n),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Playlist p = await deezerAPI.playlist(snapshot.data);
|
Playlist p = await deezerAPI.playlist(snapshot.data);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import '../api/spotify.dart';
|
||||||
import '../api/download.dart';
|
import '../api/download.dart';
|
||||||
|
|
||||||
class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget {
|
class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Size get preferredSize => AppBar().preferredSize;
|
Size get preferredSize => AppBar().preferredSize;
|
||||||
|
|
||||||
|
|
@ -35,22 +34,19 @@ class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
icon: Icon(Icons.file_download),
|
icon: Icon(Icons.file_download),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => DownloadsScreen())
|
MaterialPageRoute(builder: (context) => DownloadsScreen()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.settings),
|
icon: Icon(Icons.settings),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => SettingsScreen())
|
MaterialPageRoute(builder: (context) => SettingsScreen()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LibraryScreen extends StatelessWidget {
|
class LibraryScreen extends StatelessWidget {
|
||||||
|
|
@ -60,17 +56,20 @@ class LibraryScreen extends StatelessWidget {
|
||||||
appBar: LibraryAppBar(),
|
appBar: LibraryAppBar(),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(height: 4.0,),
|
Container(
|
||||||
|
height: 4.0,
|
||||||
|
),
|
||||||
if (!downloadManager.running && downloadManager.queueSize > 0)
|
if (!downloadManager.running && downloadManager.queueSize > 0)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text('Downloads'.i18n),
|
title: Text('Downloads'.i18n),
|
||||||
leading: LeadingIcon(Icons.file_download, color: Colors.grey),
|
leading: LeadingIcon(Icons.file_download, color: Colors.grey),
|
||||||
subtitle: Text('Downloading is currently stopped, click here to resume.'.i18n),
|
subtitle: Text(
|
||||||
|
'Downloading is currently stopped, click here to resume.'
|
||||||
|
.i18n),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
downloadManager.start();
|
downloadManager.start();
|
||||||
Navigator.of(context).push(MaterialPageRoute(
|
Navigator.of(context).push(
|
||||||
builder: (context) => DownloadsScreen()
|
MaterialPageRoute(builder: (context) => DownloadsScreen()));
|
||||||
));
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
@ -78,11 +77,13 @@ class LibraryScreen extends StatelessWidget {
|
||||||
leading: LeadingIcon(Icons.shuffle, color: Color(0xffeca704)),
|
leading: LeadingIcon(Icons.shuffle, color: Color(0xffeca704)),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
List<Track> tracks = await deezerAPI.libraryShuffle();
|
List<Track> tracks = await deezerAPI.libraryShuffle();
|
||||||
playerHelper.playFromTrackList(tracks, tracks[0].id, QueueSource(
|
playerHelper.playFromTrackList(
|
||||||
|
tracks,
|
||||||
|
tracks[0].id,
|
||||||
|
QueueSource(
|
||||||
id: 'libraryshuffle',
|
id: 'libraryshuffle',
|
||||||
source: 'libraryshuffle',
|
source: 'libraryshuffle',
|
||||||
text: 'Library shuffle'.i18n
|
text: 'Library shuffle'.i18n));
|
||||||
));
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
FreezerDivider(),
|
FreezerDivider(),
|
||||||
|
|
@ -91,8 +92,7 @@ class LibraryScreen extends StatelessWidget {
|
||||||
leading: LeadingIcon(Icons.audiotrack, color: Color(0xffbe3266)),
|
leading: LeadingIcon(Icons.audiotrack, color: Color(0xffbe3266)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => LibraryTracks())
|
MaterialPageRoute(builder: (context) => LibraryTracks()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
@ -100,8 +100,7 @@ class LibraryScreen extends StatelessWidget {
|
||||||
leading: LeadingIcon(Icons.album, color: Color(0xff4b2e7e)),
|
leading: LeadingIcon(Icons.album, color: Color(0xff4b2e7e)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => LibraryAlbums())
|
MaterialPageRoute(builder: (context) => LibraryAlbums()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
@ -109,8 +108,7 @@ class LibraryScreen extends StatelessWidget {
|
||||||
leading: LeadingIcon(Icons.recent_actors, color: Color(0xff384697)),
|
leading: LeadingIcon(Icons.recent_actors, color: Color(0xff384697)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => LibraryArtists())
|
MaterialPageRoute(builder: (context) => LibraryArtists()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
@ -118,8 +116,7 @@ class LibraryScreen extends StatelessWidget {
|
||||||
leading: LeadingIcon(Icons.playlist_play, color: Color(0xff0880b5)),
|
leading: LeadingIcon(Icons.playlist_play, color: Color(0xff0880b5)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => LibraryPlaylists())
|
MaterialPageRoute(builder: (context) => LibraryPlaylists()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
FreezerDivider(),
|
FreezerDivider(),
|
||||||
|
|
@ -128,8 +125,7 @@ class LibraryScreen extends StatelessWidget {
|
||||||
leading: LeadingIcon(Icons.history, color: Color(0xff009a85)),
|
leading: LeadingIcon(Icons.history, color: Color(0xff009a85)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => HistoryScreen())
|
MaterialPageRoute(builder: (context) => HistoryScreen()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
FreezerDivider(),
|
FreezerDivider(),
|
||||||
|
|
@ -139,16 +135,14 @@ class LibraryScreen extends StatelessWidget {
|
||||||
subtitle: Text('Import playlists from Spotify'.i18n),
|
subtitle: Text('Import playlists from Spotify'.i18n),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (spotify.doneImporting != null) {
|
if (spotify.doneImporting != null) {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
MaterialPageRoute(builder: (context) => CurrentlyImportingScreen())
|
builder: (context) => CurrentlyImportingScreen()));
|
||||||
);
|
|
||||||
if (spotify.doneImporting) spotify.doneImporting = null;
|
if (spotify.doneImporting) spotify.doneImporting = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => ImporterScreen())
|
MaterialPageRoute(builder: (context) => ImporterScreen()));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ExpansionTile(
|
ExpansionTile(
|
||||||
|
|
@ -159,13 +153,12 @@ class LibraryScreen extends StatelessWidget {
|
||||||
future: downloadManager.getStats(),
|
future: downloadManager.getStats(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return ErrorScreen();
|
if (snapshot.hasError) return ErrorScreen();
|
||||||
if (!snapshot.hasData) return Padding(
|
if (!snapshot.hasData)
|
||||||
|
return Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 4.0),
|
padding: EdgeInsets.symmetric(vertical: 4.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[CircularProgressIndicator()],
|
||||||
CircularProgressIndicator()
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
List<String> data = snapshot.data;
|
List<String> data = snapshot.data;
|
||||||
|
|
@ -214,7 +207,6 @@ class LibraryTracks extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LibraryTracksState extends State<LibraryTracks> {
|
class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
|
|
||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
bool _loadingTracks = false;
|
bool _loadingTracks = false;
|
||||||
ScrollController _scrollController = ScrollController();
|
ScrollController _scrollController = ScrollController();
|
||||||
|
|
@ -233,15 +225,16 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
tcopy.sort((a, b) => a.title.compareTo(b.title));
|
tcopy.sort((a, b) => a.title.compareTo(b.title));
|
||||||
break;
|
break;
|
||||||
case SortType.ARTIST:
|
case SortType.ARTIST:
|
||||||
tcopy.sort((a, b) => a.artists[0].name.toLowerCase().compareTo(b.artists[0].name.toLowerCase()));
|
tcopy.sort((a, b) => a.artists[0].name
|
||||||
|
.toLowerCase()
|
||||||
|
.compareTo(b.artists[0].name.toLowerCase()));
|
||||||
break;
|
break;
|
||||||
case SortType.DEFAULT:
|
case SortType.DEFAULT:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Reverse
|
//Reverse
|
||||||
if (_sort.reverse)
|
if (_sort.reverse) return tcopy.reversed.toList();
|
||||||
return tcopy.reversed.toList();
|
|
||||||
return tcopy;
|
return tcopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,15 +250,15 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
await cache.save();
|
await cache.save();
|
||||||
|
|
||||||
//Preload for sorting
|
//Preload for sorting
|
||||||
if (tracks.length < (trackCount??0))
|
if (tracks.length < (trackCount ?? 0)) _loadFull();
|
||||||
_loadFull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _load() async {
|
Future _load() async {
|
||||||
//Already loaded
|
//Already loaded
|
||||||
if (trackCount != null && tracks.length >= trackCount) {
|
if (trackCount != null && tracks.length >= trackCount) {
|
||||||
//Update tracks cache if fully loaded
|
//Update tracks cache if fully loaded
|
||||||
if (cache.libraryTracks == null || cache.libraryTracks.length != trackCount) {
|
if (cache.libraryTracks == null ||
|
||||||
|
cache.libraryTracks.length != trackCount) {
|
||||||
setState(() {
|
setState(() {
|
||||||
cache.libraryTracks = tracks.map((t) => t.id).toList();
|
cache.libraryTracks = tracks.map((t) => t.id).toList();
|
||||||
});
|
});
|
||||||
|
|
@ -293,8 +286,7 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
//Update
|
//Update
|
||||||
setState(() {
|
setState(() {
|
||||||
trackCount = favPlaylist.trackCount;
|
trackCount = favPlaylist.trackCount;
|
||||||
if (tracks.length == 0)
|
if (tracks.length == 0) tracks = favPlaylist.tracks;
|
||||||
tracks = favPlaylist.tracks;
|
|
||||||
_makeFavorite();
|
_makeFavorite();
|
||||||
_loading = false;
|
_loading = false;
|
||||||
});
|
});
|
||||||
|
|
@ -307,7 +299,8 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
|
|
||||||
List<Track> _t;
|
List<Track> _t;
|
||||||
try {
|
try {
|
||||||
_t = await deezerAPI.playlistTracksPage(deezerAPI.favoritesPlaylistId, pos);
|
_t = await deezerAPI.playlistTracksPage(
|
||||||
|
deezerAPI.favoritesPlaylistId, pos);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
//On error load offline
|
//On error load offline
|
||||||
if (_t == null) {
|
if (_t == null) {
|
||||||
|
|
@ -320,13 +313,12 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
_loading = false;
|
_loading = false;
|
||||||
_loadingTracks = false;
|
_loadingTracks = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load all tracks
|
//Load all tracks
|
||||||
Future _loadFull() async {
|
Future _loadFull() async {
|
||||||
if (tracks.length == 0 || tracks.length < (trackCount??0)) {
|
if (tracks.length == 0 || tracks.length < (trackCount ?? 0)) {
|
||||||
Playlist p;
|
Playlist p;
|
||||||
try {
|
try {
|
||||||
p = await deezerAPI.fullPlaylist(deezerAPI.favoritesPlaylistId);
|
p = await deezerAPI.fullPlaylist(deezerAPI.favoritesPlaylistId);
|
||||||
|
|
@ -342,8 +334,10 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _loadOffline() async {
|
Future _loadOffline() async {
|
||||||
Playlist p = await downloadManager.getPlaylist(deezerAPI.favoritesPlaylistId);
|
Playlist p =
|
||||||
if (p != null) setState(() {
|
await downloadManager.getPlaylist(deezerAPI.favoritesPlaylistId);
|
||||||
|
if (p != null)
|
||||||
|
setState(() {
|
||||||
tracks = p.tracks;
|
tracks = p.tracks;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -357,8 +351,7 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
|
|
||||||
//Update tracks with favorite true
|
//Update tracks with favorite true
|
||||||
void _makeFavorite() {
|
void _makeFavorite() {
|
||||||
for (int i=0; i<tracks.length; i++)
|
for (int i = 0; i < tracks.length; i++) tracks[i].favorite = true;
|
||||||
tracks[i].favorite = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -375,11 +368,9 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
|
|
||||||
//Load sorting
|
//Load sorting
|
||||||
int index = Sorting.index(SortSourceTypes.TRACKS);
|
int index = Sorting.index(SortSourceTypes.TRACKS);
|
||||||
if (index != null)
|
if (index != null) setState(() => _sort = cache.sorts[index]);
|
||||||
setState(() => _sort = cache.sorts[index]);
|
|
||||||
|
|
||||||
if (_sort.type != SortType.DEFAULT || _sort.reverse)
|
if (_sort.type != SortType.DEFAULT || _sort.reverse) _loadFull();
|
||||||
_loadFull();
|
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
@ -391,18 +382,18 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
'Tracks'.i18n,
|
'Tracks'.i18n,
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down),
|
icon: Icon(_sort.reverse
|
||||||
|
? FontAwesome5.sort_alpha_up
|
||||||
|
: FontAwesome5.sort_alpha_down),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await _reverse();
|
await _reverse();
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
child: Icon(Icons.sort, size: 32.0),
|
child: Icon(Icons.sort, size: 32.0),
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
onSelected: (SortType s) async {
|
onSelected: (SortType s) async {
|
||||||
//Preload for sorting
|
//Preload for sorting
|
||||||
if (tracks.length < (trackCount??0))
|
if (tracks.length < (trackCount ?? 0)) await _loadFull();
|
||||||
await _loadFull();
|
|
||||||
|
|
||||||
setState(() => _sort.type = s);
|
setState(() => _sort.type = s);
|
||||||
//Save sorting in cache
|
//Save sorting in cache
|
||||||
|
|
@ -444,45 +435,54 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
MakePlaylistOffline(_playlist),
|
MakePlaylistOffline(_playlist),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Icons.file_download, size: 32.0,),
|
Icon(
|
||||||
Container(width: 4,),
|
Icons.file_download,
|
||||||
|
size: 32.0,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 4,
|
||||||
|
),
|
||||||
Text('Download'.i18n)
|
Text('Download'.i18n)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (await downloadManager.addOfflinePlaylist(_playlist, private: false, context: context) != false)
|
if (await downloadManager.addOfflinePlaylist(_playlist,
|
||||||
|
private: false, context: context) !=
|
||||||
|
false)
|
||||||
MenuSheet(context).showDownloadStartedToast();
|
MenuSheet(context).showDownloadStartedToast();
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)),
|
||||||
),
|
|
||||||
FreezerDivider(),
|
FreezerDivider(),
|
||||||
//Loved tracks
|
//Loved tracks
|
||||||
...List.generate(tracks.length, (i) {
|
...List.generate(tracks.length, (i) {
|
||||||
Track t = (tracks.length == (trackCount??0))?_sorted[i]:tracks[i];
|
Track t = (tracks.length == (trackCount ?? 0))
|
||||||
|
? _sorted[i]
|
||||||
|
: tracks[i];
|
||||||
return TrackTile(
|
return TrackTile(
|
||||||
t,
|
t,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
playerHelper.playFromTrackList((tracks.length == (trackCount??0))?_sorted:tracks, t.id, QueueSource(
|
playerHelper.playFromTrackList(
|
||||||
|
(tracks.length == (trackCount ?? 0))
|
||||||
|
? _sorted
|
||||||
|
: tracks,
|
||||||
|
t.id,
|
||||||
|
QueueSource(
|
||||||
id: deezerAPI.favoritesPlaylistId,
|
id: deezerAPI.favoritesPlaylistId,
|
||||||
text: 'Favorites'.i18n,
|
text: 'Favorites'.i18n,
|
||||||
source: 'playlist'
|
source: 'playlist'));
|
||||||
));
|
|
||||||
},
|
},
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
m.defaultTrackMenu(
|
m.defaultTrackMenu(t, onRemove: () {
|
||||||
t,
|
|
||||||
onRemove: () {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
tracks.removeWhere((track) => t.id == track.id);
|
tracks.removeWhere((track) => t.id == track.id);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
@ -500,22 +500,23 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
Text(
|
Text(
|
||||||
'All offline tracks'.i18n,
|
'All offline tracks'.i18n,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.bold
|
|
||||||
),
|
),
|
||||||
|
Container(
|
||||||
|
height: 8,
|
||||||
),
|
),
|
||||||
Container(height: 8,),
|
|
||||||
...List.generate(allTracks.length, (i) {
|
...List.generate(allTracks.length, (i) {
|
||||||
Track t = allTracks[i];
|
Track t = allTracks[i];
|
||||||
return TrackTile(
|
return TrackTile(
|
||||||
t,
|
t,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
playerHelper.playFromTrackList(allTracks, t.id, QueueSource(
|
playerHelper.playFromTrackList(
|
||||||
|
allTracks,
|
||||||
|
t.id,
|
||||||
|
QueueSource(
|
||||||
id: 'allTracks',
|
id: 'allTracks',
|
||||||
text: 'All offline tracks'.i18n,
|
text: 'All offline tracks'.i18n,
|
||||||
source: 'offline'
|
source: 'offline'));
|
||||||
));
|
|
||||||
},
|
},
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -524,19 +525,16 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
)
|
)));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LibraryAlbums extends StatefulWidget {
|
class LibraryAlbums extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_LibraryAlbumsState createState() => _LibraryAlbumsState();
|
_LibraryAlbumsState createState() => _LibraryAlbumsState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LibraryAlbumsState extends State<LibraryAlbums> {
|
class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
|
|
||||||
List<Album> _albums;
|
List<Album> _albums;
|
||||||
Sorting _sort = Sorting(sourceType: SortSourceTypes.ALBUMS);
|
Sorting _sort = Sorting(sourceType: SortSourceTypes.ALBUMS);
|
||||||
ScrollController _scrollController = ScrollController();
|
ScrollController _scrollController = ScrollController();
|
||||||
|
|
@ -548,22 +546,26 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
case SortType.DEFAULT:
|
case SortType.DEFAULT:
|
||||||
break;
|
break;
|
||||||
case SortType.ALPHABETIC:
|
case SortType.ALPHABETIC:
|
||||||
albums.sort((a, b) => a.title.toLowerCase().compareTo(b.title.toLowerCase()));
|
albums.sort(
|
||||||
|
(a, b) => a.title.toLowerCase().compareTo(b.title.toLowerCase()));
|
||||||
break;
|
break;
|
||||||
case SortType.ARTIST:
|
case SortType.ARTIST:
|
||||||
albums.sort((a, b) => a.artists[0].name.toLowerCase().compareTo(b.artists[0].name.toLowerCase()));
|
albums.sort((a, b) => a.artists[0].name
|
||||||
|
.toLowerCase()
|
||||||
|
.compareTo(b.artists[0].name.toLowerCase()));
|
||||||
break;
|
break;
|
||||||
case SortType.RELEASE_DATE:
|
case SortType.RELEASE_DATE:
|
||||||
albums.sort((a, b) => DateTime.parse(a.releaseDate).compareTo(DateTime.parse(b.releaseDate)));
|
albums.sort((a, b) => DateTime.parse(a.releaseDate)
|
||||||
|
.compareTo(DateTime.parse(b.releaseDate)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Reverse
|
//Reverse
|
||||||
if (_sort.reverse)
|
if (_sort.reverse) return albums.reversed.toList();
|
||||||
return albums.reversed.toList();
|
|
||||||
return albums;
|
return albums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future _load() async {
|
Future _load() async {
|
||||||
if (settings.offlineMode) return;
|
if (settings.offlineMode) return;
|
||||||
try {
|
try {
|
||||||
|
|
@ -577,8 +579,7 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
_load();
|
_load();
|
||||||
//Load sorting
|
//Load sorting
|
||||||
int index = Sorting.index(SortSourceTypes.ALBUMS);
|
int index = Sorting.index(SortSourceTypes.ALBUMS);
|
||||||
if (index != null)
|
if (index != null) _sort = cache.sorts[index];
|
||||||
_sort = cache.sorts[index];
|
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
@ -602,7 +603,9 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
'Albums'.i18n,
|
'Albums'.i18n,
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down),
|
icon: Icon(_sort.reverse
|
||||||
|
? FontAwesome5.sort_alpha_up
|
||||||
|
: FontAwesome5.sort_alpha_down),
|
||||||
onPressed: () => _reverse(),
|
onPressed: () => _reverse(),
|
||||||
),
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
|
|
@ -647,24 +650,22 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
child: ListView(
|
child: ListView(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(height: 8.0,),
|
Container(
|
||||||
|
height: 8.0,
|
||||||
|
),
|
||||||
if (!settings.offlineMode && _albums == null)
|
if (!settings.offlineMode && _albums == null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[CircularProgressIndicator()],
|
||||||
CircularProgressIndicator()
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
|
||||||
if (_albums != null)
|
if (_albums != null)
|
||||||
...List.generate(_albums.length, (int i) {
|
...List.generate(_albums.length, (int i) {
|
||||||
Album a = _sorted[i];
|
Album a = _sorted[i];
|
||||||
return AlbumTile(
|
return AlbumTile(
|
||||||
a,
|
a,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
MaterialPageRoute(builder: (context) => AlbumDetails(a))
|
builder: (context) => AlbumDetails(a)));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onHold: () async {
|
onHold: () async {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -674,11 +675,16 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: downloadManager.getOfflineAlbums(),
|
future: downloadManager.getOfflineAlbums(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError || !snapshot.hasData || snapshot.data.length == 0) return Container(height: 0, width: 0,);
|
if (snapshot.hasError ||
|
||||||
|
!snapshot.hasData ||
|
||||||
|
snapshot.data.length == 0)
|
||||||
|
return Container(
|
||||||
|
height: 0,
|
||||||
|
width: 0,
|
||||||
|
);
|
||||||
|
|
||||||
List<Album> albums = snapshot.data;
|
List<Album> albums = snapshot.data;
|
||||||
return Column(
|
return Column(
|
||||||
|
|
@ -688,18 +694,15 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
'Offline albums'.i18n,
|
'Offline albums'.i18n,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold, fontSize: 24.0),
|
||||||
fontSize: 24.0
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
...List.generate(albums.length, (i) {
|
...List.generate(albums.length, (i) {
|
||||||
Album a = albums[i];
|
Album a = albums[i];
|
||||||
return AlbumTile(
|
return AlbumTile(
|
||||||
a,
|
a,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
MaterialPageRoute(builder: (context) => AlbumDetails(a))
|
builder: (context) => AlbumDetails(a)));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onHold: () async {
|
onHold: () async {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -722,14 +725,12 @@ class _LibraryAlbumsState extends State<LibraryAlbums> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LibraryArtists extends StatefulWidget {
|
class LibraryArtists extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_LibraryArtistsState createState() => _LibraryArtistsState();
|
_LibraryArtistsState createState() => _LibraryArtistsState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LibraryArtistsState extends State<LibraryArtists> {
|
class _LibraryArtistsState extends State<LibraryArtists> {
|
||||||
|
|
||||||
List<Artist> _artists;
|
List<Artist> _artists;
|
||||||
Sorting _sort = Sorting(sourceType: SortSourceTypes.ARTISTS);
|
Sorting _sort = Sorting(sourceType: SortSourceTypes.ARTISTS);
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
|
|
@ -746,12 +747,14 @@ class _LibraryArtistsState extends State<LibraryArtists> {
|
||||||
artists.sort((a, b) => b.fans - a.fans);
|
artists.sort((a, b) => b.fans - a.fans);
|
||||||
break;
|
break;
|
||||||
case SortType.ALPHABETIC:
|
case SortType.ALPHABETIC:
|
||||||
artists.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
|
artists.sort(
|
||||||
|
(a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Reverse
|
//Reverse
|
||||||
if (_sort.reverse)
|
if (_sort.reverse) return artists.reversed.toList();
|
||||||
return artists.reversed.toList();
|
|
||||||
return artists;
|
return artists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -786,13 +789,11 @@ class _LibraryArtistsState extends State<LibraryArtists> {
|
||||||
await cache.save();
|
await cache.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
//Restore sort
|
//Restore sort
|
||||||
int index = Sorting.index(SortSourceTypes.ARTISTS);
|
int index = Sorting.index(SortSourceTypes.ARTISTS);
|
||||||
if (index != null)
|
if (index != null) _sort = cache.sorts[index];
|
||||||
_sort = cache.sorts[index];
|
|
||||||
|
|
||||||
_load();
|
_load();
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -805,7 +806,9 @@ class _LibraryArtistsState extends State<LibraryArtists> {
|
||||||
'Artists'.i18n,
|
'Artists'.i18n,
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down),
|
icon: Icon(_sort.reverse
|
||||||
|
? FontAwesome5.sort_alpha_up
|
||||||
|
: FontAwesome5.sort_alpha_down),
|
||||||
onPressed: () => _reverse(),
|
onPressed: () => _reverse(),
|
||||||
),
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
|
|
@ -854,19 +857,15 @@ class _LibraryArtistsState extends State<LibraryArtists> {
|
||||||
children: [CircularProgressIndicator()],
|
children: [CircularProgressIndicator()],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (_error) Center(child: ErrorScreen()),
|
||||||
if (_error)
|
|
||||||
Center(child: ErrorScreen()),
|
|
||||||
|
|
||||||
if (!_loading && !_error)
|
if (!_loading && !_error)
|
||||||
...List.generate(_artists.length, (i) {
|
...List.generate(_artists.length, (i) {
|
||||||
Artist a = _sorted[i];
|
Artist a = _sorted[i];
|
||||||
return ArtistHorizontalTile(
|
return ArtistHorizontalTile(
|
||||||
a,
|
a,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
MaterialPageRoute(builder: (context) => ArtistDetails(a))
|
builder: (context) => ArtistDetails(a)));
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -890,29 +889,33 @@ class LibraryPlaylists extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
|
|
||||||
List<Playlist> _playlists;
|
List<Playlist> _playlists;
|
||||||
Sorting _sort = Sorting(sourceType: SortSourceTypes.PLAYLISTS);
|
Sorting _sort = Sorting(sourceType: SortSourceTypes.PLAYLISTS);
|
||||||
ScrollController _scrollController = ScrollController();
|
ScrollController _scrollController = ScrollController();
|
||||||
String _filter = '';
|
String _filter = '';
|
||||||
|
|
||||||
List<Playlist> get _sorted {
|
List<Playlist> get _sorted {
|
||||||
List<Playlist> playlists = List.from(_playlists.where((p) => p.title.toLowerCase().contains(_filter.toLowerCase())));
|
List<Playlist> playlists = List.from(_playlists
|
||||||
|
.where((p) => p.title.toLowerCase().contains(_filter.toLowerCase())));
|
||||||
switch (_sort.type) {
|
switch (_sort.type) {
|
||||||
case SortType.DEFAULT:
|
case SortType.DEFAULT:
|
||||||
break;
|
break;
|
||||||
case SortType.USER:
|
case SortType.USER:
|
||||||
playlists.sort((a, b) => (a.user.name??deezerAPI.userName).toLowerCase().compareTo((b.user.name??deezerAPI.userName).toLowerCase()));
|
playlists.sort((a, b) => (a.user.name ?? deezerAPI.userName)
|
||||||
|
.toLowerCase()
|
||||||
|
.compareTo((b.user.name ?? deezerAPI.userName).toLowerCase()));
|
||||||
break;
|
break;
|
||||||
case SortType.TRACK_COUNT:
|
case SortType.TRACK_COUNT:
|
||||||
playlists.sort((a, b) => b.trackCount - a.trackCount);
|
playlists.sort((a, b) => b.trackCount - a.trackCount);
|
||||||
break;
|
break;
|
||||||
case SortType.ALPHABETIC:
|
case SortType.ALPHABETIC:
|
||||||
playlists.sort((a, b) => a.title.toLowerCase().compareTo(b.title.toLowerCase()));
|
playlists.sort(
|
||||||
|
(a, b) => a.title.toLowerCase().compareTo(b.title.toLowerCase()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_sort.reverse)
|
if (_sort.reverse) return playlists.reversed.toList();
|
||||||
return playlists.reversed.toList();
|
|
||||||
return playlists;
|
return playlists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -941,8 +944,7 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
void initState() {
|
void initState() {
|
||||||
//Restore sort
|
//Restore sort
|
||||||
int index = Sorting.index(SortSourceTypes.PLAYLISTS);
|
int index = Sorting.index(SortSourceTypes.PLAYLISTS);
|
||||||
if (index != null)
|
if (index != null) _sort = cache.sorts[index];
|
||||||
_sort = cache.sorts[index];
|
|
||||||
|
|
||||||
_load();
|
_load();
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -955,9 +957,7 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
image: ImageDetails(thumbUrl: 'assets/favorites_thumb.jpg'),
|
image: ImageDetails(thumbUrl: 'assets/favorites_thumb.jpg'),
|
||||||
tracks: [],
|
tracks: [],
|
||||||
trackCount: 1,
|
trackCount: 1,
|
||||||
duration: Duration(seconds: 0)
|
duration: Duration(seconds: 0));
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -966,7 +966,9 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
'Playlists'.i18n,
|
'Playlists'.i18n,
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(_sort.reverse ? FontAwesome5.sort_alpha_up : FontAwesome5.sort_alpha_down),
|
icon: Icon(_sort.reverse
|
||||||
|
? FontAwesome5.sort_alpha_up
|
||||||
|
: FontAwesome5.sort_alpha_down),
|
||||||
onPressed: () => _reverse(),
|
onPressed: () => _reverse(),
|
||||||
),
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
|
|
@ -1021,23 +1023,20 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
fillColor: Theme.of(context).bottomAppBarColor,
|
fillColor: Theme.of(context).bottomAppBarColor,
|
||||||
filled: true,
|
filled: true,
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.grey)
|
borderSide: BorderSide(color: Colors.grey)),
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.grey)
|
borderSide: BorderSide(color: Colors.grey)),
|
||||||
),
|
)),
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text('Create new playlist'.i18n),
|
title: Text('Create new playlist'.i18n),
|
||||||
leading: LeadingIcon(Icons.playlist_add, color: Color(0xff009a85)),
|
leading:
|
||||||
|
LeadingIcon(Icons.playlist_add, color: Color(0xff009a85)),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (settings.offlineMode) {
|
if (settings.offlineMode) {
|
||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: 'Cannot create playlists in offline mode'.i18n,
|
msg: 'Cannot create playlists in offline mode'.i18n,
|
||||||
gravity: ToastGravity.BOTTOM
|
gravity: ToastGravity.BOTTOM);
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -1060,8 +1059,8 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
favoritesPlaylist,
|
favoritesPlaylist,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
Navigator.of(context).push(MaterialPageRoute(
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
builder: (context) => PlaylistDetails(favoritesPlaylist)
|
builder: (context) =>
|
||||||
));
|
PlaylistDetails(favoritesPlaylist)));
|
||||||
},
|
},
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -1072,18 +1071,18 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
|
|
||||||
if (_playlists != null)
|
if (_playlists != null)
|
||||||
...List.generate(_sorted.length, (int i) {
|
...List.generate(_sorted.length, (int i) {
|
||||||
Playlist p = (_sorted??[])[i];
|
Playlist p = (_sorted ?? [])[i];
|
||||||
return PlaylistTile(
|
return PlaylistTile(
|
||||||
p,
|
p,
|
||||||
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
||||||
builder: (context) => PlaylistDetails(p)
|
builder: (context) => PlaylistDetails(p))),
|
||||||
)),
|
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
m.defaultPlaylistMenu(
|
m.defaultPlaylistMenu(p, onRemove: () {
|
||||||
p,
|
setState(() => _playlists.remove(p));
|
||||||
onRemove: () {setState(() => _playlists.remove(p));},
|
}, onUpdate: () {
|
||||||
onUpdate: () {_load();});
|
_load();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
@ -1091,8 +1090,16 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: downloadManager.getOfflinePlaylists(),
|
future: downloadManager.getOfflinePlaylists(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError || !snapshot.hasData) return Container(height: 0, width: 0,);
|
if (snapshot.hasError || !snapshot.hasData)
|
||||||
if (snapshot.data.length == 0) return Container(height: 0, width: 0,);
|
return Container(
|
||||||
|
height: 0,
|
||||||
|
width: 0,
|
||||||
|
);
|
||||||
|
if (snapshot.data.length == 0)
|
||||||
|
return Container(
|
||||||
|
height: 0,
|
||||||
|
width: 0,
|
||||||
|
);
|
||||||
|
|
||||||
List<Playlist> playlists = snapshot.data;
|
List<Playlist> playlists = snapshot.data;
|
||||||
return Column(
|
return Column(
|
||||||
|
|
@ -1102,17 +1109,15 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
'Offline playlists'.i18n,
|
'Offline playlists'.i18n,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 24.0,
|
fontSize: 24.0, fontWeight: FontWeight.bold),
|
||||||
fontWeight: FontWeight.bold
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
...List.generate(playlists.length, (i) {
|
...List.generate(playlists.length, (i) {
|
||||||
Playlist p = playlists[i];
|
Playlist p = playlists[i];
|
||||||
return PlaylistTile(
|
return PlaylistTile(
|
||||||
p,
|
p,
|
||||||
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
onTap: () => Navigator.of(context).push(
|
||||||
builder: (context) => PlaylistDetails(p)
|
MaterialPageRoute(
|
||||||
)),
|
builder: (context) => PlaylistDetails(p))),
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
m.defaultPlaylistMenu(p, onRemove: () {
|
m.defaultPlaylistMenu(p, onRemove: () {
|
||||||
|
|
@ -1128,7 +1133,6 @@ class _LibraryPlaylistsState extends State<LibraryPlaylists> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
@ -1162,17 +1166,17 @@ class _HistoryScreenState extends State<HistoryScreen> {
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemCount: (cache.history??[]).length,
|
itemCount: (cache.history ?? []).length,
|
||||||
itemBuilder: (BuildContext context, int i) {
|
itemBuilder: (BuildContext context, int i) {
|
||||||
Track t = cache.history[cache.history.length - i - 1];
|
Track t = cache.history[cache.history.length - i - 1];
|
||||||
return TrackTile(
|
return TrackTile(
|
||||||
t,
|
t,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
playerHelper.playFromTrackList(cache.history.reversed.toList(), t.id, QueueSource(
|
playerHelper.playFromTrackList(
|
||||||
id: null,
|
cache.history.reversed.toList(),
|
||||||
text: 'History'.i18n,
|
t.id,
|
||||||
source: 'history'
|
QueueSource(
|
||||||
));
|
id: null, text: 'History'.i18n, source: 'history'));
|
||||||
},
|
},
|
||||||
onHold: () {
|
onHold: () {
|
||||||
MenuSheet m = MenuSheet(context);
|
MenuSheet m = MenuSheet(context);
|
||||||
|
|
@ -1180,9 +1184,7 @@ class _HistoryScreenState extends State<HistoryScreen> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:freezer/main.dart';
|
import 'package:freezer/main.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -697,14 +696,14 @@ class _SleepTimerDialogState extends State<SleepTimerDialog> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Dismiss'.i18n),
|
child: Text('Dismiss'.i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (cache.sleepTimer != null)
|
if (cache.sleepTimer != null)
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Cancel current timer'.i18n),
|
child: Text('Cancel current timer'.i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
cache.sleepTimer.cancel();
|
cache.sleepTimer.cancel();
|
||||||
|
|
@ -714,7 +713,7 @@ class _SleepTimerDialogState extends State<SleepTimerDialog> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Save'.i18n),
|
child: Text('Save'.i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Duration duration = Duration(hours: hours, minutes: minutes);
|
Duration duration = Duration(hours: hours, minutes: minutes);
|
||||||
|
|
@ -891,11 +890,11 @@ class _CreatePlaylistDialogState extends State<CreatePlaylistDialog> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Cancel'.i18n),
|
child: Text('Cancel'.i18n),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text(edit ? 'Update'.i18n : 'Create'.i18n),
|
child: Text(edit ? 'Update'.i18n : 'Create'.i18n),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (edit) {
|
if (edit) {
|
||||||
|
|
|
||||||
|
|
@ -63,13 +63,15 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
||||||
if (settings.blurPlayerBackground)
|
if (settings.blurPlayerBackground)
|
||||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||||
statusBarColor: palette.dominantColor.color.withOpacity(0.25),
|
statusBarColor: palette.dominantColor.color.withOpacity(0.25),
|
||||||
systemNavigationBarColor: Color.alphaBlend(palette.dominantColor.color.withOpacity(0.25), Theme.of(context).scaffoldBackgroundColor)
|
systemNavigationBarColor: Color.alphaBlend(palette.dominantColor.color.withOpacity(0.25), Theme.of(context).scaffoldBackgroundColor),
|
||||||
|
systemNavigationBarIconBrightness: ThemeData.estimateBrightnessForColor(palette.dominantColor.color) == Brightness.light ? Brightness.dark : Brightness.light
|
||||||
));
|
));
|
||||||
|
|
||||||
//Color gradient
|
//Color gradient
|
||||||
if (!settings.blurPlayerBackground) {
|
if (!settings.blurPlayerBackground) {
|
||||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||||
statusBarColor: palette.dominantColor.color.withOpacity(0.7),
|
statusBarColor: palette.dominantColor.color.withOpacity(0.7),
|
||||||
|
statusBarIconBrightness: ThemeData.estimateBrightnessForColor(palette.dominantColor.color.withOpacity(0.7)) == Brightness.light ? Brightness.dark : Brightness.light
|
||||||
));
|
));
|
||||||
setState(() => _bgGradient = LinearGradient(
|
setState(() => _bgGradient = LinearGradient(
|
||||||
begin: Alignment.topCenter,
|
begin: Alignment.topCenter,
|
||||||
|
|
@ -425,7 +427,7 @@ class _QualityInfoWidgetState extends State<QualityInfoWidget> {
|
||||||
_load();
|
_load();
|
||||||
if (streamSubscription == null)
|
if (streamSubscription == null)
|
||||||
streamSubscription = AudioService.currentMediaItemStream.listen((event) async {
|
streamSubscription = AudioService.currentMediaItemStream.listen((event) async {
|
||||||
await _load();
|
_load();
|
||||||
});
|
});
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +441,7 @@ class _QualityInfoWidgetState extends State<QualityInfoWidget> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlatButton(
|
return TextButton(
|
||||||
child: Text(value),
|
child: Text(value),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => QualitySettings()));
|
Navigator.of(context).push(MaterialPageRoute(builder: (context) => QualitySettings()));
|
||||||
|
|
@ -641,10 +643,10 @@ class _BigAlbumArtState extends State<BigAlbumArt> {
|
||||||
//Top row containing QueueSource, queue...
|
//Top row containing QueueSource, queue...
|
||||||
class PlayerScreenTopRow extends StatelessWidget {
|
class PlayerScreenTopRow extends StatelessWidget {
|
||||||
|
|
||||||
double textSize;
|
final double textSize;
|
||||||
double iconSize;
|
final double iconSize;
|
||||||
double textWidth;
|
final double textWidth;
|
||||||
bool short;
|
final bool short;
|
||||||
PlayerScreenTopRow({this.textSize, this.iconSize, this.textWidth, this.short});
|
PlayerScreenTopRow({this.textSize, this.iconSize, this.textWidth, this.short});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import 'package:flutter/src/services/keyboard_key.dart';
|
||||||
import 'package:freezer/api/cache.dart';
|
import 'package:freezer/api/cache.dart';
|
||||||
import 'package:freezer/api/download.dart';
|
import 'package:freezer/api/download.dart';
|
||||||
import 'package:freezer/api/player.dart';
|
import 'package:freezer/api/player.dart';
|
||||||
import 'package:freezer/main.dart';
|
|
||||||
import 'package:freezer/ui/details_screens.dart';
|
import 'package:freezer/ui/details_screens.dart';
|
||||||
import 'package:freezer/ui/elements.dart';
|
import 'package:freezer/ui/elements.dart';
|
||||||
import 'package:freezer/ui/home_screen.dart';
|
import 'package:freezer/ui/home_screen.dart';
|
||||||
|
|
@ -59,7 +58,7 @@ class _SearchScreenState extends State<SearchScreen> {
|
||||||
List _suggestions = [];
|
List _suggestions = [];
|
||||||
bool _cancel = false;
|
bool _cancel = false;
|
||||||
bool _showCards = true;
|
bool _showCards = true;
|
||||||
FocusNode _focus = FocusNode();
|
//FocusNode _focus = FocusNode();
|
||||||
|
|
||||||
void _submit(BuildContext context, {String query}) async {
|
void _submit(BuildContext context, {String query}) async {
|
||||||
if (query != null) _query = query;
|
if (query != null) _query = query;
|
||||||
|
|
@ -94,7 +93,7 @@ class _SearchScreenState extends State<SearchScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load search suggestions
|
//Load search suggestions
|
||||||
Future<List<String>> _loadSuggestions() async {
|
Future<void> _loadSuggestions() async {
|
||||||
if (_query == null || _query.length < 2 || _query.startsWith('http')) return null;
|
if (_query == null || _query.length < 2 || _query.startsWith('http')) return null;
|
||||||
String q = _query;
|
String q = _query;
|
||||||
await Future.delayed(Duration(milliseconds: 300));
|
await Future.delayed(Duration(milliseconds: 300));
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:audio_service/audio_service.dart';
|
||||||
import 'package:country_pickers/country.dart';
|
import 'package:country_pickers/country.dart';
|
||||||
import 'package:country_pickers/country_picker_dialog.dart';
|
import 'package:country_pickers/country_picker_dialog.dart';
|
||||||
import 'package:filesize/filesize.dart';
|
import 'package:filesize/filesize.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
|
|
@ -23,7 +22,6 @@ import 'package:package_info/package_info.dart';
|
||||||
import 'package:path_provider_ex/path_provider_ex.dart';
|
import 'package:path_provider_ex/path_provider_ex.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:freezer/translations.i18n.dart';
|
import 'package:freezer/translations.i18n.dart';
|
||||||
import 'package:clipboard/clipboard.dart';
|
|
||||||
import 'package:scrobblenaut/scrobblenaut.dart';
|
import 'package:scrobblenaut/scrobblenaut.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
|
@ -106,7 +104,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
title: Text('Language'.i18n),
|
title: Text('Language'.i18n),
|
||||||
content: Text('Language changed, please restart Freezer to apply!'.i18n),
|
content: Text('Language changed, please restart Freezer to apply!'.i18n),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('OK'),
|
child: Text('OK'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
@ -387,7 +385,7 @@ class _FontSelectorState extends State<FontSelector> {
|
||||||
title: Text('Warning'.i18n),
|
title: Text('Warning'.i18n),
|
||||||
content: Text("This app isn't made for supporting many fonts, it can break layouts and overflow. Use at your own risk!".i18n),
|
content: Text("This app isn't made for supporting many fonts, it can break layouts and overflow. Use at your own risk!".i18n),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
setState(() => settings.font = font);
|
setState(() => settings.font = font);
|
||||||
await settings.save();
|
await settings.save();
|
||||||
|
|
@ -398,7 +396,7 @@ class _FontSelectorState extends State<FontSelector> {
|
||||||
},
|
},
|
||||||
child: Text('Apply'.i18n),
|
child: Text('Apply'.i18n),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
widget.callback();
|
widget.callback();
|
||||||
|
|
@ -739,8 +737,8 @@ class _DeezerSettingsState extends State<DeezerSettings> {
|
||||||
|
|
||||||
class FilenameTemplateDialog extends StatefulWidget {
|
class FilenameTemplateDialog extends StatefulWidget {
|
||||||
|
|
||||||
String initial;
|
final String initial;
|
||||||
Function onSave;
|
final Function onSave;
|
||||||
FilenameTemplateDialog(this.initial, this.onSave, {Key key}): super(key: key);
|
FilenameTemplateDialog(this.initial, this.onSave, {Key key}): super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -782,22 +780,22 @@ class _FilenameTemplateDialogState extends State<FilenameTemplateDialog> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Cancel'.i18n),
|
child: Text('Cancel'.i18n),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Reset'.i18n),
|
child: Text('Reset'.i18n),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_controller.value = _controller.value.copyWith(text: '%artist% - %title%');
|
_controller.value = _controller.value.copyWith(text: '%artist% - %title%');
|
||||||
_new = '%artist% - %title%';
|
_new = '%artist% - %title%';
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Clear'.i18n),
|
child: Text('Clear'.i18n),
|
||||||
onPressed: () => _controller.clear(),
|
onPressed: () => _controller.clear(),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Save'.i18n),
|
child: Text('Save'.i18n),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
widget.onSave(_new);
|
widget.onSave(_new);
|
||||||
|
|
@ -907,7 +905,7 @@ class _DownloadsSettingsState extends State<DownloadsSettings> {
|
||||||
title: Text('Warning'.i18n),
|
title: Text('Warning'.i18n),
|
||||||
content: Text('Using too many concurrent downloads on older/weaker devices might cause crashes!'.i18n),
|
content: Text('Using too many concurrent downloads on older/weaker devices might cause crashes!'.i18n),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Dismiss'.i18n),
|
child: Text('Dismiss'.i18n),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
)
|
)
|
||||||
|
|
@ -1195,7 +1193,7 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
||||||
subtitle: Text('Copy userToken/ARL Cookie for use in other apps.'.i18n),
|
subtitle: Text('Copy userToken/ARL Cookie for use in other apps.'.i18n),
|
||||||
leading: Icon(Icons.lock),
|
leading: Icon(Icons.lock),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await FlutterClipboard.copy(settings.arl);
|
Clipboard.setData(ClipboardData(text: settings.arl));
|
||||||
await Fluttertoast.showToast(
|
await Fluttertoast.showToast(
|
||||||
msg: 'Copied'.i18n,
|
msg: 'Copied'.i18n,
|
||||||
);
|
);
|
||||||
|
|
@ -1251,7 +1249,7 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
||||||
// content: Text('Due to plugin incompatibility, login using browser is unavailable without restart.'.i18n),
|
// content: Text('Due to plugin incompatibility, login using browser is unavailable without restart.'.i18n),
|
||||||
content: Text('Restart of app is required to properly log out!'.i18n),
|
content: Text('Restart of app is required to properly log out!'.i18n),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Cancel'.i18n),
|
child: Text('Cancel'.i18n),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
|
|
@ -1262,7 +1260,7 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
||||||
// Navigator.of(context).pop();
|
// Navigator.of(context).pop();
|
||||||
// },
|
// },
|
||||||
// ),
|
// ),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Log out & Exit'.i18n),
|
child: Text('Log out & Exit'.i18n),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
try {AudioService.stop();} catch (e) {}
|
try {AudioService.stop();} catch (e) {}
|
||||||
|
|
@ -1329,11 +1327,11 @@ class _LastFMLoginState extends State<LastFMLogin> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Cancel'.i18n),
|
child: Text('Cancel'.i18n),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
child: Text('Login'.i18n),
|
child: Text('Login'.i18n),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
LastFM last;
|
LastFM last;
|
||||||
|
|
@ -1398,7 +1396,6 @@ class _DirectoryPickerState extends State<DirectoryPicker> {
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.sd_card),
|
icon: Icon(Icons.sd_card),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
String path = '';
|
|
||||||
//Chose storage
|
//Chose storage
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:freezer/api/cache.dart';
|
import 'package:freezer/api/cache.dart';
|
||||||
|
|
@ -168,12 +167,12 @@ class _UpdaterScreenState extends State<UpdaterScreen> {
|
||||||
//Available download
|
//Available download
|
||||||
if (_versionDownload != null)
|
if (_versionDownload != null)
|
||||||
Column(children: [
|
Column(children: [
|
||||||
RaisedButton(
|
ElevatedButton(
|
||||||
child: Text('Download'.i18n + ' (${_versionDownload.version})'),
|
child: Text('Download'.i18n + ' (${_versionDownload.version})'),
|
||||||
onPressed: _buttonEnabled ? () {
|
onPressed: _buttonEnabled ? () {
|
||||||
setState(() => _buttonEnabled = false);
|
setState(() => _buttonEnabled = false);
|
||||||
_download();
|
_download();
|
||||||
}:null
|
} : null
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ dependencies:
|
||||||
marquee: ^1.5.2
|
marquee: ^1.5.2
|
||||||
flutter_cache_manager: ^1.4.1
|
flutter_cache_manager: ^1.4.1
|
||||||
cached_network_image: ^2.3.2+1
|
cached_network_image: ^2.3.2+1
|
||||||
clipboard: ^0.1.2+8
|
|
||||||
i18n_extension: ^4.0.0
|
i18n_extension: ^4.0.0
|
||||||
fluttericon: ^1.0.7
|
fluttericon: ^1.0.7
|
||||||
url_launcher: ^5.7.2
|
url_launcher: ^5.7.2
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue