FEATURE: Allow users to opt out of automatic dark mode (#10377)

This commit is contained in:
Penar Musaraj 2020-08-06 09:45:37 -04:00 committed by GitHub
parent 8c03868808
commit 6fdc711b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 110 additions and 5 deletions

View File

@ -33,6 +33,7 @@ export default Controller.extend({
let attrs = [
"locale",
"external_links_in_new_tab",
"dark_scheme_id",
"dynamic_favicon",
"enable_quoting",
"enable_defer",
@ -149,6 +150,20 @@ export default Controller.extend({
return result;
},
@discourseComputed
showDarkModeToggle() {
return this.siteSettings.default_dark_mode_color_scheme_id > 0;
},
enableDarkMode: computed({
set(key, value) {
return value;
},
get() {
return this.get("model.user_option.dark_scheme_id") === -1 ? false : true;
}
}),
actions: {
save() {
this.set("saved", false);
@ -162,6 +177,11 @@ export default Controller.extend({
this.set("model.user_option.text_size", this.textSize);
}
this.set(
"model.user_option.dark_scheme_id",
this.enableDarkMode ? null : -1
);
return this.model
.save(this.saveAttrNames)
.then(() => {

View File

@ -300,6 +300,7 @@ const User = RestModel.extend({
"email_messages_level",
"email_level",
"email_previous_replies",
"dark_scheme_id",
"dynamic_favicon",
"enable_quoting",
"enable_defer",

View File

@ -20,6 +20,15 @@
</div>
{{/if}}
{{#if showDarkModeToggle}}
<div class="control-group dark-mode">
<label class="control-label">{{i18n "user.dark_mode"}}</label>
<div class="controls">
{{preference-checkbox labelKey="user.dark_mode_enable" checked=enableDarkMode}}
</div>
</div>
{{/if}}
<div class="control-group text-size">
<label class="control-label">{{i18n "user.text_size.title"}}</label>
<div class="controls">

View File

@ -454,7 +454,9 @@ module ApplicationHelper
result = +""
result << Stylesheet::Manager.color_scheme_stylesheet_link_tag(scheme_id)
dark_scheme_id = SiteSetting.default_dark_mode_color_scheme_id
user_dark_scheme_id = current_user&.user_option&.dark_scheme_id
dark_scheme_id = user_dark_scheme_id || SiteSetting.default_dark_mode_color_scheme_id
if dark_scheme_id != -1
result << Stylesheet::Manager.color_scheme_stylesheet_link_tag(dark_scheme_id, '(prefers-color-scheme: dark)')
end

View File

@ -8,6 +8,7 @@ class UserOptionSerializer < ApplicationSerializer
:email_level,
:email_messages_level,
:external_links_in_new_tab,
:dark_scheme_id,
:dynamic_favicon,
:enable_quoting,
:enable_defer,

View File

@ -25,6 +25,7 @@ class UserUpdater
:external_links_in_new_tab,
:enable_quoting,
:enable_defer,
:dark_scheme_id,
:dynamic_favicon,
:automatically_unpin_topics,
:digest_after_minutes,

View File

@ -909,6 +909,8 @@ en:
first_notification: "Your first notification! Select it to begin."
dynamic_favicon: "Show counts on browser icon"
theme_default_on_all_devices: "Make this the default theme on all my devices"
dark_mode: "Dark Mode"
dark_mode_enable: "Enable automatic dark mode color scheme"
text_size_default_on_all_devices: "Make this the default text size on all my devices"
allow_private_messages: "Allow other users to send me personal messages"
external_links_in_new_tab: "Open all external links in a new tab"

View File

@ -248,6 +248,7 @@ basic:
default_dark_mode_color_scheme_id:
default: -1
hidden: true
client: true
relative_date_duration:
client: true
default: 30

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddDarkSchemeIdToUserOptions < ActiveRecord::Migration[6.0]
def change
add_column :user_options, :dark_scheme_id, :integer
end
end

View File

@ -93,13 +93,17 @@ class Stylesheet::Manager
end
end
def self.color_scheme_stylesheet_details(color_scheme_id = nil)
def self.color_scheme_stylesheet_details(color_scheme_id = nil, media)
color_scheme = begin
ColorScheme.find(color_scheme_id)
rescue
# don't load fallback when requesting dark color scheme
return false if media != "all"
Theme.find_by_id(SiteSetting.default_theme_id)&.color_scheme || ColorScheme.base
end
return false if !color_scheme
target = COLOR_SCHEME_STYLESHEET.to_sym
current_hostname = Discourse.current_hostname
color_scheme_name = Slug.for(color_scheme.name)
@ -119,7 +123,9 @@ class Stylesheet::Manager
end
def self.color_scheme_stylesheet_link_tag(color_scheme_id = nil, media = 'all')
stylesheet = color_scheme_stylesheet_details(color_scheme_id)
stylesheet = color_scheme_stylesheet_details(color_scheme_id, media)
return '' if !stylesheet
href = stylesheet[:new_href]
%[<link href="#{href}" media="#{media}" rel="stylesheet"/>].html_safe
end

View File

@ -177,9 +177,14 @@ describe Stylesheet::Manager do
expect(link).not_to eq("")
end
it "does not crash on missing color scheme" do
it "loads base scheme when defined scheme id is missing" do
link = Stylesheet::Manager.color_scheme_stylesheet_link_tag(125)
expect(link).not_to eq("")
expect(link).to include("color_definitions_base")
end
it "loads nothing when defined dark scheme id is missing" do
link = Stylesheet::Manager.color_scheme_stylesheet_link_tag(125, "(prefers-color-scheme: dark)")
expect(link).to eq("")
end
it "uses the correct color scheme from the default site theme" do

View File

@ -349,6 +349,8 @@ describe ApplicationHelper do
end
describe 'discourse_color_scheme_stylesheets' do
fab!(:user) { Fabricate(:user) }
it 'returns a stylesheet link tag by default' do
cs_stylesheets = helper.discourse_color_scheme_stylesheets
expect(cs_stylesheets).to include("stylesheets/color_definitions")
@ -361,5 +363,40 @@ describe ApplicationHelper do
expect(cs_stylesheets).to include("(prefers-color-scheme: dark)")
expect(cs_stylesheets.scan("stylesheets/color_definitions").size).to eq(2)
end
it 'fails gracefully when the dark color scheme ID is set but missing' do
SiteSetting.default_dark_mode_color_scheme_id = -5
cs_stylesheets = helper.discourse_color_scheme_stylesheets
expect(cs_stylesheets).to include("stylesheets/color_definitions")
expect(cs_stylesheets).not_to include("(prefers-color-scheme: dark)")
end
context "with a user option" do
before do
user.user_option.dark_scheme_id = -1
user.user_option.save!
helper.request.env[Auth::DefaultCurrentUserProvider::CURRENT_USER_KEY] = user
SiteSetting.default_dark_mode_color_scheme_id = ColorScheme.where(name: "Dark").pluck(:id).first
end
it "returns no dark scheme stylesheet when user has disabled that option" do
color_stylesheets = helper.discourse_color_scheme_stylesheets
expect(color_stylesheets).to include("stylesheets/color_definitions")
expect(color_stylesheets).not_to include("(prefers-color-scheme: dark)")
end
it "returns user-selected dark color scheme stylesheet" do
new_cs = Fabricate(:color_scheme, name: 'Custom Color Scheme')
user.user_option.update!(dark_scheme_id: new_cs.id)
color_stylesheets = helper.discourse_color_scheme_stylesheets
expect(color_stylesheets).to include("(prefers-color-scheme: dark)")
expect(color_stylesheets).to include("custom-color-scheme")
end
end
end
end

View File

@ -482,3 +482,16 @@ QUnit.test("can select an option from a dropdown", async assert => {
await field.selectRowByValue("Cat");
assert.equal(field.header().value(), "Cat", "it sets the value of the field");
});
acceptance("User Preferences disabling dark mode", {
loggedIn: true,
settings: { default_dark_mode_color_scheme_id: 1 }
});
QUnit.test("shows option to disable dark mode", async assert => {
await visit("/u/eviltrout/preferences/interface");
assert.ok(
$(".control-group.dark-mode").length,
"it has the option to disable dark mode"
);
});