mirror of
https://github.com/iv-org/invidious.git
synced 2025-08-03 19:28:29 +00:00
Update preferences page to support prefers-color-scheme
This commit is contained in:
parent
365a261af3
commit
90cd3571ae
@ -267,8 +267,7 @@ before_all do |env|
|
||||
end
|
||||
end
|
||||
|
||||
dark_mode = env.params.query["dark_mode"]? || preferences.dark_mode.to_s
|
||||
dark_mode = dark_mode == "true"
|
||||
dark_mode = convert_theme(env.params.query["dark_mode"]?) || preferences.dark_mode.to_s
|
||||
|
||||
thin_mode = env.params.query["thin_mode"]? || preferences.thin_mode.to_s
|
||||
thin_mode = thin_mode == "true"
|
||||
@ -1528,8 +1527,7 @@ post "/preferences" do |env|
|
||||
locale ||= CONFIG.default_user_preferences.locale
|
||||
|
||||
dark_mode = env.params.body["dark_mode"]?.try &.as(String)
|
||||
dark_mode ||= "off"
|
||||
dark_mode = dark_mode == "on"
|
||||
dark_mode ||= CONFIG.default_user_preferences.dark_mode
|
||||
|
||||
thin_mode = env.params.body["thin_mode"]?.try &.as(String)
|
||||
thin_mode ||= "off"
|
||||
@ -1553,6 +1551,7 @@ post "/preferences" do |env|
|
||||
notifications_only ||= "off"
|
||||
notifications_only = notifications_only == "on"
|
||||
|
||||
# Convert to JSON and back again to take advantage of converters used for compatability
|
||||
preferences = Preferences.from_json({
|
||||
annotations: annotations,
|
||||
annotations_subscribed: annotations_subscribed,
|
||||
@ -1648,12 +1647,27 @@ get "/toggle_theme" do |env|
|
||||
if user = env.get? "user"
|
||||
user = user.as(User)
|
||||
preferences = user.preferences
|
||||
preferences.dark_mode = !preferences.dark_mode
|
||||
|
||||
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences.to_json, user.email)
|
||||
case preferences.dark_mode
|
||||
when "dark"
|
||||
preferences.dark_mode = "light"
|
||||
else
|
||||
preferences.dark_mode = "dark"
|
||||
end
|
||||
|
||||
preferences = preferences.to_json
|
||||
|
||||
PG_DB.exec("UPDATE users SET preferences = $1 WHERE email = $2", preferences, user.email)
|
||||
else
|
||||
preferences = env.get("preferences").as(Preferences)
|
||||
preferences.dark_mode = !preferences.dark_mode
|
||||
|
||||
case preferences.dark_mode
|
||||
when "dark"
|
||||
preferences.dark_mode = "light"
|
||||
else
|
||||
preferences.dark_mode = "dark"
|
||||
end
|
||||
|
||||
preferences = preferences.to_json
|
||||
|
||||
if Kemal.config.ssl || config.https_only
|
||||
@ -2026,7 +2040,7 @@ post "/data_control" do |env|
|
||||
env.response.puts %(<meta http-equiv="refresh" content="0; url=#{referer}">)
|
||||
env.response.puts %(<link rel="stylesheet" href="/css/ionicons.min.css?v=#{ASSET_COMMIT}">)
|
||||
env.response.puts %(<link rel="stylesheet" href="/css/default.css?v=#{ASSET_COMMIT}">)
|
||||
if env.get("preferences").as(Preferences).dark_mode
|
||||
if env.get("preferences").as(Preferences).dark_mode == "dark"
|
||||
env.response.puts %(<link rel="stylesheet" href="/css/darktheme.css?v=#{ASSET_COMMIT}">)
|
||||
else
|
||||
env.response.puts %(<link rel="stylesheet" href="/css/lighttheme.css?v=#{ASSET_COMMIT}">)
|
||||
|
@ -24,6 +24,27 @@ end
|
||||
|
||||
struct ConfigPreferences
|
||||
module StringToArray
|
||||
def self.to_json(value : Array(String), json : JSON::Builder)
|
||||
json.array do
|
||||
value.each do |element|
|
||||
json.string element
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.from_json(value : JSON::PullParser) : Array(String)
|
||||
begin
|
||||
result = [] of String
|
||||
value.read_array do
|
||||
result << HTML.escape(value.read_string[0, 100])
|
||||
end
|
||||
rescue ex
|
||||
result = [HTML.escape(value.read_string[0, 100]), ""]
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def self.to_yaml(value : Array(String), yaml : YAML::Nodes::Builder)
|
||||
yaml.sequence do
|
||||
value.each do |element|
|
||||
@ -44,11 +65,11 @@ struct ConfigPreferences
|
||||
node.raise "Expected scalar, not #{item.class}"
|
||||
end
|
||||
|
||||
result << item.value
|
||||
result << HTML.escape(item.value[0, 100])
|
||||
end
|
||||
rescue ex
|
||||
if node.is_a?(YAML::Nodes::Scalar)
|
||||
result = [node.value, ""]
|
||||
result = [HTML.escape(node.value[0, 100]), ""]
|
||||
else
|
||||
result = ["", ""]
|
||||
end
|
||||
@ -58,6 +79,53 @@ struct ConfigPreferences
|
||||
end
|
||||
end
|
||||
|
||||
module BoolToString
|
||||
def self.to_json(value : String, json : JSON::Builder)
|
||||
json.string value
|
||||
end
|
||||
|
||||
def self.from_json(value : JSON::PullParser) : String
|
||||
begin
|
||||
result = value.read_string
|
||||
|
||||
if result.empty?
|
||||
CONFIG.default_user_preferences.dark_mode
|
||||
else
|
||||
result
|
||||
end
|
||||
rescue ex
|
||||
result = value.read_bool
|
||||
|
||||
if result
|
||||
"dark"
|
||||
else
|
||||
"light"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.to_yaml(value : String, yaml : YAML::Nodes::Builder)
|
||||
yaml.scalar value
|
||||
end
|
||||
|
||||
def self.from_yaml(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : String
|
||||
unless node.is_a?(YAML::Nodes::Scalar)
|
||||
node.raise "Expected sequence, not #{node.class}"
|
||||
end
|
||||
|
||||
case node.value
|
||||
when "true"
|
||||
"dark"
|
||||
when "false"
|
||||
"light"
|
||||
when ""
|
||||
CONFIG.default_user_preferences.dark_mode
|
||||
else
|
||||
node.value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
yaml_mapping({
|
||||
annotations: {type: Bool, default: false},
|
||||
annotations_subscribed: {type: Bool, default: false},
|
||||
@ -66,7 +134,7 @@ struct ConfigPreferences
|
||||
comments: {type: Array(String), default: ["youtube", ""], converter: StringToArray},
|
||||
continue: {type: Bool, default: false},
|
||||
continue_autoplay: {type: Bool, default: true},
|
||||
dark_mode: {type: Bool, default: false},
|
||||
dark_mode: {type: String, default: "light", converter: BoolToString},
|
||||
latest_only: {type: Bool, default: false},
|
||||
listen: {type: Bool, default: false},
|
||||
local: {type: Bool, default: false},
|
||||
|
@ -4,7 +4,7 @@ def Object.from_json(string_or_io, default) : self
|
||||
new parser, default
|
||||
end
|
||||
|
||||
# Adds configurable 'default' to
|
||||
# Adds configurable 'default'
|
||||
macro patched_json_mapping(_properties_, strict = false)
|
||||
{% for key, value in _properties_ %}
|
||||
{% _properties_[key] = {type: value} unless value.is_a?(HashLiteral) || value.is_a?(NamedTupleLiteral) %}
|
||||
|
@ -356,3 +356,16 @@ def parse_range(range)
|
||||
|
||||
return 0_i64, nil
|
||||
end
|
||||
|
||||
def convert_theme(theme)
|
||||
case theme
|
||||
when "true"
|
||||
"dark"
|
||||
when "false"
|
||||
"light"
|
||||
when "", nil
|
||||
nil
|
||||
else
|
||||
theme
|
||||
end
|
||||
end
|
||||
|
@ -31,62 +31,6 @@ struct User
|
||||
end
|
||||
|
||||
struct Preferences
|
||||
module StringToArray
|
||||
def self.to_json(value : Array(String), json : JSON::Builder)
|
||||
json.array do
|
||||
value.each do |element|
|
||||
json.string element
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.from_json(value : JSON::PullParser) : Array(String)
|
||||
begin
|
||||
result = [] of String
|
||||
value.read_array do
|
||||
result << HTML.escape(value.read_string[0, 100])
|
||||
end
|
||||
rescue ex
|
||||
result = [HTML.escape(value.read_string[0, 100]), ""]
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def self.to_yaml(value : Array(String), yaml : YAML::Nodes::Builder)
|
||||
yaml.sequence do
|
||||
value.each do |element|
|
||||
yaml.scalar element
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.from_yaml(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : Array(String)
|
||||
begin
|
||||
unless node.is_a?(YAML::Nodes::Sequence)
|
||||
node.raise "Expected sequence, not #{node.class}"
|
||||
end
|
||||
|
||||
result = [] of String
|
||||
node.nodes.each do |item|
|
||||
unless item.is_a?(YAML::Nodes::Scalar)
|
||||
node.raise "Expected scalar, not #{item.class}"
|
||||
end
|
||||
|
||||
result << HTML.escape(item.value[0, 100])
|
||||
end
|
||||
rescue ex
|
||||
if node.is_a?(YAML::Nodes::Scalar)
|
||||
result = [HTML.escape(node.value[0, 100]), ""]
|
||||
else
|
||||
result = ["", ""]
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
module ProcessString
|
||||
def self.to_json(value : String, json : JSON::Builder)
|
||||
json.string value
|
||||
@ -127,11 +71,11 @@ struct Preferences
|
||||
annotations: {type: Bool, default: CONFIG.default_user_preferences.annotations},
|
||||
annotations_subscribed: {type: Bool, default: CONFIG.default_user_preferences.annotations_subscribed},
|
||||
autoplay: {type: Bool, default: CONFIG.default_user_preferences.autoplay},
|
||||
captions: {type: Array(String), default: CONFIG.default_user_preferences.captions, converter: StringToArray},
|
||||
comments: {type: Array(String), default: CONFIG.default_user_preferences.comments, converter: StringToArray},
|
||||
captions: {type: Array(String), default: CONFIG.default_user_preferences.captions, converter: ConfigPreferences::StringToArray},
|
||||
comments: {type: Array(String), default: CONFIG.default_user_preferences.comments, converter: ConfigPreferences::StringToArray},
|
||||
continue: {type: Bool, default: CONFIG.default_user_preferences.continue},
|
||||
continue_autoplay: {type: Bool, default: CONFIG.default_user_preferences.continue_autoplay},
|
||||
dark_mode: {type: Bool, default: CONFIG.default_user_preferences.dark_mode},
|
||||
dark_mode: {type: String, default: CONFIG.default_user_preferences.dark_mode, converter: ConfigPreferences::BoolToString},
|
||||
latest_only: {type: Bool, default: CONFIG.default_user_preferences.latest_only},
|
||||
listen: {type: Bool, default: CONFIG.default_user_preferences.listen},
|
||||
local: {type: Bool, default: CONFIG.default_user_preferences.local},
|
||||
|
@ -122,8 +122,12 @@ function update_value(element) {
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label for="dark_mode"><%= translate(locale, "Dark mode: ") %></label>
|
||||
<input name="dark_mode" id="dark_mode" type="checkbox" <% if preferences.dark_mode %>checked<% end %>>
|
||||
<label for="dark_mode"><%= translate(locale, "Theme: ") %></label>
|
||||
<select name="dark_mode" id="dark_mode">
|
||||
<% {"", "light", "dark"}.each do |option| %>
|
||||
<option value="<%= option %>" <% if preferences.dark_mode == option %> selected <% end %>><%= translate(locale, option) %></option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
|
@ -18,8 +18,8 @@
|
||||
<link rel="stylesheet" href="/css/grids-responsive-min.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/ionicons.min.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/default.css?v=<%= ASSET_COMMIT %>">
|
||||
<link rel="stylesheet" href="/css/darktheme.css?v=<%= ASSET_COMMIT %>" id="dark_theme" <% if !env.get("preferences").as(Preferences).dark_mode %>media="none"<% end %>>
|
||||
<link rel="stylesheet" href="/css/lighttheme.css?v=<%= ASSET_COMMIT %>" id="light_theme" <% if env.get("preferences").as(Preferences).dark_mode %>media="none"<% end %>>
|
||||
<link rel="stylesheet" href="/css/darktheme.css?v=<%= ASSET_COMMIT %>" id="dark_theme" <% if env.get("preferences").as(Preferences).dark_mode != "dark" %>media="none"<% end %>>
|
||||
<link rel="stylesheet" href="/css/lighttheme.css?v=<%= ASSET_COMMIT %>" id="light_theme" <% if env.get("preferences").as(Preferences).dark_mode != "light" %>media="none"<% end %>>
|
||||
</head>
|
||||
|
||||
<% locale = LOCALES[env.get("preferences").as(Preferences).locale]? %>
|
||||
@ -43,7 +43,7 @@
|
||||
<% if env.get? "user" %>
|
||||
<div class="pure-u-1-4">
|
||||
<a id="toggle_theme" href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<% if env.get("preferences").as(Preferences).dark_mode %>
|
||||
<% if env.get("preferences").as(Preferences).dark_mode == "dark" %>
|
||||
<i class="icon ion-ios-sunny"></i>
|
||||
<% else %>
|
||||
<i class="icon ion-ios-moon"></i>
|
||||
@ -76,7 +76,7 @@
|
||||
<% else %>
|
||||
<div class="pure-u-1-3">
|
||||
<a id="toggle_theme" href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
||||
<% if env.get("preferences").as(Preferences).dark_mode %>
|
||||
<% if env.get("preferences").as(Preferences).dark_mode == "dark" %>
|
||||
<i class="icon ion-ios-sunny"></i>
|
||||
<% else %>
|
||||
<i class="icon ion-ios-moon"></i>
|
||||
|
Loading…
Reference in New Issue
Block a user