Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // This Polymer element shows media controls for a route that is currently cast | |
| 6 // to a device. | |
| 7 Polymer({ | |
| 8 is: 'route-controls', | |
| 9 | |
| 10 properties: { | |
| 11 /** | |
| 12 * The current time displayed in seconds. | |
| 13 * @type {number} | |
| 14 */ | |
| 15 displayedCurrentTime_: { | |
| 16 type: Number, | |
| 17 value: 0 | |
| 18 }, | |
| 19 | |
| 20 /** | |
| 21 * Whether updates for the current time from the browser should be ignored. | |
| 22 * Set to true when the user is dragging the time slider. | |
| 23 * @private {boolean} | |
| 24 */ | |
| 25 ignoreExternalTimeUpdates_: { | |
|
mark a. foltz
2017/05/03 21:27:00
This might be clearer as isSeeking_, but I don't f
takumif
2017/05/05 18:57:39
Done.
| |
| 26 type: Boolean, | |
| 27 value: false | |
| 28 }, | |
| 29 | |
| 30 /** | |
| 31 * Whether volume updates from the browser should be ignored. Set to true | |
| 32 * when the user is dragging the volume slider. | |
| 33 * @private {boolean} | |
| 34 */ | |
| 35 ignoreExternalVolumeUpdates_: { | |
|
mark a. foltz
2017/05/03 21:27:00
isVolumeChanging_
takumif
2017/05/05 18:57:40
Done.
| |
| 36 type: Boolean, | |
| 37 value: false | |
| 38 }, | |
| 39 | |
| 40 /** | |
| 41 * Whether we have received status updates from the browser for the current | |
| 42 * route. When this is false, we allow updating the media title based on the | |
| 43 * route name. | |
|
mark a. foltz
2017/05/03 21:26:59
I don't follow how a media status update is relate
takumif
2017/05/05 18:57:39
Removed this variable. I wanted to use route descr
| |
| 44 * @private {boolean} | |
| 45 */ | |
| 46 receivedStatusUpdates_: { | |
| 47 type: Boolean, | |
| 48 value: false | |
| 49 }, | |
| 50 | |
| 51 /** | |
| 52 * The route to show. | |
| 53 * @type {?media_router.Route} | |
|
mark a. foltz
2017/05/03 21:26:59
Must this be null on construction?
takumif
2017/05/05 18:57:39
Removed.
| |
| 54 */ | |
| 55 route: { | |
| 56 type: Object, | |
| 57 observer: 'onRouteChange_', | |
| 58 value: null | |
| 59 }, | |
| 60 | |
| 61 /** | |
| 62 * The status of the media route shown. External updates are done using | |
| 63 * updateRouteStatus() to discern from internal updates. | |
|
mark a. foltz
2017/05/03 21:27:00
s/status/media status/
Can you explain "internal"
takumif
2017/05/05 18:57:40
Removed. This was to discern updates by status obj
| |
| 64 * @private {?media_router.RouteStatus} | |
| 65 */ | |
| 66 routeStatus_: { | |
| 67 type: Object, | |
| 68 observer: 'onRouteStatusChange_', | |
| 69 value: null | |
| 70 }, | |
| 71 | |
| 72 /** | |
| 73 * The value of the time slider, between 0 and 1. | |
|
mark a. foltz
2017/05/03 21:26:59
s/time slider/seek bar/
Shouldn't this be in secon
takumif
2017/05/05 18:57:40
Switched to seconds. Also merged with displayedCur
| |
| 74 * @type {number} | |
| 75 */ | |
| 76 timeSliderValue_: { | |
|
mark a. foltz
2017/05/03 21:26:59
currentTimeFraction_ ?
takumif
2017/05/05 18:57:39
Merged with displayedCurrentTime_
| |
| 77 type: Number, | |
| 78 value: 0 | |
| 79 }, | |
| 80 | |
| 81 /** | |
| 82 * The value of the volume slider, between 0 and 1. | |
|
mark a. foltz
2017/05/03 21:27:00
s/slider/control/
takumif
2017/05/05 18:57:40
Done.
| |
| 83 * @type {number} | |
| 84 */ | |
| 85 volumeSliderValue_: { | |
| 86 type: Number, | |
| 87 value: 0 | |
| 88 }, | |
| 89 }, | |
| 90 | |
| 91 behaviors: [ | |
| 92 I18nBehavior, | |
| 93 ], | |
| 94 | |
| 95 /** | |
| 96 * Gets the duration formatted in HH:MM:SS format. | |
| 97 * @param {?media_router.RouteStatus} routeStatus | |
| 98 * @return {string} | |
| 99 * | |
| 100 * @private | |
| 101 */ | |
| 102 getDuration_: function(routeStatus) { | |
| 103 return routeStatus ? this.getFormattedTime_(routeStatus.duration) : ''; | |
| 104 }, | |
| 105 | |
| 106 /** | |
| 107 * Converts a number representing an interval of seconds to a string with | |
| 108 * HH:MM:SS format. | |
| 109 * @param {number} timeInSec Must be non-negative. Intervals longer than 100 | |
| 110 * hours get truncated silently. | |
| 111 * @return {string} | |
| 112 * | |
| 113 * @private | |
| 114 */ | |
| 115 getFormattedTime_: function(timeInSec) { | |
| 116 if (timeInSec < 0) { | |
| 117 return ''; | |
| 118 } | |
| 119 var hours = Math.floor(timeInSec / 3600); | |
|
mark a. foltz
2017/05/03 21:27:00
s/var/const/
takumif
2017/05/05 18:57:39
The presubmit check tells us to use var instead of
| |
| 120 var minutes = Math.floor(timeInSec / 60) % 60; | |
| 121 var seconds = Math.floor(timeInSec) % 60; | |
| 122 var timeParts = [ | |
| 123 ('0' + hours).substr(-2), ('0' + minutes).substr(-2), | |
| 124 ('0' + seconds).substr(-2) | |
| 125 ]; | |
| 126 return timeParts.join(':'); | |
|
mark a. foltz
2017/05/03 21:27:00
This can be combined with the previous line.
takumif
2017/05/05 18:57:39
Done.
| |
| 127 }, | |
| 128 | |
| 129 /** | |
| 130 * @param {?media_router.RouteStatus} routeStatus | |
| 131 * @return {string} The value for the icon attribute of the mute/unmute | |
| 132 * button. | |
| 133 * | |
| 134 * @private | |
| 135 */ | |
| 136 getMuteUnmuteIcon_: function(routeStatus) { | |
| 137 return (routeStatus && routeStatus.isMuted) ? 'av:volume-off' : | |
|
mark a. foltz
2017/05/03 21:27:00
Can we initialize the element with a routeStatus t
takumif
2017/05/05 18:57:39
Done.
| |
| 138 'av:volume-up'; | |
| 139 }, | |
| 140 | |
| 141 /** | |
| 142 * @param {?media_router.RouteStatus} routeStatus | |
| 143 * @return {string} Localized title for the mute/unmute button. | |
| 144 * | |
| 145 * @private | |
| 146 */ | |
| 147 getMuteUnmuteTitle_: function(routeStatus) { | |
| 148 return (routeStatus && routeStatus.isMuted) ? this.i18n('unmuteTitle') : | |
| 149 this.i18n('muteTitle'); | |
| 150 }, | |
| 151 | |
| 152 /** | |
| 153 * @param {?media_router.RouteStatus} routeStatus | |
| 154 * @return {string}The value for the icon attribute of the play/pause button. | |
| 155 * | |
| 156 * @private | |
| 157 */ | |
| 158 getPlayPauseIcon_: function(routeStatus) { | |
| 159 return (routeStatus && routeStatus.isPaused) ? 'av:play-arrow' : 'av:pause'; | |
| 160 }, | |
| 161 | |
| 162 /** | |
| 163 * @param {?media_router.RouteStatus} routeStatus | |
| 164 * @return {string} Localized title for the play/pause button. | |
| 165 * | |
| 166 * @private | |
| 167 */ | |
| 168 getPlayPauseTitle_: function(routeStatus) { | |
| 169 return (routeStatus && routeStatus.isPaused) ? this.i18n('playTitle') : | |
| 170 this.i18n('pauseTitle'); | |
| 171 }, | |
| 172 | |
| 173 /** | |
| 174 * @param {number} seekPositionRatio The ratio with the duration, which must | |
| 175 * be between 0 and 1. | |
| 176 * @param {number} duration The duration in seconds. | |
| 177 * @return {number} The seek position in seconds. | |
| 178 * | |
| 179 * @private | |
| 180 */ | |
| 181 getSeekPosition_: function(seekPositionRatio, duration) { | |
|
mark a. foltz
2017/05/03 21:27:00
getSeekTime_(seekPosition, duration) ?
takumif
2017/05/05 18:57:40
Using seconds in the slider, and removing this fun
| |
| 182 return duration ? Math.floor(seekPositionRatio * duration) : 0; | |
|
mark a. foltz
2017/05/03 21:27:00
I don't think this extra check is necessary; Math.
takumif
2017/05/05 18:57:39
Removing.
| |
| 183 }, | |
| 184 | |
| 185 /** | |
| 186 * @param {number} seekPosition The seek position in seconds. | |
| 187 * @param {number} duration The duration in seconds. | |
| 188 * @return {number} The seek position as a ratio with the duration, between 0 | |
| 189 * and 1. | |
| 190 * | |
| 191 * @private | |
| 192 */ | |
| 193 getSeekPositionRatio_: function(seekPosition, duration) { | |
|
mark a. foltz
2017/05/03 21:27:00
getSeekPosition_(seekTime, duration) ?
takumif
2017/05/05 18:57:39
Removing.
| |
| 194 return duration ? (seekPosition / duration) : 0; | |
| 195 }, | |
| 196 | |
| 197 /** | |
| 198 * Called when the user starts dragging the current-time slider. | |
| 199 * @param {!Event} e | |
| 200 * | |
| 201 * @private | |
| 202 */ | |
| 203 onImmediateTimeSliderChange_: function(e) { | |
|
mark a. foltz
2017/05/03 21:26:59
onSeekStart_ ?
takumif
2017/05/05 18:57:39
Done.
| |
| 204 this.ignoreExternalTimeUpdates_ = true; | |
| 205 /** @type {{immediateValue: number}} */ | |
| 206 var target = e.target; | |
| 207 this.timeSliderValue_ = target.immediateValue; | |
| 208 this.displayedCurrentTime_ = this.getSeekPosition_( | |
| 209 this.timeSliderValue_, this.routeStatus_.duration); | |
| 210 }, | |
| 211 | |
| 212 /** | |
| 213 * Called when the user starts dragging the volume slider. | |
| 214 * @param {!Event} e | |
| 215 * | |
| 216 * @private | |
| 217 */ | |
| 218 onImmediateVolumeSliderChange_: function(e) { | |
|
mark a. foltz
2017/05/03 21:27:00
onVolumeChangeStart_?
takumif
2017/05/05 18:57:40
Done.
| |
| 219 this.ignoreExternalVolumeUpdates_ = true; | |
| 220 /** @type {{immediateValue: number}} */ | |
| 221 var target = e.target; | |
| 222 this.volumeSliderValue_ = target.immediateValue; | |
| 223 }, | |
| 224 | |
| 225 /** | |
| 226 * Sends a mute or unmute command to the browser. | |
|
mark a. foltz
2017/05/03 21:27:00
Called when the user toggles the mute status of th
takumif
2017/05/05 18:57:39
Done.
| |
| 227 * | |
| 228 * @private | |
| 229 */ | |
| 230 onMuteUnmute_: function() { | |
| 231 media_router.browserApi.setCurrentMediaMute(!this.routeStatus_.isMuted); | |
| 232 }, | |
| 233 | |
| 234 /** | |
| 235 * Sends a play or pause command to the browser. | |
|
mark a. foltz
2017/05/03 21:27:00
Called when the user toggles between playing and p
takumif
2017/05/05 18:57:39
Done.
| |
| 236 * | |
| 237 * @private | |
| 238 */ | |
| 239 onPlayPause_: function() { | |
| 240 if (this.routeStatus_.isPaused) { | |
| 241 media_router.browserApi.playCurrentMedia(); | |
| 242 } else { | |
| 243 media_router.browserApi.pauseCurrentMedia(); | |
| 244 } | |
| 245 }, | |
| 246 | |
| 247 /** | |
| 248 * Updates the route title shown, if no status updates have been received. | |
| 249 * | |
| 250 * @private | |
| 251 */ | |
| 252 onRouteChange_: function(newRoute) { | |
| 253 if (!newRoute || this.receivedStatusUpdates_) | |
| 254 return; | |
| 255 | |
| 256 // Hide all the elements except for the title showing the route description. | |
| 257 this.routeStatus_ = new media_router.RouteStatus( | |
|
mark a. foltz
2017/05/03 21:27:00
Would this be simpler as just a <div> with text co
takumif
2017/05/05 18:57:39
Creating a displayedDescription_ property to set i
| |
| 258 loadTimeData.getStringF('castingActivityStatus', newRoute.description), | |
| 259 '', false, false, false, false, false, false, 0, 0, 0); | |
| 260 }, | |
| 261 | |
| 262 /** | |
| 263 * Called when the route details view is closed. | |
| 264 */ | |
| 265 onRouteDetailsClosed: function() { | |
| 266 this.receivedStatusUpdates_ = false; | |
| 267 this.routeStatus_ = null; | |
| 268 media_router.ui.setRouteControls(null); | |
| 269 }, | |
| 270 | |
| 271 /** | |
| 272 * Updates seek and volume sliders if the user is not currently dragging on | |
| 273 * them. | |
| 274 * @param {?media_router.RouteStatus} newRouteStatus | |
| 275 * | |
| 276 * @private | |
| 277 */ | |
| 278 onRouteStatusChange_: function(newRouteStatus) { | |
| 279 if (!newRouteStatus) | |
| 280 return; | |
| 281 | |
| 282 if (!this.ignoreExternalTimeUpdates_) { | |
| 283 this.displayedCurrentTime_ = newRouteStatus.currentTime; | |
| 284 this.timeSliderValue_ = this.getSeekPositionRatio_( | |
| 285 newRouteStatus.currentTime, newRouteStatus.duration); | |
| 286 } | |
| 287 | |
| 288 if (!this.ignoreExternalVolumeUpdates_) { | |
| 289 this.volumeSliderValue_ = newRouteStatus.volume; | |
| 290 } | |
| 291 }, | |
| 292 | |
| 293 /** | |
| 294 * Called when the user clicks on or stops dragging the current-time slider. | |
| 295 * @param {!Event} e | |
| 296 * | |
| 297 * @private | |
| 298 */ | |
| 299 onTimeSliderChange_: function(e) { | |
|
mark a. foltz
2017/05/03 21:27:00
onSeekComplete_
takumif
2017/05/05 18:57:40
Done.
| |
| 300 if (!this.routeStatus_) | |
| 301 return; | |
| 302 | |
| 303 this.ignoreExternalTimeUpdates_ = false; | |
| 304 /** @type {{value: number}} */ | |
| 305 var target = e.target; | |
| 306 this.timeSliderValue_ = target.value; | |
| 307 this.displayedCurrentTime_ = this.getSeekPosition_( | |
| 308 this.timeSliderValue_, this.routeStatus_.duration); | |
| 309 media_router.browserApi.seekCurrentMedia(this.displayedCurrentTime_); | |
| 310 }, | |
| 311 | |
| 312 /** | |
| 313 * Called when the user clicks on or stops dragging the volume slider. | |
| 314 * @param {!Event} e | |
| 315 * | |
| 316 * @private | |
| 317 */ | |
| 318 onVolumeSliderChange_: function(e) { | |
|
mark a. foltz
2017/05/03 21:27:00
onVolumeChangeComplete_
takumif
2017/05/05 18:57:39
Done.
| |
| 319 if (!this.routeStatus_) | |
| 320 return; | |
| 321 | |
| 322 this.ignoreExternalVolumeUpdates_ = false; | |
| 323 /** @type {{value: number}} */ | |
| 324 var target = e.target; | |
| 325 this.volumeSliderValue_ = target.value; | |
| 326 media_router.browserApi.setCurrentMediaVolume(this.volumeSliderValue_); | |
| 327 }, | |
| 328 | |
| 329 /** | |
| 330 * Called by Polymer on ready. | |
| 331 */ | |
| 332 ready: function() { | |
| 333 media_router.ui.setRouteControls(this); | |
| 334 }, | |
| 335 | |
| 336 /** | |
| 337 * Updates the route status that is displayed on the controls. | |
| 338 * | |
| 339 * @param {!media_router.RouteStatus} status | |
| 340 */ | |
| 341 updateRouteStatus: function(status) { | |
| 342 this.receivedStatusUpdates_ = true; | |
|
mark a. foltz
2017/05/03 21:27:00
Is this the same as testing this.routeStatus_ ?
takumif
2017/05/05 18:57:39
Removed.
| |
| 343 this.routeStatus_ = status; | |
| 344 }, | |
| 345 }); | |
| OLD | NEW |