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

feat: add skip forward/backward buttons #8147

Merged
merged 19 commits into from
Mar 6, 2023
Merged

feat: add skip forward/backward buttons #8147

merged 19 commits into from
Mar 6, 2023

Conversation

usmanonazim
Copy link
Contributor

@usmanonazim usmanonazim commented Feb 21, 2023

Description

With the upgrade to videojs font 4.0.0, font icons for skipping forward and backward have been introduced. This PR adds the option to add a skip forward or skip backward button to the control bar. These buttons are placed after the PlayToggle and before the VolumeControl, as shown in the image below.

image

The user also has the option to enable only one of the two skip buttons, as shown in the image below.

image

Code pen example with all icons: https://codepen.io/usmanomar/pen/MWqjWjj
Relevant docs: videojs/videojs.com#167

Options Description

controlBar.skipButtons.forward

Type: number

The number of seconds forward that should be skipped on button click (can be 5, 10, or 30)

controlBar.skipButtons.backward

Type: number

The number of seconds backward that should be skipped on button click (can be 5, 10 or 30)

Specific Changes proposed

  • Implement a SkipForward button that skips forward through a video a configurable amount of seconds
  • Implement a SkipBackward button skips backward through a video a configurable amount of seconds
  • Use the vjs-icon-forward-x and vjs-icon-replay-x for the SkipForward and SkipBackward buttons respectively

Requirements Checklist

  • Feature implemented / Bug fixed
  • If necessary, more likely in a feature request than a bug fix
    • Change has been verified in an actual browser (Chrome, Firefox, IE)
    • Unit Tests updated or fixed
    • Docs/guides updated
    • Example created (sandbox/skip-buttons.html.example)
  • Reviewed by Two Core Contributors

@codecov
Copy link

codecov bot commented Feb 21, 2023

Codecov Report

Merging #8147 (9a8d070) into main (0a47175) will increase coverage by 0.11%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #8147      +/-   ##
==========================================
+ Coverage   82.02%   82.14%   +0.11%     
==========================================
  Files         110      112       +2     
  Lines        7344     7391      +47     
  Branches     1773     1782       +9     
==========================================
+ Hits         6024     6071      +47     
  Misses       1320     1320              
Impacted Files Coverage Δ
src/js/control-bar/control-bar.js 83.33% <ø> (ø)
src/js/control-bar/skip-buttons/skip-backward.js 100.00% <100.00%> (ø)
src/js/control-bar/skip-buttons/skip-forward.js 100.00% <100.00%> (ø)

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@usmanonazim usmanonazim marked this pull request as ready for review February 21, 2023 15:17
@mister-ben
Copy link
Contributor

The numbers on the icons are pretty illegible at the default size of the controls. That may well be flagged in an acessiblity audit.

@usmanonazim
Copy link
Contributor Author

The numbers on the icons are pretty illegible at the default size of the controls. That may well be flagged in an acessiblity audit.

Do you know if there's a good way to fix that?

@mister-ben
Copy link
Contributor

The numbers on the icons are pretty illegible at the default size of the controls. That may well be flagged in an acessiblity audit.

Do you know if there's a good way to fix that?

I think it needs to be different icons that are readble at that size, or plain arrows. The control text could (and for accessibility probably should) state the increment to be skipped by.

@roman-bc-dev
Copy link
Contributor

The numbers on the icons are pretty illegible at the default size of the controls. That may well be flagged in an acessiblity audit.

Do you know if there's a good way to fix that?

The icons used here are from the standard Material Design set. Unless we jerry-rig a solution with existing videojs font icons, we'd need to decide on brand new ones and then update the font repo with them to then be used here, which seems outside the scope of the changes described.

@mister-ben The empty round arrow icon is already used for replay UI and plain arrows are not descriptive of the intended action here. Are there any other icons from the Material Design or Font Awesome collections that you would recommend for legibility?

@mister-ben
Copy link
Contributor

I've seen the rewind / fast forward icons used for this in OTT apps, but they are also problematic as they can be understood as changing the playback rate.

Some also use a similar looped arrow with a double arrowhead, but there's no such icon in Material Icons or Font Awesome. Netflix is like this. (They also show numbers, but have the icons large enough for this to work.)

Here I used rotated arrows to distinguish them from replay.

Maybe showing the number, larger, when the button has focus could work? If we really want numbers they need to be readable, I might try tweaking the SVG icons.

It might be easier if we could consider using "restart alt" from Material icons for replay with a fuller, broken loop.
grafik

@mister-ben
Copy link
Contributor

Here's one idea, modifying Material Icons's SVG

grafik

@usmanonazim
Copy link
Contributor Author

Here's one idea, modifying Material Icons's SVG

grafik

That looks great - thank you for the suggestion! Is it ok if I use that?

@roman-bc-dev
Copy link
Contributor

Here's one idea, modifying Material Icons's SVG

grafik

Love that icon idea.

@usmanonazim Are you comfy with modifying SVGs? You have the tools to do so?

@mister-ben
Copy link
Contributor

Thinking about it, the icon could just be that partial arrow, and the number can be text. That's a lot less SVG work, we don't have to impose the increments that can be used, and the number can be localised for languages that don't use "arabic numerals", like actual arabic numbers.

@usmanonazim
Copy link
Contributor Author

Thinking about it, the icon could just be that partial arrow, and the number can be text. That's a lot less SVG work, we don't have to impose the increments that can be used, and the number can be localised for languages that don't use "arabic numerals", like actual arabic numbers.

Just to clarify, do you mean that the icon used would just be the partial arrow, and then the control text would specify the number, or that the number would go underneath the arrow icon? If it's the second one, setting a number that's too large (ie 1000) could ruin the look of the icon right?

@mister-ben
Copy link
Contributor

mister-ben commented Feb 23, 2023

The control text should be something useful for screenreaders, like "skip back 10 seconds".

I've updated the codepen example with a version that adds a span for the number, with aria-hidden so it's not read out, and can be localised to match the player language.

grafik

You're right, a high number won't work well. Maybe accept =< 99?

@roman-bc-dev
Copy link
Contributor

You'd also have to consider dynamic typeface sizing/interactions within an SVG icon, which gets finicky, especially with hover effects, etc. For the purposes of the intended work here, it may be best to implement the expected icons with the 5, 10, and 30 increments as SVGs and then build a more expanded solution later down the line.

@usmanonazim
Copy link
Contributor Author

You'd also have to consider dynamic typeface sizing/interactions within an SVG icon, which gets finicky, especially with hover effects, etc. For the purposes of the intended work here, it may be best to implement the expected icons with the 5, 10, and 30 increments as SVGs and then build a more expanded solution later down the line.

I agree - I've created a codepen example with the new icons. @mister-ben @roman-bc-dev please let me know what you think of them 😄

@mister-ben
Copy link
Contributor

Nice. Are we sticking with SVG or getting these into the font? (In general I'd prefer to move to SVG directly).

@usmanonazim
Copy link
Contributor Author

usmanonazim commented Feb 24, 2023

Nice. Are we sticking with SVG or getting these into the font? (In general I'd prefer to move to SVG directly).

I was planning to replace the existing icons for replay-x and forward-x in font with the SVGs that I've created.

@usmanonazim
Copy link
Contributor Author

usmanonazim commented Feb 27, 2023

I've now created a PR in videojs/font to update the existing icons: videojs/font#49

this.skipTime = this.getSkipBackwardTime();

if (this.skipTime && this.validOptions.includes(this.skipTime)) {
this.controlText(`Skip backward ${this.skipTime} seconds`);
Copy link
Contributor

Choose a reason for hiding this comment

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

This way means the translation file need a translation for each allowed increment. It's relatively manageable with 3 permitted values, but it is possible to use a variable in these translations: this.localize('Skip backward {seconds} seconds', [this.skipTime])

Either way there should be at least an entry for each string in en.json, so there's a template to translate from.

Copy link
Member

@misteroneill misteroneill Feb 28, 2023

Choose a reason for hiding this comment

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

I agree.

It should be safe to pass a pre-localized string to controlText, like:

this.controlText(this.localize('Skip backward {seconds} seconds', [this.skipTime]));

The reason for this is that translators will want a tokenized static string. The {seconds} token tells them what sort of value to expect in that position.

Then the en.json should have a new entry:

"Skip backward {seconds} seconds": "Skip backward {seconds} seconds"

The reason to include these in en.json is that is used as a reference by the script that parses out missing translations.


EDIT: adding a bit more context here...

The controlText method will pass the string through localize again, but this will be a pass-thru because the replacement of {seconds} will have already happened. It's unlikely there would be a matching localization key for something like Skip backward 1 seconds.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh ok thank you for the explanation! How does translation normally work - am I only expected to add this to en.json and then translators can add the translations to the other json files?

Copy link
Contributor

@mister-ben mister-ben left a comment

Choose a reason for hiding this comment

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

The deploy preview is looking good! Just the note about translations. At the least there should be an en.json. If swithcing to variables is complicated we can tackle that later (and there's an issue with variables and languagechange event that is out of scope for this PR).

Could you also add a link to the sandbox page in /index.html?

Copy link
Member

@misteroneill misteroneill left a comment

Choose a reason for hiding this comment

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

Looks great, Usman! I think just addressing the localization thing should be all that's needed.

this.skipTime = this.getSkipBackwardTime();

if (this.skipTime && this.validOptions.includes(this.skipTime)) {
this.controlText(`Skip backward ${this.skipTime} seconds`);
Copy link
Member

@misteroneill misteroneill Feb 28, 2023

Choose a reason for hiding this comment

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

I agree.

It should be safe to pass a pre-localized string to controlText, like:

this.controlText(this.localize('Skip backward {seconds} seconds', [this.skipTime]));

The reason for this is that translators will want a tokenized static string. The {seconds} token tells them what sort of value to expect in that position.

Then the en.json should have a new entry:

"Skip backward {seconds} seconds": "Skip backward {seconds} seconds"

The reason to include these in en.json is that is used as a reference by the script that parses out missing translations.


EDIT: adding a bit more context here...

The controlText method will pass the string through localize again, but this will be a pass-thru because the replacement of {seconds} will have already happened. It's unlikely there would be a matching localization key for something like Skip backward 1 seconds.

this.skipTime = this.getSkipForwardTime();

if (this.skipTime && this.validOptions.includes(this.skipTime)) {
this.controlText(`Skip forward ${this.skipTime} seconds`);
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here about localization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've now moved the control text strings from skip-forward and skip-backward to en.json for localization.

@usmanonazim
Copy link
Contributor Author

The deploy preview is looking good! Just the note about translations. At the least there should be an en.json. If swithcing to variables is complicated we can tackle that later (and there's an issue with variables and languagechange event that is out of scope for this PR).

Could you also add a link to the sandbox page in /index.html?

I've added the link to the sandbox page now 😁

Copy link
Member

@misteroneill misteroneill left a comment

Choose a reason for hiding this comment

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

LGTM, thanks Usman!

@usmanonazim usmanonazim merged commit 8f3f32c into videojs:main Mar 6, 2023
@usmanonazim usmanonazim deleted the feat/forward-back-buttons branch March 6, 2023 09:52
edirub pushed a commit to edirub/video.js that referenced this pull request Jun 8, 2023
* remove duplicate icons from icon example

* create initial forward and back button classes

* add logic for back/forward buttons on click

* change icon used based on option passed into player

* move logic from forward and back buttons into one component

* add jsdoc comments for clarity

* create initial test file

* refactor button logic into separate files

* update skip button example and add test files

* test both the forward and backward buttons

* test handleClick fns for both forward and backward btns

* update skip buttons example

* update jsdocs for skip backward and forward buttons

* make control text accessible and use seekableEnd/Start when skipping forward/back

* update font version to use updated icons

* set control text only if config is valid

* add link to sandbox page & use localization

* update translations needed
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