mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 12:26:35 +00:00
Support for showing playback progress in media_player (#150)
* Added support for showing playback progress in media_player. * Small bugfix. * Playback progress now updates without needed state transitions in HA. * media_position_update_at property is now a datetime. * Linting fixes + removed _internal polymer property + cleanup * More linting.
This commit is contained in:
parent
9184aaf33f
commit
4d7e1fef75
@ -100,6 +100,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
|
position: relative;
|
||||||
@apply(--paper-font-body1);
|
@apply(--paper-font-body1);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-bottom-left-radius: 2px;
|
border-bottom-left-radius: 2px;
|
||||||
@ -112,6 +113,14 @@
|
|||||||
height: 44px;
|
height: 44px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.controls .progress {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
--paper-progress-active-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
paper-icon-button {
|
paper-icon-button {
|
||||||
opacity: var(--dark-primary-opacity);
|
opacity: var(--dark-primary-opacity);
|
||||||
}
|
}
|
||||||
@ -150,6 +159,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='controls layout horizontal justified'>
|
<div class='controls layout horizontal justified'>
|
||||||
|
<paper-progress
|
||||||
|
max='[[playbackDuration]]'
|
||||||
|
value='[[playbackPosition]]'
|
||||||
|
hidden$='[[!playbackVisible]]'
|
||||||
|
class='progress'
|
||||||
|
></paper-progress>
|
||||||
|
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon='mdi:power'
|
icon='mdi:power'
|
||||||
on-tap='handleTogglePower'
|
on-tap='handleTogglePower'
|
||||||
@ -221,13 +237,86 @@ Polymer({
|
|||||||
value: 1,
|
value: 1,
|
||||||
reflectToAttribute: true,
|
reflectToAttribute: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
playbackDuration: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
|
||||||
|
playbackPosition: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
|
||||||
|
playbackVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
playerObjChanged: function (playerObj) {
|
playerObjChanged: function (playerObj) {
|
||||||
|
var timeSincePositionValid;
|
||||||
|
|
||||||
if (!playerObj.isOff && !playerObj.isIdle) {
|
if (!playerObj.isOff && !playerObj.isIdle) {
|
||||||
this.$.cover.style.backgroundImage = playerObj.stateObj.attributes.entity_picture ?
|
this.$.cover.style.backgroundImage = playerObj.stateObj.attributes.entity_picture ?
|
||||||
'url(' + playerObj.stateObj.attributes.entity_picture + ')' : '';
|
'url(' + playerObj.stateObj.attributes.entity_picture + ')' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof this._positionTracking === 'undefined') {
|
||||||
|
this._positionTracking = {
|
||||||
|
position: null, // last value of media_position
|
||||||
|
time: null, // when that value was updated
|
||||||
|
interval: null, // interval timer to update playbackPosition property
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear previous interval timer
|
||||||
|
if (this._positionTracking.interval) {
|
||||||
|
clearInterval(this._positionTracking.interval);
|
||||||
|
this._positionTracking.interval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update playback state from object
|
||||||
|
if (playerObj.stateObj.attributes.media_position_updated_at) {
|
||||||
|
// when was the position valid?
|
||||||
|
timeSincePositionValid = Math.abs(
|
||||||
|
new Date() - Date.parse(playerObj.stateObj.attributes.media_position_updated_at)
|
||||||
|
);
|
||||||
|
|
||||||
|
// update "current" position (in ms) to reflect that
|
||||||
|
this._positionTracking.position = (1000 * playerObj.stateObj.attributes.media_position) +
|
||||||
|
timeSincePositionValid;
|
||||||
|
|
||||||
|
// base playbackPosition calculations on calculate position now
|
||||||
|
this._positionTracking.time = Date.now();
|
||||||
|
|
||||||
|
// playbackDuration is expressed in ms (rounded to the next second)
|
||||||
|
this.playbackDuration = 1000 * playerObj.stateObj.attributes.media_duration;
|
||||||
|
} else {
|
||||||
|
// no playback position
|
||||||
|
this._positionTracking.position = null;
|
||||||
|
this._positionTracking.time = null;
|
||||||
|
this.playbackDuration = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerObj.isPlaying && this._positionTracking.position != null && this.playbackDuration) {
|
||||||
|
// playback is in progress, update the playback status on an interval timer
|
||||||
|
// we choose 200ms here in order to get the playback paper-progress control movement smooth
|
||||||
|
this._positionTracking.interval = setInterval(this.updatePlaybackPosition.bind(this), 200);
|
||||||
|
} else {
|
||||||
|
// no playback in progress (or no playback info), update playback status
|
||||||
|
this.updatePlaybackPosition();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updatePlaybackPosition: function () {
|
||||||
|
if (this._positionTracking.position != null && this.playbackDuration) {
|
||||||
|
// calculate playback position in ms
|
||||||
|
this.playbackPosition = this._positionTracking.position +
|
||||||
|
(Date.now() - this._positionTracking.time);
|
||||||
|
this.playbackVisible = true;
|
||||||
|
} else {
|
||||||
|
this.playbackPosition = null;
|
||||||
|
this.playbackVisible = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computeBannerClasses: function (playerObj) {
|
computeBannerClasses: function (playerObj) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user