lyrics wip: better visualizer

player_screen: always white statusbar icons
This commit is contained in:
pato05 2021-04-06 02:04:57 +02:00
parent 20b92334ba
commit 5edcc8648c
6 changed files with 152 additions and 141 deletions

View file

@ -20,7 +20,6 @@
<uses-feature android:name="android.software.LEANBACK" android:required="true"/> <uses-feature android:name="android.software.LEANBACK" android:required="true"/>
<application <application
android:name="io.flutter.app.FlutterApplication"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="Freezer" android:label="Freezer"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"

View file

@ -5,6 +5,7 @@ import 'package:fluttertoast/fluttertoast.dart';
import 'package:freezer/api/cache.dart'; import 'package:freezer/api/cache.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/importer.dart';
import 'package:freezer/api/player.dart'; import 'package:freezer/api/player.dart';
import 'package:freezer/settings.dart'; import 'package:freezer/settings.dart';
import 'package:freezer/ui/details_screens.dart'; import 'package:freezer/ui/details_screens.dart';
@ -18,7 +19,6 @@ import 'package:draggable_scrollbar/draggable_scrollbar.dart';
import 'menu.dart'; import 'menu.dart';
import 'settings_screen.dart'; import 'settings_screen.dart';
import '../api/spotify.dart';
import '../api/download.dart'; import '../api/download.dart';
class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget { class LibraryAppBar extends StatelessWidget implements PreferredSizeWidget {
@ -134,15 +134,45 @@ class LibraryScreen extends StatelessWidget {
leading: LeadingIcon(Icons.import_export, color: Color(0xff2ba766)), leading: LeadingIcon(Icons.import_export, color: Color(0xff2ba766)),
subtitle: Text('Import playlists from Spotify'.i18n), subtitle: Text('Import playlists from Spotify'.i18n),
onTap: () { onTap: () {
if (spotify.doneImporting != null) { //Show progress
if (importer.done || importer.busy) {
Navigator.of(context).push(MaterialPageRoute( Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CurrentlyImportingScreen())); builder: (context) => ImporterStatusScreen()));
if (spotify.doneImporting) spotify.doneImporting = null;
return; return;
} }
Navigator.of(context).push( //Pick importer dialog
MaterialPageRoute(builder: (context) => ImporterScreen())); showDialog(
context: context,
builder: (context) => SimpleDialog(
title: Text('Importer'.i18n),
children: [
ListTile(
leading: Icon(FontAwesome5.spotify),
title: Text('Spotify v1'.i18n),
subtitle: Text(
'Import Spotify playlists up to 100 tracks without any login.'
.i18n),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SpotifyImporterV1()));
},
),
ListTile(
leading: Icon(FontAwesome5.spotify),
title: Text('Spotify v2'.i18n),
subtitle: Text(
'Import any Spotify playlist, import from own Spotify library. Requires free account.'
.i18n),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SpotifyImporterV2()));
},
)
],
));
}, },
), ),
ExpansionTile( ExpansionTile(

View file

@ -150,6 +150,67 @@ class _LyricsScreenState extends State<LyricsScreen> {
: null), : null),
body: Stack( body: Stack(
children: [ children: [
//Lyrics
_error
?
//Shouldn't really happen, empty lyrics have own text
ErrorScreen()
:
// Loading lyrics
_loading
? Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [CircularProgressIndicator()],
),
)
: NotificationListener(
onNotification: (Notification notification) {
if (_freeScroll ||
notification is! ScrollStartNotification)
return false;
if (!_animatedScroll)
setState(() => _freeScroll = true);
return false;
},
child: ListView.builder(
controller: _controller,
padding: EdgeInsets.fromLTRB(
0, 0, 0, settings.lyricsVisualizer ? 100 : 0),
itemCount: lyrics.lyrics.length,
itemBuilder: (BuildContext context, int i) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: _currentIndex == i
? Colors.grey.withOpacity(0.25)
: Colors.transparent,
),
height: height,
child: InkWell(
borderRadius:
BorderRadius.circular(8.0),
onTap: lyrics.id != null
? () => AudioService.seekTo(
lyrics.lyrics[i].offset)
: null,
child: Center(
child: Text(
lyrics.lyrics[i].text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26.0,
fontWeight: (_currentIndex == i)
? FontWeight.bold
: FontWeight.normal),
),
))));
},
)),
//Visualizer //Visualizer
if (settings.lyricsVisualizer) if (settings.lyricsVisualizer)
Positioned( Positioned(
@ -160,89 +221,21 @@ class _LyricsScreenState extends State<LyricsScreen> {
stream: playerHelper.visualizerStream, stream: playerHelper.visualizerStream,
builder: (BuildContext context, AsyncSnapshot snapshot) { builder: (BuildContext context, AsyncSnapshot snapshot) {
List<double> data = snapshot.data ?? []; List<double> data = snapshot.data ?? [];
double width = double width = MediaQuery.of(context).size.width /
MediaQuery.of(context).size.width / data.length - data.length; //- 0.25;
0.25;
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate( children: List.generate(
data.length, data.length,
(i) => AnimatedContainer( (i) => AnimatedContainer(
duration: Duration(milliseconds: 130), duration: Duration(milliseconds: 130),
color: Theme.of(context).primaryColor, color: settings.primaryColor,
height: data[i] * 100, height: data[i] * 100,
width: width, width: width,
)), )),
); );
}), }),
), ),
//Lyrics
Padding(
padding: EdgeInsets.fromLTRB(
0, 0, 0, settings.lyricsVisualizer ? 100 : 0),
child: _error
?
//Shouldn't really happen, empty lyrics have own text
ErrorScreen()
:
// Loading
_loading
? Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [CircularProgressIndicator()],
),
)
: NotificationListener(
onNotification: (Notification notification) {
if (_freeScroll ||
notification is! ScrollStartNotification)
return false;
if (!_animatedScroll)
setState(() => _freeScroll = true);
return false;
},
child: ListView.builder(
controller: _controller,
itemCount: lyrics.lyrics.length,
itemBuilder: (BuildContext context, int i) {
return Padding(
padding:
EdgeInsets.symmetric(horizontal: 8.0),
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(8.0),
color: _currentIndex == i
? Colors.grey.withOpacity(0.25)
: Colors.transparent,
),
height: height,
child: InkWell(
borderRadius:
BorderRadius.circular(8.0),
onTap: lyrics.id != null
? () => AudioService.seekTo(
lyrics.lyrics[i].offset)
: null,
child: Center(
child: Text(
lyrics.lyrics[i].text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 26.0,
fontWeight:
(_currentIndex == i)
? FontWeight.bold
: FontWeight.normal),
),
))));
},
)),
)
], ],
)); ));
} }

View file

@ -70,22 +70,13 @@ class _PlayerScreenState extends State<PlayerScreen> {
systemNavigationBarColor: Color.alphaBlend( systemNavigationBarColor: Color.alphaBlend(
palette.dominantColor.color.withOpacity(0.25), palette.dominantColor.color.withOpacity(0.25),
Theme.of(context).scaffoldBackgroundColor), Theme.of(context).scaffoldBackgroundColor),
systemNavigationBarIconBrightness: systemNavigationBarIconBrightness: Brightness.dark));
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( statusBarIconBrightness: Brightness.dark));
palette.dominantColor.color.withOpacity(0.7)) ==
Brightness.light
? Brightness.dark
: Brightness.light));
setState(() => _bgGradient = LinearGradient( setState(() => _bgGradient = LinearGradient(
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,

View file

@ -1362,9 +1362,9 @@ class _DirectoryPickerState extends State<DirectoryPicker> {
), ),
); );
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: List<Widget>.generate(
...List.generate(snapshot.data.length, (i) { snapshot.data.length, (int i) {
StorageInfo si = snapshot.data[i]; StorageInfo si = snapshot.data[i];
return ListTile( return ListTile(
title: Text(si.rootDir), title: Text(si.rootDir),
@ -1381,9 +1381,7 @@ class _DirectoryPickerState extends State<DirectoryPicker> {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
); );
}) }));
],
);
}, },
), ),
); );

View file

@ -63,14 +63,14 @@ packages:
name: build_config name: build_config
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.5" version: "0.4.6"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.7" version: "2.1.10"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
@ -84,28 +84,28 @@ packages:
name: build_runner name: build_runner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.11.1" version: "1.11.5"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.7" version: "6.1.10"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
name: built_collection name: built_collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.3.2" version: "5.0.0"
built_value: built_value:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "7.1.0" version: "8.0.4"
cached_network_image: cached_network_image:
dependency: "direct main" dependency: "direct main"
description: description:
@ -140,7 +140,7 @@ packages:
name: cli_util name: cli_util
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0" version: "0.3.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -154,7 +154,7 @@ packages:
name: code_builder name: code_builder
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.6.0" version: "3.7.0"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
@ -303,7 +303,7 @@ packages:
name: ffi name: ffi
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.3" version: "1.0.0"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -324,7 +324,7 @@ packages:
name: fixnum name: fixnum
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.10.11" version: "1.0.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -364,7 +364,7 @@ packages:
name: flutter_isolate name: flutter_isolate
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0+14" version: "1.0.0+15"
flutter_local_notifications: flutter_local_notifications:
dependency: "direct main" dependency: "direct main"
description: description:
@ -435,7 +435,7 @@ packages:
name: glob name: glob
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "2.0.1"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
@ -498,7 +498,7 @@ packages:
name: infinite_listview name: infinite_listview
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1+1" version: "1.1.0"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -512,7 +512,7 @@ packages:
name: io name: io
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.4" version: "0.3.5"
js: js:
dependency: transitive dependency: transitive
description: description:
@ -561,14 +561,14 @@ packages:
name: logging name: logging
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.11.4" version: "1.0.1"
marquee: marquee:
dependency: "direct main" dependency: "direct main"
description: description:
name: marquee name: marquee
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.1" version: "1.7.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -596,21 +596,7 @@ packages:
name: move_to_background name: move_to_background
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.0.2"
node_interop:
dependency: transitive
description:
name: node_interop
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
numberpicker: numberpicker:
dependency: "direct main" dependency: "direct main"
description: description:
@ -638,7 +624,7 @@ packages:
name: open_file name: open_file
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.3" version: "3.1.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@ -708,7 +694,7 @@ packages:
name: pedantic name: pedantic
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.9.2" version: "1.11.0"
permission_handler: permission_handler:
dependency: "direct main" dependency: "direct main"
description: description:
@ -757,28 +743,28 @@ packages:
name: pool name: pool
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.0" version: "1.5.0"
process: process:
dependency: transitive dependency: transitive
description: description:
name: process name: process
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.1.0" version: "4.2.1"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.4.4" version: "2.0.0"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.7" version: "0.1.8"
quick_actions: quick_actions:
dependency: "direct main" dependency: "direct main"
description: description:
@ -813,7 +799,7 @@ packages:
name: scrobblenaut name: scrobblenaut
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.5"
share: share:
dependency: "direct main" dependency: "direct main"
description: description:
@ -834,7 +820,7 @@ packages:
name: shelf_web_socket name: shelf_web_socket
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.4" version: "0.2.4+1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -846,7 +832,7 @@ packages:
name: source_gen name: source_gen
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.10+1" version: "0.9.10+3"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@ -874,14 +860,14 @@ packages:
name: sqflite name: sqflite
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.2+3" version: "1.3.2+4"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3+1" version: "1.0.3+3"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -902,7 +888,7 @@ packages:
name: stream_transform name: stream_transform
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "2.0.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
@ -952,6 +938,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.0" version: "0.4.0"
universal_io:
dependency: transitive
description:
name: universal_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
url_launcher: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1014,7 +1007,7 @@ packages:
name: version name: version
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.3.1"
wakelock: wakelock:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1042,7 +1035,7 @@ packages:
name: watcher name: watcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.7+15" version: "1.0.0"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
@ -1070,7 +1063,14 @@ packages:
name: yaml name: yaml
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.1" version: "3.1.0"
zone_local:
dependency: transitive
description:
name: zone_local
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
sdks: sdks:
dart: ">=2.12.0 <3.0.0" dart: ">=2.12.0 <3.0.0"
flutter: ">=1.22.2" flutter: ">=1.22.2"