Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subtitles #117

Merged
merged 1 commit into from
May 17, 2017
Merged

Subtitles #117

merged 1 commit into from
May 17, 2017

Conversation

bhh1988
Copy link
Contributor

@bhh1988 bhh1988 commented May 16, 2017

No description provided.

*/
handleSubtitle() {
const subtitleIdx = parseInt(cache.get('media-subtitles'), 10);
if (subtitleIdx >= 0 && subtitleIdx < this.textTracks.length) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could just check for if (this.textTracts[subtitileIdx]) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -279,9 +300,21 @@ class DashViewer extends VideoBaseViewer {
addEventListenersForMediaControls() {
super.addEventListenersForMediaControls();
this.mediaControls.addListener('qualitychange', this.handleQuality);
this.mediaControls.addListener('subtitlechange', this.handleSubtitle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be removed like qualitychange is. You could also just call removeAllListeners in the destroy method. https://nodejs.org/api/events.html#events_emitter_removealllisteners_eventname

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Removing subtitlechange event in destroy. Can follow up with another commit later to refactor things to call removeAllListeners, since that seems generally better practice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your thinking on removeAllListeners vs removeListener? Typically I like explicitly removing only what I add since that lowers the probability you're stomping through some other listener.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but if it's in a function like destroy(), is there still a risk?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not.

* @return {void}
*/
loadSubtitles() {
this.textTracks = this.player.getTextTracks().sort((track1, track2) => { return track1.id - track2.id; });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if you omit the '{}' for the function body in a one-liner like this there is an implicit return.

this.player.getTextTracks().sort((track1, track2) => track1.id - track2.id); looks a little cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool. Done.

loadSubtitles() {
this.textTracks = this.player.getTextTracks().sort((track1, track2) => { return track1.id - track2.id; });
if (this.textTracks.length > 0) {
this.mediaControls.initSubtitles(this.textTracks.map((track) => { return track.language; }));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, can remove the {} and return if you'd like.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -35,6 +35,10 @@
<label class="bp-media-controls-label bp-media-controls-timecode">00:00</label>
<span class="bp-media-controls-label">&nbsp;&#47;&nbsp;</span>
<label class="bp-media-controls-label bp-media-controls-duration">00:00</label>
<button class="bp-media-controls-btn bp-media-cc-icon">
<span class="bp-media-controls-cc-text">CC</span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename this to "bp-media-cc-icon-text" to match with the 'icon-on' and parent button?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*/
toggleSubtitles() {
this.show();
this.emit('togglesubtitles');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I've had trouble following this myself but I believe our convention is to emit absolutely last in a function. Here it wouldn't really make a difference but if we ran some time intensive code after it could cause issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, good catch. Done.

this.settingsEl.style.width = `${menu.offsetWidth + 18}px`;
// height = n * $item-height + 2 * $padding (see Settings.scss)
// where n is the number of displayed items in the menu
const sumHeight = [].reduce.call(menu.children, (sum, child) => { return sum + child.offsetHeight; }, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can avoid the return here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (prevValue !== newValue) {
this.toggleToSubtitle = prevValue;
}
this.containerEl.classList.remove(CLASS_SETTINGS_SUBTITLES_ON);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: new line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally add a line break after if blocks before other chunks of code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

const subtitlesSubMenu = this.settingsEl.querySelector('.bp-media-settings-menu-subtitles');
subtitles.forEach((subtitle, idx) => {
insertTemplate(subtitlesSubMenu, SUBTITLES_SUBITEM_TEMPLATE.replace(/{{language}}/g, subtitle).replace(/{{dataValue}}/g, idx));
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I usually add new lines after any {} block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line break

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I think. Lemme know if I did it wrong.

});
this.containerEl.classList.remove(CLASS_SETTINGS_SUBTITLES_UNAVAILABLE);
const subsCache = cache.get('media-subtitles');
if (subsCache !== null && subsCache !== '-1') { // Last video watched with subtitles, so turn them on here too
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: doing if (subscache) checks for falsey values, so it would catch things like null and undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea but it also catches things like empty string or 0. 0 in particular can be a problem because it's a valid index into the subtitle track list (though it should always be a string, so we should be fine, but just in case...)

@@ -279,9 +300,21 @@ class DashViewer extends VideoBaseViewer {
addEventListenersForMediaControls() {
super.addEventListenersForMediaControls();
this.mediaControls.addListener('qualitychange', this.handleQuality);
this.mediaControls.addListener('subtitlechange', this.handleSubtitle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your thinking on removeAllListeners vs removeListener? Typically I like explicitly removing only what I add since that lowers the probability you're stomping through some other listener.

if (prevValue !== newValue) {
this.toggleToSubtitle = prevValue;
}
this.containerEl.classList.remove(CLASS_SETTINGS_SUBTITLES_ON);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally add a line break after if blocks before other chunks of code

toggleSubtitles() {
if (this.subtitlesOn) {
this.chooseOption('subtitles', '-1');
this.subtitlesOn = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we infer that subtitles are on / off without adding a property? (checking what option is set already, checking a shaka player property?, etc)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good tip. I'm going with checking the menu to see if it's off.

const subtitlesSubMenu = this.settingsEl.querySelector('.bp-media-settings-menu-subtitles');
subtitles.forEach((subtitle, idx) => {
insertTemplate(subtitlesSubMenu, SUBTITLES_SUBITEM_TEMPLATE.replace(/{{language}}/g, subtitle).replace(/{{dataValue}}/g, idx));
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line break

const subsCache = cache.get('media-subtitles');
if (subsCache !== null && subsCache !== '-1') { // Last video watched with subtitles, so turn them on here too
this.toggleSubtitles();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing with line breaks - we generally prefer less dense-looking code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* @private
* @return {boolean}
*/
subtitlesOn() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

areSubtitlesOn() - the current name is ambiguous between turning subtitles on vs checking if they're on

* @param {string} type - The submenu (e.g. speed, quality, subtitles)
* @return {HTMLElement} The sub-item html element from the Settings menu that's selected
*/
selectedOption(type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSelectedOption(type) - function names should contain verbs if you're retrieving a value.

this.showSubMenu('speed');
} else if (curNode.getAttribute('data-type') === 'quality') {
this.showSubMenu('quality');
const dataType = curNode.getAttribute('data-type');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can combine the if blocks and reduce arrowness of the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combining two if-blocks but leaving the top one, just for protection.

@@ -80,6 +87,21 @@ const SETTINGS_TEMPLATE = `<div class="bp-media-settings">
<div class="bp-media-settings-value">${__('media_quality_auto')}</div>
</div>
</div>
<div class="bp-media-settings-menu-subtitles bp-media-settings-menu bp-media-settings-is-hidden" role="menu">
<div class="bp-media-settings-sub-item bp-media-settings-sub-item-subtitles" data-type="menu" tabindex="0" role="menuitem" aria-haspopup="true">
Copy link
Contributor

@priyajeet priyajeet May 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are working on media stuff later, make all these classes variables.
We are repeating so many strings that we can just do <div class="${CLASSNAME}">.
Should reduce file size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok i'll keep that in mind next time

this.mediaControls.removeListener('qualitychange', this.handleQuality);
this.mediaControls.removeListener('subtitlechange', this.handleSubtitle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why arent the last 2 in removeAllListeners()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea great question.... @jeremypress ?? I didn't notice removeAllListeners is already being called. Are these calls necessary?

this.emit('subtitlechange', track.language);
} else {
this.player.setTextTrackVisibility(false);
this.emit('subtitlechange', __('off'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not localize event data, its for developers using the preview sdk and not for end users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*/
handleSubtitle() {
const subtitleIdx = parseInt(cache.get('media-subtitles'), 10);
if (this.textTracks[subtitleIdx] !== undefined) {
Copy link
Contributor

@priyajeet priyajeet May 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessary !== undefined
if (this.textTracks[subtitleIdx]) should suffice, with it reveresed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty string

*/
loadSubtitles() {
this.textTracks = this.player.getTextTracks().sort((track1, track2) => track1.id - track2.id);
if (this.textTracks.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be > 1?
As in should we show the menu at all if there is only 1 track?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because then they can see what language it is for instance

Added subtitles to the video menu. The subtitles menu only shows if the
video is detected to have subtitles in it. This is only supported in the
DashViewer. There is also a CC button for toggling subtitles on/off
@bhh1988 bhh1988 merged commit 4c56532 into box:master May 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants