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

Add prefers-color-scheme support #601

Merged
merged 8 commits into from
Aug 15, 2019
Merged

Add prefers-color-scheme support #601

merged 8 commits into from
Aug 15, 2019

Conversation

psvenk
Copy link
Contributor

@psvenk psvenk commented Jun 18, 2019

This should fix #559.

The cookie storage format has been changed from boolean ("true"/"false") to tri-state ("dark"/"light"/""), so that users without a cookie set will get dark mode if they have enabled the dark theme in their operating system. The code for handling the cookie state, along with the user's operating system theme, has been factored out into a new function update_mode, which is called both at window load and at the "storage" event listener, because the "storage" event listener is only trigerred when a change is made to the localStorage from another tab/window (for more info, see https://stackoverflow.com/a/4679754).

This has worked in my limited testing using Firefox with the "Dark Website Forcer" add-on, using the Docker install instructions on GNU+Linux.

@psvenk
Copy link
Contributor Author

psvenk commented Jun 19, 2019

I just noticed that the "dark mode" checkbox in the preferences doesn't work if the user has not selected a preference for dark mode (i.e. the user has not clicked on the toggle) and goes into the preferences. This can be seen if the OS is in light mode and one goes to the preferences and checks "dark mode"—dark mode is enabled for a fraction of a second and then light mode takes effect again due to the system theme. I think a tri-state preference that affects both the cookie and the current appearance is the solution for that, mirroring what has been done in assets/js/themes.js.

@omarroth
Copy link
Contributor

Very much appreciated! I'll hopefully have time to test this out properly sometime tomorrow.

As you mentioned I expect some handling server-side needs to be added before this is merged.

Rather than change the type for dark_mode, I think it makes sense to add it as a new field theme which overrides the current option, which would then allow any additional themes to be added as "theme": "x" in future.

@psvenk
Copy link
Contributor Author

psvenk commented Jun 19, 2019

Thank you. I was just now trying to see if I could change the preferences page, but as you mentioned there is some server-side code (including a .ecr file—I am assuming that is the Crystal equivalent of embedded Ruby) that needs to be changed. I am not familiar with embedded Ruby or embedded Crystal and I saw that these files deal with the locale files, so I think that it would be best if someone more qualified than me writes the code for that.

As for the theme field, I think we are on the same page. Here is a quick mockup that I made for the frontend (from Firefox developer tools), with HTML source code in case it would be helpful:

  Before After
Screenshot Before After
Source code
Click to show
<div class="pure-control-group"><label for="dark_mode">Dark mode: </label><input name="dark_mode" id="dark_mode" type="checkbox" checked=""></div>
Click to show
<div class="pure-control-group"><label>Theme: </label><input id="theme_auto" name="theme" value="theme_auto" type="radio"><label for="theme_auto" style="text-align: left; width: auto;">Auto</label><input id="theme_light" name="theme" value="light_mode" type="radio"><label for="theme_light" style="text-align: left; width: auto;">Light</label><input id="theme_dark" name="theme" value="theme_dark" type="radio"><label for="theme_dark" style="text-align: left; width: auto;">Dark</label></div>

Maybe instead of the dark/light button in the top right, there could be a dropdown with the same theme options available from the settings.

@omarroth
Copy link
Contributor

Apologies for the delay. I pushed the necessary changes for this to be supported with existing preferences, cookies, etc.

I encountered an issue when testing without localStorage set. To reproduce:

  • Open new tab without cookies or localStorage
  • Go to preferences and change theme to dark (without using the "Dark Website Forcer" addon)

The page will have the desired dark theme while loading, then immediately switch to light after themes.js has loaded, since dark_mode in localStorage is undefined.

assets/js/themes.js Outdated Show resolved Hide resolved
assets/js/themes.js Outdated Show resolved Hide resolved
@omarroth
Copy link
Contributor

omarroth commented Jul 5, 2019

I think the only issue is when first visiting the site without prefers-color-scheme: dark. Otherwise this should be ready to merge 👍

@psvenk
Copy link
Contributor Author

psvenk commented Jul 28, 2019

I'm sorry, I just now saw your comment detailing the issue with localStorage unset. It seems like this occurs because the "Dark mode" preference, stored in the Crystal backend, is not synchronized properly with the dark_mode preference in localStorage. Because this is not an issue in current omarroth:master (the status quo), I imagine that the frontend and backend are communicating to keep this preference synchronized, but I cannot find where this happens. Would you please point me to the specific lines of code?

assets/js/themes.js Outdated Show resolved Hide resolved
assets/js/themes.js Show resolved Hide resolved
@omarroth
Copy link
Contributor

omarroth commented Jul 30, 2019

I imagine that the frontend and backend are communicating to keep this preference synchronized, but I cannot find where this happens.

When changing a user's theme, the client will send a /toggle_theme XHR and a storageEvent to other tabs to update the current theme. It may be necessary to update the /toggle_theme endpoint to support switching to a specific theme, although you may have to clarify what you mean here.

@psvenk
Copy link
Contributor Author

psvenk commented Aug 8, 2019

Thank you for the information, and sorry for the delay. I have made some changes so that the dark-mode preference (on the preferences page) now defaults to "" and the client now updates localStorage with the value from the dark-mode preference on page load. The bug that you pointed out is gone now (at least on Firefox 68.0.1 on Arch Linux, private browsing, no add-ons enabled), and I have not found any other issues. Is this ready to merge?

@omarroth
Copy link
Contributor

omarroth commented Aug 9, 2019

From some quick testing it LGTM. I'd like to test it out a bit more but otherwise I think this should be ready to merge.

assets/js/themes.js Show resolved Hide resolved
assets/js/themes.js Outdated Show resolved Hide resolved
assets/js/themes.js Outdated Show resolved Hide resolved
assets/js/themes.js Show resolved Hide resolved
assets/js/themes.js Outdated Show resolved Hide resolved
@psvenk
Copy link
Contributor Author

psvenk commented Aug 9, 2019

The above comments are comments that I had written previously in response to the review comments that the two of you had posted. I did not fully understand how GitHub's review system works and I had not noticed that these comments were "Pending" and that I had to "submit" the review to make them public. In any case, all of these review comments concern outdated code or are otherwise resolved.

psvenk and others added 8 commits August 15, 2019 11:26
This should fix <iv-org#559>.
The cookie storage format has been changed from boolean
("true"/"false") to tri-state ("dark"/"light"/""), so that users
without a cookie set will get dark mode if they have enabled the dark
theme in their operating system. The code for handling the cookie
state, along with the user's operating system theme, has been factored
out into a new function `update_mode`, which is called both at window
load and at the "storage" event listener, because the "storage" event
listener is only trigerred when a change is made to the localStorage
from another tab/window (for more info - see
<https://stackoverflow.com/a/4679754>).
This should clear up some confusion with the way that I had implemented mode setting, making the code more readable.
Use strict equality, to avoid type coercion and conform to JS best practices (as suggested by @leonklingele).
Changed the default value for the preference `dark-mode` from
"light" to "", to reflect the fact that `dark-mode` is tri-state
and that the default (no preference set) may be the dark theme
(depending on `prefers-color-scheme`).
The JS frontend now reads from the preference stored in the Crystal
backend to update the localStorage on page load, and checks the
preference stored in the backend when updating the mode. This should
fix the issues noted in PR iv-org#601 regarding the frontend and backend
prefs not being synchronized properly.
@omarroth
Copy link
Contributor

Thank you! ❤️

greentornado added a commit to greentornado/invidious that referenced this pull request Aug 22, 2019
* upstream/master:
  Add 'playlistThumbnail' to playlist objects
  Use accurate sub count when available
  Refactor search extractor
  Fix allowed_regions for globally blocked videos
  js: add support to detect alt, meta and control key in keydown handler (iv-org#704)
  Fix playlist_thumbnail extractor
  js: add support for keydown events (iv-org#678)
  Change font family to better native selection (iv-org#679)
  Fix season playlists
  Add prefers-color-scheme support (iv-org#601)
@github-actions
Copy link

This pull request has been automatically locked since there has not been any activity in it in the last 30 days. If you want to tell us about needed or wanted changes or if problems related to this code are discovered, feel free to open an issue or a new pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support "prefers-color-scheme"
3 participants