-
Notifications
You must be signed in to change notification settings - Fork 124
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
[DRAFT] Demo: store the settings in the url hash #1349
base: dev
Are you sure you want to change the base?
Conversation
I would advocate for both:
|
0b408c2
to
e7c95fc
Compare
const loadContent = React.useCallback((content: IPlayableContent) => { | ||
getLoadVideoOptions(content).then( | ||
(loadVideoOptions) => { | ||
loadVideo(loadVideoOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't look too much into it yet but have you verified that this code is not sensible to race conditions?
For example, if loadContent
is called multiple consecutive times, are we sure that the last call will lead to playback in the end?
Will look more into it, but that's a question I was asking myself reading this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(the issue may already have been there before)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to provoke a race condition but didn't succeed in doing so.
I still have added the code to prevent any race condition, let me know what you think of that because I'm not 100% sure that this is the correct way of doing so.
90fbc13
to
cd9ff08
Compare
e7c95fc
to
b66c200
Compare
1de6ca5
to
a18689b
Compare
b66c200
to
7731780
Compare
const { loadVideoConfig, playerConfig, disableReactiveURL } = parsedHash; | ||
if (typeof loadVideoConfig === "string") { | ||
// maybe we want to check the shape of the object to | ||
// be error prone instead of casting? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have made some changes here, JSON.parse() is not safe if the string is not convertible to a JS object. Therefore I wrapped it in a try/catch.
I have added some checks on the shape of the parsed object, there are quite simple as they only check the "typeof", that would be enough. I didn't went as deep as checking if values are respecting the typescript intersection (maybe it's preferable to use a validating library like Yup or Joi if we want to make such checks?)
I have also handled the case where we stringify/Parse "Infinity'
if (!isAlreadyLoading) { | ||
setIsAlreadyLoading(true); | ||
try { | ||
const loadVideoOptions = await getLoadVideoOptions(content); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest I still feel a race condition is technically possible here.
Perhaps we should have a mechanism (useRef
?) to check that he content is still the last one wanted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To reproduce a race condition, you would have a first getLoadVideoOptions
responding very slowly (e.g. server certificate behind a slow CDN) and try to load another content without this issue.
Here we might play the second content, then play the first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh my bad I didn't see isAlreadyLoading
is here to fix this. Though I don't think this is the right solution. We want to play the last content, not the initial one.
|
||
const { useCallback, useEffect, useRef, useState } = React; | ||
|
||
// time in ms while seeking/loading/buffering after which the spinner is shown | ||
const SPINNER_TIMEOUT = 300; | ||
|
||
const isShapeOfLoadVideoConfig = (arg: any): arg is ILoadVideoSettings => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the need to do that? Is it for type casting?
It looks very dependent of what we expose through the demo's options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a user reach the demo page with an URL with a pre-establish config:
http://player.com/#config={foo:bar}
if at some point we change the demo, and the expected url is now
http://player.com/#config={toto:tata}
then we could have errors.
In others words, the URL cannot be trusted and we have to check if the data in it is coherent when parsing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK I get it.
But the downside would be that we have to make sure to update that code each time the shape is changed... And I don't think we'll think to do that.
Maybe we could type arg
as ILoadVideoConfig
or whatever so that TypeScript warn us if we're exploiting inexistant properties? Even with that I don't know...
2e58dd6
to
cc6a502
Compare
1d13bfb
to
1a7da65
Compare
Storing the player settings in the url hash let us refresh the demo page while keeping all the settings previously set.
It's more efficient and comfortable when debugging to not have to reset them manually after each page refresh.
To Do: