Add setting to change player height.
This commit is contained in:
parent
b3bd37d39e
commit
e410ac1011
|
@ -38,8 +38,10 @@ final List<BoxShadow> _customShadowNight = [
|
|||
BoxShadow(blurRadius: 8, offset: Offset(2, 2), color: Colors.black)
|
||||
];
|
||||
|
||||
const List minsToSelect = [10, 15, 20, 25, 30, 45, 60, 70, 80, 90, 99];
|
||||
const List speedToSelect = [0.5, 0.6, 0.8, 1.0, 1.2, 1.5, 2.0];
|
||||
const List kMinsToSelect = [10, 15, 20, 25, 30, 45, 60, 70, 80, 90, 99];
|
||||
const List kSpeedToSelect = [0.5, 0.6, 0.8, 1.0, 1.2, 1.5, 2.0];
|
||||
const List kMinPlayerHeight = <double>[70.0, 75.0, 80.0];
|
||||
const List kMaxPlayerHeight = <double>[300.0, 325.0, 350.0];
|
||||
|
||||
class PlayerWidget extends StatelessWidget {
|
||||
PlayerWidget({this.playerKey});
|
||||
|
@ -56,7 +58,7 @@ class PlayerWidget extends StatelessWidget {
|
|||
selector: (_, audio) =>
|
||||
Tuple2(audio.episode?.primaryColor, audio.seekSliderValue),
|
||||
builder: (_, data, __) {
|
||||
var _c = context.brightness == Brightness.light
|
||||
var c = context.brightness == Brightness.light
|
||||
? data.item1.colorizedark()
|
||||
: data.item1.colorizeLight();
|
||||
return SizedBox(
|
||||
|
@ -64,7 +66,7 @@ class PlayerWidget extends StatelessWidget {
|
|||
child: LinearProgressIndicator(
|
||||
value: data.item2,
|
||||
backgroundColor: context.primaryColor,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(_c),
|
||||
valueColor: AlwaysStoppedAnimation<Color>(c),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -214,15 +216,20 @@ class PlayerWidget extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<AudioPlayerNotifier, bool>(
|
||||
selector: (_, audio) => audio.playerRunning,
|
||||
builder: (_, playerrunning, __) {
|
||||
return !playerrunning
|
||||
return Selector<AudioPlayerNotifier, Tuple2<bool, PlayerHeight>>(
|
||||
selector: (_, audio) => Tuple2(audio.playerRunning, audio?.playerHeight),
|
||||
builder: (_, data, __) {
|
||||
var minHeight = kMinPlayerHeight[data.item2.index];
|
||||
var maxHeight = kMaxPlayerHeight[data.item2.index];
|
||||
return !data.item1
|
||||
? Center()
|
||||
: AudioPanel(
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
key: playerKey,
|
||||
miniPanel: _miniPanel(context),
|
||||
expandedPanel: ControlPanel(
|
||||
maxHeight: maxHeight,
|
||||
onExpand: () {
|
||||
playerKey.currentState.scrollToTop();
|
||||
},
|
||||
|
@ -235,14 +242,9 @@ class PlayerWidget extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class LastPosition extends StatefulWidget {
|
||||
class LastPosition extends StatelessWidget {
|
||||
LastPosition({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LastPositionState createState() => _LastPositionState();
|
||||
}
|
||||
|
||||
class _LastPositionState extends State<LastPosition> {
|
||||
Future<PlayHistory> getPosition(EpisodeBrief episode) async {
|
||||
var dbHelper = DBHelper();
|
||||
return await dbHelper.getPosition(episode);
|
||||
|
@ -255,35 +257,61 @@ class _LastPositionState extends State<LastPosition> {
|
|||
return Selector<AudioPlayerNotifier, EpisodeBrief>(
|
||||
selector: (_, audio) => audio.episode,
|
||||
builder: (context, episode, child) {
|
||||
return FutureBuilder<PlayHistory>(
|
||||
future: getPosition(episode),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasError) print(snapshot.error);
|
||||
return snapshot.hasData
|
||||
? snapshot.data.seekValue > 0.90
|
||||
? Container(
|
||||
height: 20.0,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 5),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 1, color: context.textColor),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(10.0))),
|
||||
child: Text(s.listened))
|
||||
: snapshot.data.seconds < 10
|
||||
? Center()
|
||||
: OutlineButton(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100.0),
|
||||
side: BorderSide(color: Colors.green[700])),
|
||||
highlightedBorderColor: Colors.green[700],
|
||||
onPressed: () => audio.seekTo(
|
||||
(snapshot.data.seconds * 1000).toInt()),
|
||||
child: Text(snapshot.data.seconds.toTime),
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FutureBuilder<PlayHistory>(
|
||||
future: getPosition(episode),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasError) print(snapshot.error);
|
||||
return snapshot.hasData
|
||||
? snapshot.data.seekValue > 0.90
|
||||
? Container(
|
||||
height: 20,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CustomPaint(
|
||||
painter: ListenedAllPainter(
|
||||
context.accentColor,
|
||||
stroke: 2.0),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Center();
|
||||
});
|
||||
: snapshot.data.seconds < 10
|
||||
? Center()
|
||||
: OutlineButton(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(100.0),
|
||||
side:
|
||||
BorderSide(color: Colors.green[700])),
|
||||
highlightedBorderColor: Colors.green[700],
|
||||
onPressed: () => audio.seekTo(
|
||||
(snapshot.data.seconds * 1000).toInt()),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(s.timeLastPlayed(
|
||||
snapshot.data.seconds.toTime)),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Center();
|
||||
}),
|
||||
Selector<AudioPlayerNotifier, double>(
|
||||
selector: (_, audio) => audio.switchValue,
|
||||
builder: (_, data, __) => data == 1
|
||||
? Container(
|
||||
height: 20,
|
||||
width: 40,
|
||||
child: Transform.rotate(
|
||||
angle: math.pi * 0.7,
|
||||
child: Icon(Icons.brightness_2, size: 18)))
|
||||
: Center(),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -688,7 +716,7 @@ class SleepModeState extends State<SleepMode>
|
|||
? Center()
|
||||
: Wrap(
|
||||
direction: Axis.horizontal,
|
||||
children: minsToSelect
|
||||
children: kMinsToSelect
|
||||
.map((e) => InkWell(
|
||||
onTap: () =>
|
||||
setState(() => _minSelected = e),
|
||||
|
@ -870,9 +898,11 @@ class SleepModeState extends State<SleepMode>
|
|||
}
|
||||
|
||||
class ControlPanel extends StatefulWidget {
|
||||
ControlPanel({this.onExpand, this.onClose, Key key}) : super(key: key);
|
||||
ControlPanel({this.onExpand, this.onClose, this.maxHeight, Key key})
|
||||
: super(key: key);
|
||||
final VoidCallback onExpand;
|
||||
final VoidCallback onClose;
|
||||
final double maxHeight;
|
||||
@override
|
||||
_ControlPanelState createState() => _ControlPanelState();
|
||||
}
|
||||
|
@ -935,7 +965,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
var maxHeight = constraints.maxHeight;
|
||||
var height = constraints.maxHeight;
|
||||
return Container(
|
||||
color: context.primaryColor,
|
||||
height: 300,
|
||||
|
@ -954,10 +984,10 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
EdgeInsets.only(top: 20, left: 10, right: 10),
|
||||
child: SliderTheme(
|
||||
data: SliderTheme.of(context).copyWith(
|
||||
activeTrackColor: maxHeight <= 300
|
||||
activeTrackColor: height <= widget.maxHeight
|
||||
? context.accentColor.withAlpha(70)
|
||||
: Colors.transparent,
|
||||
inactiveTrackColor: maxHeight > 300
|
||||
inactiveTrackColor: height > widget.maxHeight
|
||||
? Colors.transparent
|
||||
: context.primaryColorDark,
|
||||
trackHeight: 8.0,
|
||||
|
@ -981,7 +1011,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
Container(
|
||||
height: 20.0,
|
||||
padding: EdgeInsets.symmetric(horizontal: 30.0),
|
||||
child: maxHeight > 300
|
||||
child: height > widget.maxHeight
|
||||
? Center()
|
||||
: Row(
|
||||
children: <Widget>[
|
||||
|
@ -1150,59 +1180,70 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
),
|
||||
),
|
||||
Container(
|
||||
height: 70.0,
|
||||
padding:
|
||||
EdgeInsets.only(left: 60, right: 60, bottom: 10, top: 10),
|
||||
height: 80.0,
|
||||
padding: EdgeInsets.only(left: 60, right: 60),
|
||||
alignment: Alignment.center,
|
||||
child: Selector<AudioPlayerNotifier, String>(
|
||||
selector: (_, audio) => audio.episode.title,
|
||||
builder: (_, title, __) {
|
||||
return Container(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, size) {
|
||||
var span = TextSpan(
|
||||
text: title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 20));
|
||||
var tp = TextPainter(
|
||||
text: span,
|
||||
maxLines: 1,
|
||||
textDirection: TextDirection.ltr);
|
||||
tp.layout(maxWidth: size.maxWidth);
|
||||
if (tp.didExceedMaxLines) {
|
||||
return Marquee(
|
||||
text: title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 18),
|
||||
scrollAxis: Axis.horizontal,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
blankSpace: 30.0,
|
||||
velocity: 50.0,
|
||||
pauseAfterRound: Duration.zero,
|
||||
startPadding: 30.0,
|
||||
accelerationDuration:
|
||||
Duration(milliseconds: 100),
|
||||
accelerationCurve: Curves.linear,
|
||||
decelerationDuration:
|
||||
Duration(milliseconds: 100),
|
||||
decelerationCurve: Curves.linear,
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 20),
|
||||
);
|
||||
}
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Selector<AudioPlayerNotifier, String>(
|
||||
selector: (_, audio) => audio.episode.title,
|
||||
builder: (_, title, __) {
|
||||
return Container(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, size) {
|
||||
var span = TextSpan(
|
||||
text: title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20));
|
||||
var tp = TextPainter(
|
||||
text: span,
|
||||
maxLines: 1,
|
||||
textDirection: TextDirection.ltr);
|
||||
tp.layout(maxWidth: size.maxWidth);
|
||||
if (tp.didExceedMaxLines) {
|
||||
return Marquee(
|
||||
text: title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18),
|
||||
scrollAxis: Axis.horizontal,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
blankSpace: 30.0,
|
||||
velocity: 50.0,
|
||||
pauseAfterRound: Duration.zero,
|
||||
startPadding: 30.0,
|
||||
accelerationDuration:
|
||||
Duration(milliseconds: 100),
|
||||
accelerationCurve: Curves.linear,
|
||||
decelerationDuration:
|
||||
Duration(milliseconds: 100),
|
||||
decelerationCurve: Curves.linear,
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (height <= widget.maxHeight) LastPosition()
|
||||
],
|
||||
),
|
||||
),
|
||||
if (constraints.maxHeight > 300)
|
||||
if (height > widget.maxHeight)
|
||||
SizedBox(
|
||||
height: constraints.maxHeight - 300,
|
||||
height: height - widget.maxHeight,
|
||||
child: SingleChildScrollView(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
child: SizedBox(
|
||||
|
@ -1229,7 +1270,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
if (maxHeight <= 300)
|
||||
if (height <= widget.maxHeight)
|
||||
Selector<AudioPlayerNotifier,
|
||||
Tuple3<EpisodeBrief, bool, bool>>(
|
||||
selector: (_, audio) => Tuple3(audio.episode,
|
||||
|
@ -1252,16 +1293,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
FadeRoute(
|
||||
page: EpisodeDetail(
|
||||
episodeItem: data.item1,
|
||||
heroTag: 'playpanel'))
|
||||
// PageRouteBuilder( pageBuilder: (context,
|
||||
// animation,
|
||||
// secondAnimation) =>
|
||||
// EpisodeDetail(
|
||||
// episodeItem:
|
||||
// data.item1,
|
||||
// heroTag:
|
||||
// 'playpanel'))
|
||||
);
|
||||
heroTag: 'playpanel')));
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
|
@ -1292,7 +1324,7 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
padding: EdgeInsets.all(10.0),
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: speedToSelect
|
||||
children: kSpeedToSelect
|
||||
.map<Widget>((e) => InkWell(
|
||||
onTap: () {
|
||||
if (_setSpeed == 1) {
|
||||
|
@ -1389,7 +1421,11 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
),
|
||||
if (_setSpeed == 0)
|
||||
Positioned(
|
||||
bottom: 15,
|
||||
bottom: widget.maxHeight == kMaxPlayerHeight[2]
|
||||
? 35.0
|
||||
: widget.maxHeight == kMaxPlayerHeight[1]
|
||||
? 25.0
|
||||
: 15.0,
|
||||
child: InkWell(
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
|
@ -1401,16 +1437,18 @@ class _ControlPanelState extends State<ControlPanel>
|
|||
painter: TabIndicator(
|
||||
index: _tabIndex,
|
||||
indicatorSize: 20,
|
||||
fraction: (maxHeight - 300) / 300,
|
||||
fraction:
|
||||
(height - widget.maxHeight) / 300,
|
||||
accentColor: context.accentColor,
|
||||
color: context.textColor)),
|
||||
),
|
||||
),
|
||||
onTap: widget.onExpand),
|
||||
),
|
||||
if (_setSpeed == 0 && maxHeight > 300)
|
||||
if (_setSpeed == 0 && height > widget.maxHeight)
|
||||
Transform.translate(
|
||||
offset: Offset(0, 5) * (maxHeight - 300) / 300,
|
||||
offset:
|
||||
Offset(0, 5) * (height - widget.maxHeight) / 300,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: context.width / 2 - 80),
|
||||
|
|
|
@ -33,6 +33,7 @@ const String autoSleepTimerModeKey = 'autoSleepTimerModeKey';
|
|||
const String tapToOpenPopupMenuKey = 'tapToOpenPopupMenuKey';
|
||||
const String fastForwardSecondsKey = 'fastForwardSecondsKey';
|
||||
const String rewindSecondsKey = 'rewindSecondsKey';
|
||||
const String playerHeightKey = 'playerHeightKey';
|
||||
|
||||
class KeyValueStorage {
|
||||
final String key;
|
||||
|
|
|
@ -832,11 +832,13 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
|||
],
|
||||
),
|
||||
),
|
||||
Selector<AudioPlayerNotifier, bool>(
|
||||
selector: (_, audio) => audio.playerRunning,
|
||||
Selector<AudioPlayerNotifier, Tuple2<bool, PlayerHeight>>(
|
||||
selector: (_, audio) =>
|
||||
Tuple2(audio.playerRunning, audio.playerHeight),
|
||||
builder: (_, data, __) {
|
||||
var height = kMinPlayerHeight[data.item2.index];
|
||||
return SizedBox(
|
||||
height: data ? 70.0 : 0,
|
||||
height: data.item1 ? height : 0,
|
||||
);
|
||||
}),
|
||||
],
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../class/settingstate.dart';
|
||||
import '../local_storage/key_value_storage.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../util/custom_dropdown.dart';
|
||||
import '../util/custom_widget.dart';
|
||||
import '../util/episodegrid.dart';
|
||||
import '../util/extension_helper.dart';
|
||||
|
@ -21,6 +25,23 @@ class _LayoutSettingState extends State<LayoutSetting> {
|
|||
return Layout.values[layout];
|
||||
}
|
||||
|
||||
String _getHeightString(PlayerHeight mode) {
|
||||
final s = context.s;
|
||||
switch (mode) {
|
||||
case PlayerHeight.short:
|
||||
return s.playerHeightShort;
|
||||
break;
|
||||
case PlayerHeight.mid:
|
||||
return s.playerHeightMed;
|
||||
break;
|
||||
case PlayerHeight.tall:
|
||||
return s.playerHeightTall;
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
Widget _gridOptions(BuildContext context,
|
||||
{String key,
|
||||
Layout layout,
|
||||
|
@ -130,6 +151,7 @@ class _LayoutSettingState extends State<LayoutSetting> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = context.s;
|
||||
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
|
||||
|
@ -160,55 +182,84 @@ class _LayoutSettingState extends State<LayoutSetting> {
|
|||
.bodyText1
|
||||
.copyWith(color: Theme.of(context).accentColor)),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PopupMenuSetting())),
|
||||
contentPadding: EdgeInsets.only(left: 80.0, right: 20),
|
||||
title: Text(s.settingsPopupMenu),
|
||||
subtitle: Text(s.settingsPopupMenuDes),
|
||||
),
|
||||
Divider(height: 2),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
),
|
||||
Container(
|
||||
height: 30.0,
|
||||
padding: EdgeInsets.symmetric(horizontal: 70),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(s.play,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
.copyWith(color: Theme.of(context).accentColor)),
|
||||
),
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 80.0, right: 20, bottom: 10, top: 10),
|
||||
title: Text(s.settingsPlayerHeight),
|
||||
subtitle: Text(s.settingsPlayerHeightDes),
|
||||
trailing: Selector<AudioPlayerNotifier, PlayerHeight>(
|
||||
selector: (_, audio) => audio.playerHeight,
|
||||
builder: (_, data, __) => MyDropdownButton(
|
||||
hint: Text(_getHeightString(data)),
|
||||
underline: Center(),
|
||||
elevation: 1,
|
||||
value: data.index,
|
||||
items: <int>[0, 1, 2].map<DropdownMenuItem<int>>((e) {
|
||||
return DropdownMenuItem<int>(
|
||||
value: e,
|
||||
child: Text(
|
||||
_getHeightString(PlayerHeight.values[e])));
|
||||
}).toList(),
|
||||
onChanged: (index) =>
|
||||
audio.setPlayerHeight = PlayerHeight.values[index]),
|
||||
),
|
||||
),
|
||||
Divider(height: 2),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
),
|
||||
Container(
|
||||
height: 30.0,
|
||||
padding: EdgeInsets.symmetric(horizontal: 70),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(s.settingsDefaultGrid,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
.copyWith(color: Theme.of(context).accentColor)),
|
||||
),
|
||||
ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.vertical,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PopupMenuSetting())),
|
||||
contentPadding: EdgeInsets.only(left: 80.0, right: 20),
|
||||
title: Text(s.settingsPopupMenu),
|
||||
subtitle: Text(s.settingsPopupMenuDes),
|
||||
),
|
||||
Divider(height: 2),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
),
|
||||
Container(
|
||||
height: 30.0,
|
||||
padding: EdgeInsets.symmetric(horizontal: 70),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(s.settingsDefaultGrid,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
.copyWith(
|
||||
color: Theme.of(context).accentColor)),
|
||||
),
|
||||
ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.vertical,
|
||||
children: <Widget>[
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridPodcast,
|
||||
key: podcastLayoutKey),
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridRecent,
|
||||
key: recentLayoutKey),
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridFavorite,
|
||||
key: favLayoutKey),
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridDownload,
|
||||
key: downloadLayoutKey),
|
||||
]),
|
||||
Divider(height: 2)
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridPodcast,
|
||||
key: podcastLayoutKey),
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridRecent,
|
||||
key: recentLayoutKey),
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridFavorite,
|
||||
key: favLayoutKey),
|
||||
_setDefaultGridView(context,
|
||||
text: s.settingsDefaultGridDownload,
|
||||
key: downloadLayoutKey),
|
||||
]),
|
||||
Divider(height: 2),
|
||||
],
|
||||
),
|
||||
)),
|
||||
|
|
|
@ -395,7 +395,7 @@ class PlaySetting extends StatelessWidget {
|
|||
onChanged: (value) =>
|
||||
settings.setDefaultSleepTimer = value,
|
||||
items:
|
||||
minsToSelect.map<DropdownMenuItem<int>>((e) {
|
||||
kMinsToSelect.map<DropdownMenuItem<int>>((e) {
|
||||
return DropdownMenuItem<int>(
|
||||
value: e, child: Text(s.minsCount(e)));
|
||||
}).toList()),
|
||||
|
|
|
@ -49,7 +49,7 @@ void _audioPlayerTaskEntrypoint() async {
|
|||
|
||||
/// Sleep timer mode.
|
||||
enum SleepTimerMode { endOfEpisode, timer, undefined }
|
||||
|
||||
enum PlayerHeight { short, mid, tall }
|
||||
//enum ShareStatus { generate, download, complete, undefined, error }
|
||||
|
||||
class AudioPlayerNotifier extends ChangeNotifier {
|
||||
|
@ -63,6 +63,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||
var autoSleepTimerEndStorage = KeyValueStorage(autoSleepTimerEndKey);
|
||||
var fastForwardSecondsStorage = KeyValueStorage(fastForwardSecondsKey);
|
||||
var rewindSecondsStorage = KeyValueStorage(rewindSecondsKey);
|
||||
var playerHeightStorage = KeyValueStorage(playerHeightKey);
|
||||
|
||||
/// Current playing episdoe.
|
||||
EpisodeBrief _episode;
|
||||
|
@ -139,6 +140,9 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||
//Update episode card when setting changed
|
||||
bool _episodeState = false;
|
||||
|
||||
/// Player height.
|
||||
PlayerHeight _playerHeight;
|
||||
|
||||
AudioProcessingState get audioState => _audioState;
|
||||
int get backgroundAudioDuration => _backgroundAudioDuration;
|
||||
int get backgroundAudioPosition => _backgroundAudioPosition;
|
||||
|
@ -161,6 +165,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||
bool get autoSleepTimer => _autoSleepTimer;
|
||||
int get fastForwardSeconds => _fastForwardSeconds;
|
||||
int get rewindSeconds => _rewindSeconds;
|
||||
PlayerHeight get playerHeight => _playerHeight;
|
||||
|
||||
set setSwitchValue(double value) {
|
||||
_switchValue = value;
|
||||
|
@ -172,6 +177,21 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
set setPlayerHeight(PlayerHeight mode) {
|
||||
_playerHeight = mode;
|
||||
notifyListeners();
|
||||
_savePlayerHeight();
|
||||
}
|
||||
|
||||
Future _getPlayerHeight() async {
|
||||
var index = await playerHeightStorage.getInt(defaultValue: 1);
|
||||
_playerHeight = PlayerHeight.values[index];
|
||||
}
|
||||
|
||||
Future _savePlayerHeight() async {
|
||||
await playerHeightStorage.saveInt(_playerHeight.index);
|
||||
}
|
||||
|
||||
Future _getAutoPlay() async {
|
||||
var i = await autoPlayStorage.getInt();
|
||||
_autoPlay = i == 0;
|
||||
|
@ -189,6 +209,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
|
|||
|
||||
@override
|
||||
void addListener(VoidCallback listener) async {
|
||||
await _getPlayerHeight();
|
||||
super.addListener(listener);
|
||||
_queueUpdate = false;
|
||||
await _getAutoSleepTimer();
|
||||
|
|
|
@ -53,7 +53,7 @@ class AudioPanelState extends State<AudioPanel> with TickerProviderStateMixin {
|
|||
_controller.forward();
|
||||
_slideDirection = SlideDirection.up;
|
||||
super.initState();
|
||||
_expandHeight = 600;
|
||||
_expandHeight = widget.maxHeight + 300;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -63,6 +63,16 @@ class AudioPanelState extends State<AudioPanel> with TickerProviderStateMixin {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(AudioPanel oldWidget) {
|
||||
if (oldWidget.maxHeight != widget.maxHeight) {
|
||||
setState(() {
|
||||
_expandHeight = widget.maxHeight + 300;
|
||||
});
|
||||
}
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
double _getHeight() {
|
||||
if (_animation.value >= _expandHeight) {
|
||||
return _expandHeight;
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:focused_menu/modals.dart';
|
|||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tsacdop/home/audioplayer.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../episodes/episode_detail.dart';
|
||||
|
@ -592,10 +593,11 @@ class OpenContainerWrapper extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<AudioPlayerNotifier, bool>(
|
||||
selector: (_, audio) => audio.playerRunning,
|
||||
return Selector<AudioPlayerNotifier, Tuple2<bool, PlayerHeight>>(
|
||||
selector: (_, audio) => Tuple2(audio.playerRunning, audio.playerHeight),
|
||||
builder: (_, data, __) => OpenContainer(
|
||||
playerRunning: data,
|
||||
playerRunning: data.item1,
|
||||
playerHeight: kMinPlayerHeight[data.item2.index],
|
||||
flightWidget: CircleAvatar(
|
||||
backgroundImage: FileImage(File("${episode.imagePath}")),
|
||||
),
|
||||
|
|
|
@ -73,6 +73,7 @@ class OpenContainer extends StatefulWidget {
|
|||
@required this.openBuilder,
|
||||
this.flightWidget,
|
||||
this.playerRunning,
|
||||
this.playerHeight,
|
||||
this.tappable = true,
|
||||
this.transitionDuration = const Duration(milliseconds: 300),
|
||||
this.transitionType = ContainerTransitionType.fade,
|
||||
|
@ -106,6 +107,7 @@ class OpenContainer extends StatefulWidget {
|
|||
final Color closedColor;
|
||||
final Widget flightWidget;
|
||||
final bool playerRunning;
|
||||
final double playerHeight;
|
||||
|
||||
/// Background color of the container while it is open.
|
||||
///
|
||||
|
@ -248,6 +250,7 @@ class _OpenContainerState extends State<OpenContainer> {
|
|||
transitionType: widget.transitionType,
|
||||
flightWidget: widget.flightWidget,
|
||||
playerRunning: widget.playerRunning,
|
||||
playerHeight: widget.playerHeight,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -362,6 +365,7 @@ class _OpenContainerRoute extends ModalRoute<void> {
|
|||
@required this.transitionType,
|
||||
this.flightWidget,
|
||||
this.playerRunning,
|
||||
this.playerHeight,
|
||||
}) : assert(closedColor != null),
|
||||
assert(openColor != null),
|
||||
assert(closedElevation != null),
|
||||
|
@ -391,6 +395,7 @@ class _OpenContainerRoute extends ModalRoute<void> {
|
|||
|
||||
final Widget flightWidget;
|
||||
final bool playerRunning;
|
||||
final double playerHeight;
|
||||
static _FlippableTweenSequence<Color> _getColorTween({
|
||||
@required ContainerTransitionType transitionType,
|
||||
@required Color closedColor,
|
||||
|
@ -725,7 +730,7 @@ class _OpenContainerRoute extends ModalRoute<void> {
|
|||
_positionTween.end = Offset(
|
||||
10,
|
||||
playerRunning
|
||||
? MediaQuery.of(context).size.height - 110
|
||||
? MediaQuery.of(context).size.height - 40 - playerHeight
|
||||
: MediaQuery.of(context).size.height - 40);
|
||||
|
||||
var _width = MediaQuery.of(context).size.width;
|
||||
|
@ -742,7 +747,9 @@ class _OpenContainerRoute extends ModalRoute<void> {
|
|||
child: SizedBox(
|
||||
width: rect.width,
|
||||
height: rect.height *
|
||||
(playerRunning ? (1 - 70 / context.height) : 1),
|
||||
(playerRunning
|
||||
? (1 - playerHeight / context.height)
|
||||
: 1),
|
||||
child: Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
animationDuration: Duration.zero,
|
||||
|
|
Loading…
Reference in New Issue