1
0
mirror of https://github.com/stonega/tsacdop synced 2025-02-17 20:10:37 +01:00

Update sleep timer picker UI.

This commit is contained in:
Stonegate 2021-01-01 02:08:03 +08:00
parent d3d21f28e3
commit b25093583a
2 changed files with 300 additions and 185 deletions

View File

@ -3,7 +3,6 @@ import 'dart:math' as math;
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.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:google_fonts/google_fonts.dart';
import 'package:line_icons/line_icons.dart'; import 'package:line_icons/line_icons.dart';
import 'package:marquee/marquee.dart'; import 'package:marquee/marquee.dart';
@ -23,7 +22,6 @@ import '../util/pageroute.dart';
import '../widgets/audiopanel.dart'; import '../widgets/audiopanel.dart';
import '../widgets/custom_slider.dart'; import '../widgets/custom_slider.dart';
import '../widgets/custom_widget.dart'; import '../widgets/custom_widget.dart';
import 'playlist.dart';
final List<BoxShadow> _customShadow = [ final List<BoxShadow> _customShadow = [
BoxShadow(blurRadius: 26, offset: Offset(-6, -6), color: Colors.white), BoxShadow(blurRadius: 26, offset: Offset(-6, -6), color: Colors.white),
@ -232,7 +230,8 @@ class PlayerWidget extends StatelessWidget {
return Center(); return Center();
} else { } else {
var minHeight = kMinPlayerHeight[data.item2.index]; 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( return AudioPanel(
minHeight: minHeight, minHeight: minHeight,
maxHeight: maxHeight, maxHeight: maxHeight,
@ -422,191 +421,195 @@ class _PlaylistWidgetState extends State<PlaylistWidget> {
return Column( return Column(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: data.item1.name == 'Queue' child:
? AnimatedList( // data.item1.name == 'Queue'
key: miniPlaylistKey, // ? AnimatedList(
shrinkWrap: true, // key: miniPlaylistKey,
scrollDirection: Axis.vertical, // shrinkWrap: true,
initialItemCount: episodes.length, // scrollDirection: Axis.vertical,
itemBuilder: (context, index, animation) => // initialItemCount: episodes.length,
ScaleTransition( // itemBuilder: (context, index, animation) =>
alignment: Alignment.center, // ScaleTransition(
scale: animation, // alignment: Alignment.center,
child: Column( // scale: animation,
children: <Widget>[ // child: Column(
Row( // children: <Widget>[
children: <Widget>[ // Row(
Expanded( // children: <Widget>[
child: Material( // Expanded(
color: Colors.transparent, // child: Material(
child: InkWell( // color: Colors.transparent,
onTap: () { // child: InkWell(
audio.episodeLoad(episodes[index]); // onTap: () {
miniPlaylistKey.currentState // audio.episodeLoad(episodes[index]);
.removeItem( // miniPlaylistKey.currentState
index, // .removeItem(
(context, animation) => // index,
Center()); // (context, animation) =>
}, // Center());
child: Container( // },
height: 60, // child: Container(
padding: EdgeInsets.symmetric( // height: 60,
horizontal: 20), // padding: EdgeInsets.symmetric(
alignment: Alignment.centerLeft, // horizontal: 20),
child: Row( // alignment: Alignment.centerLeft,
mainAxisAlignment: // child: Row(
MainAxisAlignment.center, // mainAxisAlignment:
crossAxisAlignment: // MainAxisAlignment.center,
CrossAxisAlignment.center, // crossAxisAlignment:
mainAxisSize: MainAxisSize.min, // CrossAxisAlignment.center,
children: <Widget>[ // mainAxisSize: MainAxisSize.min,
Container( // children: <Widget>[
padding: EdgeInsets.all(10.0), // Container(
child: ClipRRect( // padding: EdgeInsets.all(10.0),
borderRadius: // child: ClipRRect(
BorderRadius.all( // borderRadius:
Radius.circular( // BorderRadius.all(
15.0)), // Radius.circular(
child: Container( // 15.0)),
height: 30.0, // child: Container(
width: 30.0, // height: 30.0,
child: Image.file(File( // width: 30.0,
"${episodes[index].imagePath}"))), // child: Image.file(File(
), // "${episodes[index].imagePath}"))),
), // ),
Expanded( // ),
child: Align( // Expanded(
alignment: // child: Align(
Alignment.centerLeft, // alignment:
child: Text( // Alignment.centerLeft,
episodes[index].title, // child: Text(
maxLines: 1, // episodes[index].title,
overflow: // maxLines: 1,
TextOverflow.ellipsis, // overflow:
), // TextOverflow.ellipsis,
), // ),
), // ),
], // ),
), // ],
), // ),
), // ),
), // ),
), // ),
Padding( // ),
padding: const EdgeInsets.symmetric( // Padding(
horizontal: 20.0), // padding: const EdgeInsets.symmetric(
child: Material( // horizontal: 20.0),
borderRadius: // child: Material(
BorderRadius.circular(100), // borderRadius:
clipBehavior: Clip.hardEdge, // BorderRadius.circular(100),
color: context.primaryColor, // clipBehavior: Clip.hardEdge,
child: InkWell( // color: context.primaryColor,
borderRadius: BorderRadius.all( // child: InkWell(
Radius.circular(15.0)), // borderRadius: BorderRadius.all(
onTap: () async { // Radius.circular(15.0)),
var episdoe = // onTap: () async {
episodes.removeAt(index); // var episdoe =
episodes.insert(0, episdoe); // episodes.removeAt(index);
miniPlaylistKey.currentState // episodes.insert(0, episdoe);
.removeItem( // miniPlaylistKey.currentState
index, // .removeItem(
(context, animation) { // index,
return Center(); // (context, animation) {
}, // return Center();
duration: Duration.zero, // },
); // duration: Duration.zero,
miniPlaylistKey.currentState // );
.insertItem( // miniPlaylistKey.currentState
0, // .insertItem(
duration: Duration( // 0,
milliseconds: 100)); // duration: Duration(
await Future.delayed( // milliseconds: 100));
Duration(milliseconds: 100)); // await Future.delayed(
await audio.moveToTop( // Duration(milliseconds: 100));
data.item1.episodes[index + 1]); // await audio.moveToTop(
}, // data.item1.episodes[index + 1]);
child: SizedBox( // },
height: 30.0, // child: SizedBox(
width: 30.0, // height: 30.0,
child: Transform.rotate( // width: 30.0,
angle: math.pi, // child: Transform.rotate(
child: Icon( // angle: math.pi,
LineIcons.download_solid, // child: Icon(
size: 20.0, // LineIcons.download_solid,
), // size: 20.0,
), // ),
), // ),
), // ),
), // ),
), // ),
], // ),
), // ],
Divider(height: 1), // ),
], // Divider(height: 1),
), // ],
), // ),
) // ),
: ListView.builder( // )
itemCount: episodes.length, ListView.builder(
itemBuilder: (context, index) { itemCount: episodes.length,
final isPlaying = episodes[index] != null && itemBuilder: (context, index) {
episodes[index] == data.item2; final isPlaying = episodes[index] != null &&
return InkWell( episodes[index] == data.item2;
onTap: () async { return InkWell(
if (!isPlaying) { onTap: () async {
await context if (!isPlaying) {
.read<AudioPlayerNotifier>() if (data.item1.name == 'Queue')
.loadEpisodeFromPlaylist(episodes[index]); audio.episodeLoad(episodes[index]);
} else
}, await context
child: Container( .read<AudioPlayerNotifier>()
color: isPlaying .loadEpisodeFromPlaylist(episodes[index]);
? context.accentColor }
: Colors.transparent, },
child: Row( child: Container(
mainAxisAlignment: MainAxisAlignment.center, color: isPlaying
crossAxisAlignment: CrossAxisAlignment.center, ? context.accentColor
mainAxisSize: MainAxisSize.min, : Colors.transparent,
children: <Widget>[ child: Row(
Container( mainAxisAlignment: MainAxisAlignment.center,
padding: EdgeInsets.all(10.0), crossAxisAlignment: CrossAxisAlignment.center,
child: ClipRRect( mainAxisSize: MainAxisSize.min,
borderRadius: BorderRadius.all( children: <Widget>[
Radius.circular(15.0)), Container(
child: Container( padding: EdgeInsets.all(10.0),
height: 30.0, child: ClipRRect(
width: 30.0, borderRadius:
child: Image.file(File( BorderRadius.all(Radius.circular(15.0)),
"${episodes[index].imagePath}"))), child: Container(
), height: 30.0,
), width: 30.0,
Expanded( child: Image.file(File(
child: Align( "${episodes[index].imagePath}"))),
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)),
],
), ),
), ),
); 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( SizedBox(
height: 60.0, height: 60.0,

View File

@ -1280,3 +1280,115 @@ Widget episodeTag(String text, Color color) {
child: Text(text, style: TextStyle(fontSize: 14.0, color: Colors.black)), 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),
),
),
],
));
}
}