-
Notifications
You must be signed in to change notification settings - Fork 64
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
Add: Trubbel’s Utilities 1.0.0 #259
Conversation
// Load collapsed state from localStorage | ||
function loadCollapsedState() { | ||
try { | ||
const stored = localStorage.getItem(STORAGE_KEY); |
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.
Please use FFZ's settings provider for storing values rather than localStorage.
this.settings.provider.get(key);
this.settings.provider.set(key, value);
this.settings.provider.has(key);
this.settings.provider.delete(key);
}); | ||
|
||
// Start observing | ||
observer.observe(document.body, { |
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.
This observer does not need to run if you aren't on twitch.tv/drops/inventory
.
You can use, and in fact I see you are using, the site.router:route
event to detect navigation changes within the React app and use that to check the current URL and decide to enable or disable your logic, rather than just leave it running all the time. But you don't have any code that stops the observer when the user leaves that page.
@@ -0,0 +1,5 @@ | |||
query FFZ_GetClipDate($slug: ID!) { | |||
clip(slug: $slug) { |
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.
You should always include the id
column when fetching something like a clip model to that Apollo's caching layer stays happy.
@@ -0,0 +1,5 @@ | |||
query FFZ_GetVideoDate($id: ID!) { | |||
video(id: $id) { |
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.
You should always include the id
column when fetching something like a video model to that Apollo's caching layer stays happy. Yes, even though the query includes the id.
}); | ||
|
||
try { | ||
if (result?.data?.clip && result?.data?.clip.createdAt) { |
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.
You can just do if (result?.data?.clip?.createdAt)
src/trubbel/index.js
Outdated
defaultDateTimeFormat: this.settings.get("addon.trubbel.format.datetime") | ||
}); | ||
|
||
this.on("addon.trubbel.format.datetime-clip", () => this.setClipOrVideoTimestamp()); |
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 think this is supposed to be settings:changed:addon.trubbel.format.datetime-clip
and not just addon.trubbel.format.datetime-clip
? Similar issue with the line below this.
src/trubbel/index.js
Outdated
}); | ||
|
||
this.on("addon.trubbel.format.datetime-clip", () => this.setClipOrVideoTimestamp()); | ||
this.on("addon.trubbel.format.datetime-video", () => this.setClipOrVideoTimestamp()); |
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.
A lot of these event listeners have unnecessary lambdas. You can just do this.on(some_event, this.handler)
and it will work. If you don't supply a context as the third argument, the context (aka what this
is when the handler is called) will be set to the this
from this.on()
by default.
src/trubbel/index.js
Outdated
if (metadataElement) { | ||
const hasError = errorCodes.some(code => metadataElement.textContent.includes(code)); | ||
if (hasError) { | ||
this.site.children.player.resetPlayer(this.site.children.player.current); |
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.
My main issue with this code is that there isn't really a good safety check against it potentially breaking and causing a stampede. There should be a limit so that it can only try resetting the player so many times within a certain time window.
While reducing frustration for the user is good, we also want to ensure we can't accidentally create excessive load on Twitch's servers.
src/trubbel/index.js
Outdated
|
||
|
||
onDisable() { | ||
if (this.handleMouseEnterListener) { |
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's a lot of event listeners and potentially long running code that isn't disabled in this onDisable method. It may as well not be here in its current state since a user will need to refresh the page to fully clean out this add-on's side effects.
src/trubbel/index.js
Outdated
} | ||
|
||
handleMouseLeave(event) { | ||
handleMouseLeave(event); |
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'm not sure what the point of this is, to be honest. If you really want handleMouseLeave
to be accessible under your module you could just do this.handleMouseLeave = handleMouseLeave;
in your constructor or even assign it to the prototype. This is just an extra layer of function when you're already using an arrow function elsewhere where actually binding this method?
Had made a few changes beforehand. Hopefully this is better. |
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.
Looking better! Just a few more things to bring up. I should've gone over the GQL better the first time, so sorry about that.
The GQL requests are the only thing I consider a real blocker here, though I'd suggest also addressing the change to settings (removing an unnecessary JSON serialization) since changing that in the future, once this is in user hands, would be more annoying.
|
||
removeCommandHandlers() { | ||
for (const handler of this.commandHandlers) { | ||
ffz.off("chat:get-tab-commands", handler); |
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 are you using the window global ffz
to register/unregister events? You're already working within a Module so you can just use this.on(...)
and this.off(...)
|
||
saveCollapsedState(state) { | ||
try { | ||
this.settings.provider.set(STORAGE_KEY_CONFIG, JSON.stringify(state)); |
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 clarify, FFZ's setting providers can store JSON safe objects, you don't need to run stringify / parse yourself.
updateCSS() { | ||
// Remove/Hide Things - Stream - Remove the Gradient from Player | ||
if (this.settings.get("addon.trubbel.remove-things.player-gradient")) { | ||
this.css_tweaks.set("hide-player-gradient", ".video-player .top-bar, .video-player .player-controls { background: transparent !important; }"); |
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.
Just curious, is there any reason you're using css_tweaks to store your css when you have a custom ManagedStyle instance you could be setting these in?
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.
A little bit of being stupid, and a little bit of starting something and not finishing it. And going back and forth.
(Just like with the translation core)
@@ -0,0 +1,10 @@ | |||
query FFZ_GetUserFollowAge($login: String!) { |
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.
This query is redundant. FFZ's twitch_data module has a getUserFollowed(id, login)
method that returns followedAt.
@@ -0,0 +1,6 @@ | |||
query FFZ_GetUserAccountAge($login: String!) { |
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 forgot to mention it before, but please set the unique prefix of your gql query names to something other than FFZ, like Trubbel perhaps. This follows the pattern established by the Deck add-on and helps if we need to identify the source of a specific query.
src/trubbel/settings/clips-videos.js
Outdated
} | ||
|
||
onEnable() { | ||
this._ = new NewTransCore({ |
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 looked through the code again and I don't think you're ever actually using this for anything? Just assigning a format to it. You should probably drop creating your own translation core and instead access i18n._
in that one specific place where you want to iterate the available formats.
|
||
async waitForElements() { | ||
return new Promise((resolve) => { | ||
const checkElements = () => { |
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 it doesn't end up finding what it wants, this code could end up running once per frame until the page is closed/reloaded. I would suggest adding a timeout.
…etc