diff --git a/lib/entities/media_player/widgets/media_player_progress_bar.widget.dart b/lib/entities/media_player/widgets/media_player_progress_bar.widget.dart new file mode 100644 index 0000000..c2b3094 --- /dev/null +++ b/lib/entities/media_player/widgets/media_player_progress_bar.widget.dart @@ -0,0 +1,53 @@ +part of '../../../main.dart'; + +class MediaPlayerProgressBar extends StatefulWidget { + @override + _MediaPlayerProgressBarState createState() => _MediaPlayerProgressBarState(); +} + +class _MediaPlayerProgressBarState extends State { + + 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(EntityColor.stateColor(EntityState.on)), + ); + } + + @override + void dispose() { + _timer?.cancel(); + super.dispose(); + } + +} \ No newline at end of file diff --git a/lib/entities/media_player/widgets/media_player_seek_bar.widget.dart b/lib/entities/media_player/widgets/media_player_seek_bar.widget.dart new file mode 100644 index 0000000..d8d6f49 --- /dev/null +++ b/lib/entities/media_player/widgets/media_player_seek_bar.widget.dart @@ -0,0 +1,114 @@ +part of '../../../main.dart'; + +class MediaPlayerSeekBar extends StatefulWidget { + @override + _MediaPlayerSeekBarState createState() => _MediaPlayerSeekBarState(); +} + +class _MediaPlayerSeekBarState extends State { + + 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: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + 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(); + } + +} \ No newline at end of file diff --git a/lib/entities/media_player/widgets/media_player_widgets.dart b/lib/entities/media_player/widgets/media_player_widgets.dart index 50d583b..a60536e 100644 --- a/lib/entities/media_player/widgets/media_player_widgets.dart +++ b/lib/entities/media_player/widgets/media_player_widgets.dart @@ -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 { ]; 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 { ); } -} - -class MediaPlayerProgressWidget extends StatefulWidget { - @override - _MediaPlayerProgressWidgetState createState() => _MediaPlayerProgressWidgetState(); -} - -class _MediaPlayerProgressWidgetState extends State { - - 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(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 { - - 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: [ - Row( - mainAxisSize: MainAxisSize.max, - children: [ - 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(); - } - } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index eecb754..1d315cf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -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(); diff --git a/lib/pages/main.page.dart b/lib/pages/main.page.dart index 05e3aed..606df4e 100644 --- a/lib/pages/main.page.dart +++ b/lib/pages/main.page.dart @@ -681,21 +681,22 @@ class _MainPageState extends ReceiveShareState with WidgetsBindingObse } if (playersCount > 0) { mediaMenuIcon = Stack( + overflow: Overflow.visible, children: [ 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 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 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) {