Update sleep timer picker UI.
This commit is contained in:
parent
d3d21f28e3
commit
b25093583a
|
@ -3,7 +3,6 @@ import 'dart:math' as math;
|
|||
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_time_picker_spinner/flutter_time_picker_spinner.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
import 'package:marquee/marquee.dart';
|
||||
|
@ -23,7 +22,6 @@ import '../util/pageroute.dart';
|
|||
import '../widgets/audiopanel.dart';
|
||||
import '../widgets/custom_slider.dart';
|
||||
import '../widgets/custom_widget.dart';
|
||||
import 'playlist.dart';
|
||||
|
||||
final List<BoxShadow> _customShadow = [
|
||||
BoxShadow(blurRadius: 26, offset: Offset(-6, -6), color: Colors.white),
|
||||
|
@ -232,7 +230,8 @@ class PlayerWidget extends StatelessWidget {
|
|||
return Center();
|
||||
} else {
|
||||
var minHeight = kMinPlayerHeight[data.item2.index];
|
||||
var maxHeight = kMaxPlayerHeight[data.item2.index];
|
||||
var maxHeight = math.min(kMaxPlayerHeight[data.item2.index] as double,
|
||||
context.height - 20);
|
||||
return AudioPanel(
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
|
@ -422,191 +421,195 @@ class _PlaylistWidgetState extends State<PlaylistWidget> {
|
|||
return Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: data.item1.name == 'Queue'
|
||||
? AnimatedList(
|
||||
key: miniPlaylistKey,
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.vertical,
|
||||
initialItemCount: episodes.length,
|
||||
itemBuilder: (context, index, animation) =>
|
||||
ScaleTransition(
|
||||
alignment: Alignment.center,
|
||||
scale: animation,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
audio.episodeLoad(episodes[index]);
|
||||
miniPlaylistKey.currentState
|
||||
.removeItem(
|
||||
index,
|
||||
(context, animation) =>
|
||||
Center());
|
||||
},
|
||||
child: Container(
|
||||
height: 60,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.all(
|
||||
Radius.circular(
|
||||
15.0)),
|
||||
child: Container(
|
||||
height: 30.0,
|
||||
width: 30.0,
|
||||
child: Image.file(File(
|
||||
"${episodes[index].imagePath}"))),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment:
|
||||
Alignment.centerLeft,
|
||||
child: Text(
|
||||
episodes[index].title,
|
||||
maxLines: 1,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20.0),
|
||||
child: Material(
|
||||
borderRadius:
|
||||
BorderRadius.circular(100),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: context.primaryColor,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(15.0)),
|
||||
onTap: () async {
|
||||
var episdoe =
|
||||
episodes.removeAt(index);
|
||||
episodes.insert(0, episdoe);
|
||||
miniPlaylistKey.currentState
|
||||
.removeItem(
|
||||
index,
|
||||
(context, animation) {
|
||||
return Center();
|
||||
},
|
||||
duration: Duration.zero,
|
||||
);
|
||||
miniPlaylistKey.currentState
|
||||
.insertItem(
|
||||
0,
|
||||
duration: Duration(
|
||||
milliseconds: 100));
|
||||
await Future.delayed(
|
||||
Duration(milliseconds: 100));
|
||||
await audio.moveToTop(
|
||||
data.item1.episodes[index + 1]);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 30.0,
|
||||
width: 30.0,
|
||||
child: Transform.rotate(
|
||||
angle: math.pi,
|
||||
child: Icon(
|
||||
LineIcons.download_solid,
|
||||
size: 20.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Divider(height: 1),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: episodes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final isPlaying = episodes[index] != null &&
|
||||
episodes[index] == data.item2;
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
if (!isPlaying) {
|
||||
await context
|
||||
.read<AudioPlayerNotifier>()
|
||||
.loadEpisodeFromPlaylist(episodes[index]);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: isPlaying
|
||||
? context.accentColor
|
||||
: Colors.transparent,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(15.0)),
|
||||
child: Container(
|
||||
height: 30.0,
|
||||
width: 30.0,
|
||||
child: Image.file(File(
|
||||
"${episodes[index].imagePath}"))),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
episodes[index].title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isPlaying)
|
||||
Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: 10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: WaveLoader(
|
||||
color: context.primaryColor)),
|
||||
],
|
||||
child:
|
||||
// data.item1.name == 'Queue'
|
||||
// ? AnimatedList(
|
||||
// key: miniPlaylistKey,
|
||||
// shrinkWrap: true,
|
||||
// scrollDirection: Axis.vertical,
|
||||
// initialItemCount: episodes.length,
|
||||
// itemBuilder: (context, index, animation) =>
|
||||
// ScaleTransition(
|
||||
// alignment: Alignment.center,
|
||||
// scale: animation,
|
||||
// child: Column(
|
||||
// children: <Widget>[
|
||||
// Row(
|
||||
// children: <Widget>[
|
||||
// Expanded(
|
||||
// child: Material(
|
||||
// color: Colors.transparent,
|
||||
// child: InkWell(
|
||||
// onTap: () {
|
||||
// audio.episodeLoad(episodes[index]);
|
||||
// miniPlaylistKey.currentState
|
||||
// .removeItem(
|
||||
// index,
|
||||
// (context, animation) =>
|
||||
// Center());
|
||||
// },
|
||||
// child: Container(
|
||||
// height: 60,
|
||||
// padding: EdgeInsets.symmetric(
|
||||
// horizontal: 20),
|
||||
// alignment: Alignment.centerLeft,
|
||||
// child: Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.center,
|
||||
// crossAxisAlignment:
|
||||
// CrossAxisAlignment.center,
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: <Widget>[
|
||||
// Container(
|
||||
// padding: EdgeInsets.all(10.0),
|
||||
// child: ClipRRect(
|
||||
// borderRadius:
|
||||
// BorderRadius.all(
|
||||
// Radius.circular(
|
||||
// 15.0)),
|
||||
// child: Container(
|
||||
// height: 30.0,
|
||||
// width: 30.0,
|
||||
// child: Image.file(File(
|
||||
// "${episodes[index].imagePath}"))),
|
||||
// ),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: Align(
|
||||
// alignment:
|
||||
// Alignment.centerLeft,
|
||||
// child: Text(
|
||||
// episodes[index].title,
|
||||
// maxLines: 1,
|
||||
// overflow:
|
||||
// TextOverflow.ellipsis,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// horizontal: 20.0),
|
||||
// child: Material(
|
||||
// borderRadius:
|
||||
// BorderRadius.circular(100),
|
||||
// clipBehavior: Clip.hardEdge,
|
||||
// color: context.primaryColor,
|
||||
// child: InkWell(
|
||||
// borderRadius: BorderRadius.all(
|
||||
// Radius.circular(15.0)),
|
||||
// onTap: () async {
|
||||
// var episdoe =
|
||||
// episodes.removeAt(index);
|
||||
// episodes.insert(0, episdoe);
|
||||
// miniPlaylistKey.currentState
|
||||
// .removeItem(
|
||||
// index,
|
||||
// (context, animation) {
|
||||
// return Center();
|
||||
// },
|
||||
// duration: Duration.zero,
|
||||
// );
|
||||
// miniPlaylistKey.currentState
|
||||
// .insertItem(
|
||||
// 0,
|
||||
// duration: Duration(
|
||||
// milliseconds: 100));
|
||||
// await Future.delayed(
|
||||
// Duration(milliseconds: 100));
|
||||
// await audio.moveToTop(
|
||||
// data.item1.episodes[index + 1]);
|
||||
// },
|
||||
// child: SizedBox(
|
||||
// height: 30.0,
|
||||
// width: 30.0,
|
||||
// child: Transform.rotate(
|
||||
// angle: math.pi,
|
||||
// child: Icon(
|
||||
// LineIcons.download_solid,
|
||||
// size: 20.0,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// Divider(height: 1),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
ListView.builder(
|
||||
itemCount: episodes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final isPlaying = episodes[index] != null &&
|
||||
episodes[index] == data.item2;
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
if (!isPlaying) {
|
||||
if (data.item1.name == 'Queue')
|
||||
audio.episodeLoad(episodes[index]);
|
||||
else
|
||||
await context
|
||||
.read<AudioPlayerNotifier>()
|
||||
.loadEpisodeFromPlaylist(episodes[index]);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color: isPlaying
|
||||
? context.accentColor
|
||||
: Colors.transparent,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(15.0)),
|
||||
child: Container(
|
||||
height: 30.0,
|
||||
width: 30.0,
|
||||
child: Image.file(File(
|
||||
"${episodes[index].imagePath}"))),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
episodes[index].title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isPlaying)
|
||||
Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
margin:
|
||||
EdgeInsets.symmetric(horizontal: 10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: WaveLoader(
|
||||
color: context.primaryColor)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 60.0,
|
||||
|
|
|
@ -1280,3 +1280,115 @@ Widget episodeTag(String text, Color color) {
|
|||
child: Text(text, style: TextStyle(fontSize: 14.0, color: Colors.black)),
|
||||
);
|
||||
}
|
||||
|
||||
// Sleep time picker.
|
||||
class SleepTimerPicker extends StatefulWidget {
|
||||
final ValueChanged<Duration> onChange;
|
||||
SleepTimerPicker({this.onChange, Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SleepTimerPickerState createState() => _SleepTimerPickerState();
|
||||
}
|
||||
|
||||
class _SleepTimerPickerState extends State<SleepTimerPicker> {
|
||||
final textStyle = TextStyle(fontSize: 60);
|
||||
int hour;
|
||||
int minute;
|
||||
@override
|
||||
void initState() {
|
||||
_initTimer();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
_initTimer(){
|
||||
int h = DateTime.now().hour;
|
||||
int m = DateTime.now().minute;
|
||||
if(m > 50){
|
||||
hour = (h+1) % 24;
|
||||
minute = 0;
|
||||
}
|
||||
else {
|
||||
hour = h;
|
||||
minute = m ~/10 * 10 +10;
|
||||
}
|
||||
}
|
||||
|
||||
_getDuration() {
|
||||
int h = DateTime.now().hour;
|
||||
int m = DateTime.now().minute;
|
||||
Duration d =
|
||||
Duration(hours: hour, minutes: minute) - Duration(hours: h, minutes: m);
|
||||
if (d >= Duration.zero) {
|
||||
return d;
|
||||
} else {
|
||||
return Duration(hours: 24) - d;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (hour >= 23)
|
||||
hour = 0;
|
||||
else
|
||||
hour++;
|
||||
});
|
||||
widget.onChange(_getDuration());
|
||||
},
|
||||
onLongPress: () {
|
||||
setState(() {
|
||||
hour = DateTime.now().hour;
|
||||
});
|
||||
widget.onChange(_getDuration());
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColorDark,
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
child: Text(hour.toString().padLeft(2, '0'), style: textStyle),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(
|
||||
':',
|
||||
style: textStyle,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: (() {
|
||||
setState(() {
|
||||
if (minute >= 55)
|
||||
minute = 0;
|
||||
else
|
||||
minute += 5;
|
||||
});
|
||||
widget.onChange(_getDuration());
|
||||
}),
|
||||
onLongPress: () {
|
||||
setState(() {
|
||||
minute = 0;
|
||||
});
|
||||
widget.onChange(_getDuration());
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColorDark,
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
child:
|
||||
Text(minute.toString().padLeft(2, '0'), style: textStyle),
|
||||
),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue