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

Selma: Content script sometimes gets injected after DOMContentLoaded event on OperaGX #158

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

A-K-O-R-A
Copy link
Contributor

Pull Request

Description

This resolves an issue where the Selma improvement script won't activate when it gets injected after the DOMContentLoaded event. It also resolves a small layout issue with the credit banner.
See: https://stackoverflow.com/a/39993724

image
image

Type of change

  • Bug fix (non-breaking change which fixes a bug)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that might cause existing functionality to not work as expected)

Further info

  • This change requires a documentation update
  • I updated the documentation accordingly, if required
  • I commented my code where its useful

Testing

We have 1500+ Users. Please test your changes thoroughly.

  • Tested my changes on Firefox
  • Tested my changes on Chromium-Based-Browsers
  • Successfully run npm run test locally

@A-K-O-R-A A-K-O-R-A requested a review from a team as a code owner January 20, 2025 12:31
@A-K-O-R-A A-K-O-R-A requested a review from C0ntroller January 20, 2025 12:31
@C0ntroller
Copy link
Member

Seems like a fix, but there is some strange weirdness in this file.

First of all: why is the Css injected via js? This could also be declared in the manifest.json, couldn't it?

Also, the reason this happens is, that we try to inject before the page is loaded and sometime it already is once the code is run. Correct?
But why even inject the script before the loading is complete? Because we could also just set the content script to load at "document_idle" (also in the manifest). Is there a reason the script should even be run before?

@A-K-O-R-A
Copy link
Contributor Author

First of all: why is the Css injected via js? This could also be declared in the manifest.json, couldn't it?

Because the goal was to give the user the chance to disable the stylesheet, as it only works with the changes the JS script makes to the page

Also, the reason this happens is, that we try to inject before the page is loaded and sometime it already is once the code is run. Correct?
But why even inject the script before the loading is complete? Because we could also just set the content script to load at "document_idle" (also in the manifest). Is there a reason the script should even be run before?

The initial goal was to prevent a flickering effect when the style sheet gets applied after the page is loaded, but with the current solution it does get applied after the page is loaded so I am not sure what I wrote there 😅

@C0ntroller
Copy link
Member

Because the goal was to give the user the chance to disable the stylesheet, as it only works with the changes the JS script makes to the page

This is probably nitpicking, but wouldn't be the better way to do this to inject the Css, prefix all styles in the Css with a specific class and or remove the class to the body? I just think injecting files is way less safe and more prone to being blocked in the future 😅
But well, I guess is works, so I won't give it any priority :)

The initial goal was to prevent a flickering effect when the style sheet gets applied after the page is loaded

Why isn't the reading of the setting and the css injection (based on the result) done while waiting for the event? Because these operations should be working even without the fully loaded Dom, shouldn't it?

@A-K-O-R-A
Copy link
Contributor Author

This is probably nitpicking, but wouldn't be the better way to do this to inject the Css, prefix all styles in the Css with a specific class and or remove the class to the body? I just think injecting files is way less safe and more prone to being blocked in the future 😅 But well, I guess is works, so I won't give it any priority :)

Yes changing a flag class on the root would be a better solution, I did not think of that back then but if I find the time for it I will change it.

Why isn't the reading of the setting and the css injection (based on the result) done while waiting for the event? Because these operations should be working even without the fully loaded Dom, shouldn't it?

Yes they could be done in parallel, I think in reality this does not really change anything. Weirdly this entire issue is not present on firefox, but can also be observed on safari

@A-K-O-R-A
Copy link
Contributor Author

Ok so I just tested it with document_idle, using that does make the flicker noticeably worse. So I would be in favor of keping the (admittedly finicky) current solution for now. I did move the promise for setting to the top of the file and it is now executed in parallel to the rest

@C0ntroller
Copy link
Member

C0ntroller commented Jan 20, 2025

It still looks like injectCSS() get only called after DOMContentLoaded. We should probably think about this as two separate actions: applying styles and applying DOM changes.

So probably you could do something like this:

//... 
// Inject CSS
storage.get(['improveSelma'], result => {
    if(!result.improveSelma) return;
    injectCSS('base');
    //... Inject the other styles based on path
});

// Running this outside the async makes it way more predicable
if (document.state !== 'loading') main();
else appendListener('DOMContentLoaded', main);

async main() {
    const enabled = await new Promise(resolve => storage.get(['improveSelma', r => resolve(r.improveSelma));
    if (!enabled) return;
    addCreditsBanner();
    applyChanges();
    //... 
} 

//... All the other definitions

This would fix two things:

  • the event listener should be way more predictable, maybe it will even work cross browser
  • Css get's injected at earliest moment possible, this should reduce flicker to an absolute minimum for this method.
    • Using the class approach could even more reduce this, as the files do not need to be loaded anymore

@A-K-O-R-A
Copy link
Contributor Author

Injecting the CSS before the DOMContentLoaded unfortunately is not possible, because that way the CSS styles will get overridden by the CSS styles from selma :/

@C0ntroller
Copy link
Member

Injecting the CSS before the DOMContentLoaded unfortunately is not possible, because that way the CSS styles will get overridden by the CSS styles from selma :/

Even when using !important for the styles in question?

@A-K-O-R-A
Copy link
Contributor Author

Even when using !important for the styles in question?

Yes, for some reason the alternating colors in the table get messed up, it's all a bit strange. Maybe I did something wrong though, I am not really a web dev expert to be honest

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.

2 participants