Media player controls improvements

This commit is contained in:
estevez-dev
2019-09-15 10:39:08 +03:00
parent b8b92171a8
commit 6707201e23
5 changed files with 181 additions and 180 deletions

View File

@ -0,0 +1,53 @@
part of '../../../main.dart';
class MediaPlayerProgressBar extends StatefulWidget {
@override
_MediaPlayerProgressBarState createState() => _MediaPlayerProgressBarState();
}
class _MediaPlayerProgressBarState extends State<MediaPlayerProgressBar> {
Timer _timer;
@override
initState() {
super.initState();
_timer = Timer.periodic(Duration(seconds: 1), (_) {
setState(() {
});
});
}
@override
Widget build(BuildContext context) {
final EntityModel entityModel = EntityModel.of(context);
final MediaPlayerEntity entity = entityModel.entityWrapper.entity;
double progress;
DateTime lastUpdated = DateTime.tryParse("${entity.attributes["media_position_updated_at"]}")?.toLocal();
if (lastUpdated != null) {
Duration duration = Duration(seconds: entity._getIntAttributeValue("media_duration") ?? 1);
Duration position = Duration(seconds: entity._getIntAttributeValue("media_position") ?? 0);
int currentPosition = position.inSeconds;
int differenceInSeconds = DateTime
.now()
.difference(lastUpdated)
.inSeconds;
currentPosition = currentPosition + differenceInSeconds;
progress = (currentPosition <= duration.inSeconds) ? currentPosition / duration.inSeconds : 100;
} else {
progress = 0;
}
return LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black45,
valueColor: AlwaysStoppedAnimation<Color>(EntityColor.stateColor(EntityState.on)),
);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}

View File

@ -0,0 +1,114 @@
part of '../../../main.dart';
class MediaPlayerSeekBar extends StatefulWidget {
@override
_MediaPlayerSeekBarState createState() => _MediaPlayerSeekBarState();
}
class _MediaPlayerSeekBarState extends State<MediaPlayerSeekBar> {
Timer _timer;
bool _seekStarted = false;
bool _changedHere = false;
double _currentPosition = 0;
final TextStyle _seekTextStyle = TextStyle(
fontSize: 20,
color: Colors.blue,
fontWeight: FontWeight.bold
);
@override
initState() {
super.initState();
_timer = Timer.periodic(Duration(seconds: 1), (_) {
if (!_seekStarted && !_changedHere) {
setState(() {});
}
});
}
@override
Widget build(BuildContext context) {
final EntityModel entityModel = EntityModel.of(context);
final MediaPlayerEntity entity = entityModel.entityWrapper.entity;
DateTime lastUpdated = DateTime.tryParse("${
entity.attributes["media_position_updated_at"]}")?.toLocal();
if (lastUpdated != null) {
Duration duration = Duration(
seconds: entity._getIntAttributeValue("media_duration") ?? 1);
Duration position = Duration(
seconds: entity._getIntAttributeValue("media_position") ?? 0);
if (entity.state == EntityState.playing && !_seekStarted &&
!_changedHere) {
_currentPosition = position.inSeconds.toDouble();
int differenceInSeconds = DateTime
.now()
.difference(lastUpdated)
.inSeconds;
_currentPosition = (_currentPosition <= duration.inSeconds) ? _currentPosition + differenceInSeconds : duration.inSeconds;
} else if (_changedHere) {
_changedHere = false;
}
return Padding(
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, 20, Sizes.rightWidgetPadding, 0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text("00:00"),
Expanded(
child: Text("${Duration(seconds: _currentPosition.toInt()).toString().split(".")[0]}",textAlign: TextAlign.center, style: _seekTextStyle),
),
Text("${duration.toString().split(".")[0]}")
],
),
Container(height: 10,),
Slider(
min: 0,
activeColor: Colors.amber,
inactiveColor: Colors.black26,
max: duration.inSeconds.toDouble(),
value: _currentPosition,
onChangeStart: (val) {
_seekStarted = true;
},
onChanged: (val) {
setState(() {
_currentPosition = val;
});
},
onChangeEnd: (val) {
_seekStarted = false;
Timer(Duration(milliseconds: 500), () {
if (!_seekStarted) {
eventBus.fire(ServiceCallEvent(
"media_player",
"media_seek",
"${entity.entityId}",
{"seek_position": val}
));
setState(() {
_changedHere = true;
_currentPosition = val;
});
}
});
},
)
],
),
);
} else {
return Container(width: 0, height: 0,);
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}

View File

@ -26,7 +26,7 @@ class MediaPlayerWidget extends StatelessWidget {
bottom: 0.0,
left: 0.0,
right: 0.0,
child: MediaPlayerProgressWidget()
child: MediaPlayerProgressBar()
)
],
),
@ -306,9 +306,9 @@ class _MediaPlayerControlsState extends State<MediaPlayerControls> {
];
if (entity.state != EntityState.off && entity.state != EntityState.unknown && entity.state != EntityState.unavailable) {
if (entity.supportSeek) {
children.add(MediaPlayerSeekWidget());
children.add(MediaPlayerSeekBar());
} else {
children.add(MediaPlayerProgressWidget());
children.add(MediaPlayerProgressBar());
}
Widget muteWidget;
Widget volumeStepWidget;
@ -410,173 +410,4 @@ class _MediaPlayerControlsState extends State<MediaPlayerControls> {
);
}
}
class MediaPlayerProgressWidget extends StatefulWidget {
@override
_MediaPlayerProgressWidgetState createState() => _MediaPlayerProgressWidgetState();
}
class _MediaPlayerProgressWidgetState extends State<MediaPlayerProgressWidget> {
Timer _timer;
@override
Widget build(BuildContext context) {
final EntityModel entityModel = EntityModel.of(context);
final MediaPlayerEntity entity = entityModel.entityWrapper.entity;
double progress;
try {
DateTime lastUpdated = DateTime.parse(
entity.attributes["media_position_updated_at"]).toLocal();
Duration duration = Duration(seconds: entity._getIntAttributeValue("media_duration") ?? 1);
Duration position = Duration(seconds: entity._getIntAttributeValue("media_position") ?? 0);
int currentPosition = position.inSeconds;
if (entity.state == EntityState.playing) {
_timer?.cancel();
_timer = Timer(Duration(seconds: 1), () {
setState(() {
});
});
int differenceInSeconds = DateTime
.now()
.difference(lastUpdated)
.inSeconds;
currentPosition = currentPosition + differenceInSeconds;
} else {
_timer?.cancel();
}
progress = currentPosition / duration.inSeconds;
return LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black45,
valueColor: AlwaysStoppedAnimation<Color>(EntityColor.stateColor(EntityState.on)),
);
} catch (e) {
_timer?.cancel();
progress = 0.0;
}
return LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black45,
);
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}
class MediaPlayerSeekWidget extends StatefulWidget {
@override
_MediaPlayerSeekWidgetState createState() => _MediaPlayerSeekWidgetState();
}
class _MediaPlayerSeekWidgetState extends State<MediaPlayerSeekWidget> {
Timer _timer;
bool _seekStarted = false;
double _currentPosition = 0;
final TextStyle _seekTextStyle = TextStyle(
fontSize: 20,
color: Colors.blue,
fontWeight: FontWeight.bold
);
@override
Widget build(BuildContext context) {
final EntityModel entityModel = EntityModel.of(context);
final MediaPlayerEntity entity = entityModel.entityWrapper.entity;
//double progress;
try {
DateTime lastUpdated = DateTime.parse(
entity.attributes["media_position_updated_at"]).toLocal();
Duration duration = Duration(seconds: entity._getIntAttributeValue("media_duration") ?? 1);
Duration position = Duration(seconds: entity._getIntAttributeValue("media_position") ?? 0);
if (entity.state == EntityState.playing && !_seekStarted) {
_currentPosition = position.inSeconds.toDouble();
_timer?.cancel();
_timer = Timer(Duration(seconds: 1), () {
if (!_seekStarted) {
setState(() {
});
}
});
int differenceInSeconds = DateTime
.now()
.difference(lastUpdated)
.inSeconds;
_currentPosition += differenceInSeconds;
} else {
_timer?.cancel();
}
//progress = currentPosition / duration.inSeconds;
return Padding(
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, 20, Sizes.rightWidgetPadding, 0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text("00:00"),
Expanded(
child: Text("${Duration(seconds: _currentPosition.toInt()).toString().split(".")[0]}",textAlign: TextAlign.center, style: _seekTextStyle),
),
Text("${duration.toString().split(".")[0]}")
],
),
Slider(
min: 0,
activeColor: Colors.amber,
inactiveColor: Colors.black26,
max: duration.inSeconds.toDouble(),
value: _currentPosition,
onChangeStart: (val) {
_seekStarted = true;
setState(() {
_currentPosition = val;
});
},
onChanged: (val) {
setState(() {
_currentPosition = val;
});
},
onChangeEnd: (val) {
_seekStarted = false;
eventBus.fire(ServiceCallEvent(
"media_player",
"media_seek",
"${entity.entityId}",
{"seek_position": val}
));
setState(() {
_currentPosition = val;
});
},
)
],
),
);
} catch (e) {
_timer?.cancel();
//progress = 0.0;
}
return Container(width: 0, height: 0,);
/*return LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black45,
);*/
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}

View File

@ -126,6 +126,8 @@ part 'cards/widgets/gauge_card_body.dart';
part 'cards/widgets/light_card_body.dart';
part 'pages/play_media.page.dart';
part 'entities/entity_page_layout.widget.dart';
part 'entities/media_player/widgets/media_player_seek_bar.widget.dart';
part 'entities/media_player/widgets/media_player_progress_bar.widget.dart';
EventBus eventBus = new EventBus();
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

View File

@ -681,21 +681,22 @@ class _MainPageState extends ReceiveShareState<MainPage> with WidgetsBindingObse
}
if (playersCount > 0) {
mediaMenuIcon = Stack(
overflow: Overflow.visible,
children: <Widget>[
Icon(MaterialDesignIcons.getIconDataFromIconName(
"mdi:television"), color: Colors.white,),
Positioned(
bottom: 0,
right: 0,
bottom: -4,
right: -4,
child: Container(
height: 14,
width: 14,
height: 16,
width: 16,
decoration: new BoxDecoration(
color: Colors.amber,
color: Colors.orange,
shape: BoxShape.circle,
),
child: Center(
child: Text("$playersCount", style: TextStyle(fontSize: 10)),
child: Text("$playersCount", style: TextStyle(fontSize: 12)),
),
),
)
@ -768,7 +769,7 @@ class _MainPageState extends ReceiveShareState<MainPage> with WidgetsBindingObse
icon: mediaMenuIcon,
onPressed: () {
showMenu(
position: RelativeRect.fromLTRB(MediaQuery.of(context).size.width, 70.0, 0.0, 0.0),
position: RelativeRect.fromLTRB(MediaQuery.of(context).size.width, 100.0, 50, 0.0),
context: context,
items: mediaMenuItems
).then((String val) {
@ -785,7 +786,7 @@ class _MainPageState extends ReceiveShareState<MainPage> with WidgetsBindingObse
"mdi:dots-vertical"), color: Colors.white,),
onPressed: () {
showMenu(
position: RelativeRect.fromLTRB(MediaQuery.of(context).size.width, 70.0, 0.0, 0.0),
position: RelativeRect.fromLTRB(MediaQuery.of(context).size.width, 100, 0.0, 0.0),
context: context,
items: serviceMenuItems
).then((String val) {