154 lines
4.1 KiB
Dart
154 lines
4.1 KiB
Dart
|
import 'dart:async';
|
||
|
|
||
|
import 'package:audio_service/audio_service.dart';
|
||
|
import 'package:flutter/cupertino.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:freezer/api/deezer.dart';
|
||
|
import 'package:freezer/api/definitions.dart';
|
||
|
import 'package:freezer/ui/elements.dart';
|
||
|
import 'package:freezer/translations.i18n.dart';
|
||
|
import 'package:freezer/ui/error.dart';
|
||
|
|
||
|
class LyricsScreen extends StatefulWidget {
|
||
|
|
||
|
final Lyrics lyrics;
|
||
|
final String trackId;
|
||
|
|
||
|
LyricsScreen({this.lyrics, this.trackId, Key key}): super(key: key);
|
||
|
|
||
|
@override
|
||
|
_LyricsScreenState createState() => _LyricsScreenState();
|
||
|
}
|
||
|
|
||
|
class _LyricsScreenState extends State<LyricsScreen> {
|
||
|
|
||
|
Lyrics lyrics;
|
||
|
bool _loading = true;
|
||
|
bool _error = false;
|
||
|
int _currentIndex = 0;
|
||
|
int _prevIndex = 0;
|
||
|
Timer _timer;
|
||
|
ScrollController _controller = ScrollController();
|
||
|
StreamSubscription _mediaItemSub;
|
||
|
final double height = 90;
|
||
|
|
||
|
Future _load() async {
|
||
|
//Already available
|
||
|
if (this.lyrics != null) return;
|
||
|
if (widget.lyrics != null && widget.lyrics.lyrics != null && widget.lyrics.lyrics.length > 0) {
|
||
|
setState(() {
|
||
|
lyrics = widget.lyrics;
|
||
|
_loading = false;
|
||
|
_error = false;
|
||
|
});
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//Fetch
|
||
|
try {
|
||
|
Lyrics l = await deezerAPI.lyrics(widget.trackId);
|
||
|
setState(() {
|
||
|
_loading = false;
|
||
|
lyrics = l;
|
||
|
});
|
||
|
} catch (e) {
|
||
|
setState(() {
|
||
|
_error = true;
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
_load();
|
||
|
|
||
|
Timer.periodic(Duration(milliseconds: 350), (timer) {
|
||
|
_timer = timer;
|
||
|
if (_loading) return;
|
||
|
|
||
|
//Update current lyric index
|
||
|
setState(() => _currentIndex = lyrics.lyrics.lastIndexWhere((l) => l.offset <= AudioService.playbackState.currentPosition));
|
||
|
|
||
|
//Scroll to current lyric
|
||
|
if (_currentIndex <= 0) return;
|
||
|
if (_prevIndex == _currentIndex) return;
|
||
|
_prevIndex = _currentIndex;
|
||
|
_controller.animateTo(
|
||
|
//Lyric height, screen height, appbar height
|
||
|
(height * _currentIndex) - (MediaQuery.of(context).size.height / 2) + (height / 2) + 56,
|
||
|
duration: Duration(milliseconds: 250),
|
||
|
curve: Curves.ease
|
||
|
);
|
||
|
});
|
||
|
|
||
|
//Track change = exit lyrics
|
||
|
AudioService.currentMediaItemStream.listen((event) {
|
||
|
if (event.id != widget.trackId)
|
||
|
Navigator.of(context).pop();
|
||
|
});
|
||
|
|
||
|
super.initState();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void dispose() {
|
||
|
if (_timer != null)
|
||
|
_timer.cancel();
|
||
|
if (_mediaItemSub != null)
|
||
|
_mediaItemSub.cancel();
|
||
|
super.dispose();
|
||
|
}
|
||
|
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Scaffold(
|
||
|
appBar: FreezerAppBar('Lyrics'.i18n),
|
||
|
body: ListView(
|
||
|
controller: _controller,
|
||
|
children: [
|
||
|
//Shouldn't really happen, empty lyrics have own text
|
||
|
if (_error)
|
||
|
ErrorScreen(),
|
||
|
|
||
|
//Loading
|
||
|
if (_loading)
|
||
|
Padding(
|
||
|
padding: EdgeInsets.all(8.0),
|
||
|
child: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||
|
children: [
|
||
|
CircularProgressIndicator()
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
|
||
|
if (lyrics != null)
|
||
|
...List.generate(lyrics.lyrics.length, (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: Center(
|
||
|
child: Text(
|
||
|
lyrics.lyrics[i].text,
|
||
|
textAlign: TextAlign.center,
|
||
|
style: TextStyle(
|
||
|
fontSize: 26.0,
|
||
|
fontWeight: (_currentIndex == i) ? FontWeight.bold : FontWeight.normal
|
||
|
),
|
||
|
),
|
||
|
)
|
||
|
)
|
||
|
);
|
||
|
}),
|
||
|
],
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}
|