mirror of
https://github.com/iv-org/invidious.git
synced 2025-08-06 04:38:31 +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
|
||||||
end
|
end
|
||||||
|
|
||||||
dark_mode = env.params.query["dark_mode"]? || preferences.dark_mode.to_s
|
dark_mode = convert_theme(env.params.query["dark_mode"]?) || preferences.dark_mode.to_s
|
||||||
dark_mode = dark_mode == "true"
|
|
||||||
|
|
||||||
thin_mode = env.params.query["thin_mode"]? || preferences.thin_mode.to_s
|
thin_mode = env.params.query["thin_mode"]? || preferences.thin_mode.to_s
|
||||||
thin_mode = thin_mode == "true"
|
thin_mode = thin_mode == "true"
|
||||||
@ -1528,8 +1527,7 @@ post "/preferences" do |env|
|
|||||||
locale ||= CONFIG.default_user_preferences.locale
|
locale ||= CONFIG.default_user_preferences.locale
|
||||||
|
|
||||||
dark_mode = env.params.body["dark_mode"]?.try &.as(String)
|
dark_mode = env.params.body["dark_mode"]?.try &.as(String)
|
||||||
dark_mode ||= "off"
|
dark_mode ||= CONFIG.default_user_preferences.dark_mode
|
||||||
dark_mode = dark_mode == "on"
|
|
||||||
|
|
||||||
thin_mode = env.params.body["thin_mode"]?.try &.as(String)
|
thin_mode = env.params.body["thin_mode"]?.try &.as(String)
|
||||||
thin_mode ||= "off"
|
thin_mode ||= "off"
|
||||||
@ -1553,6 +1551,7 @@ post "/preferences" do |env|
|
|||||||
notifications_only ||= "off"
|
notifications_only ||= "off"
|
||||||
notifications_only = notifications_only == "on"
|
notifications_only = notifications_only == "on"
|
||||||
|
|
||||||
|
# Convert to JSON and back again to take advantage of converters used for compatability
|
||||||
preferences = Preferences.from_json({
|
preferences = Preferences.from_json({
|
||||||
annotations: annotations,
|
annotations: annotations,
|
||||||
annotations_subscribed: annotations_subscribed,
|
annotations_subscribed: annotations_subscribed,
|
||||||
@ -1648,12 +1647,27 @@ get "/toggle_theme" do |env|
|
|||||||
if user = env.get? "user"
|
if user = env.get? "user"
|
||||||
user = user.as(User)
|
user = user.as(User)
|
||||||
preferences = user.preferences
|
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
|
else
|
||||||
preferences = env.get("preferences").as(Preferences)
|
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
|
preferences = preferences.to_json
|
||||||
|
|
||||||
if Kemal.config.ssl || config.https_only
|
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 %(<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/ionicons.min.css?v=#{ASSET_COMMIT}">)
|
||||||
env.response.puts %(<link rel="stylesheet" href="/css/default.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}">)
|
env.response.puts %(<link rel="stylesheet" href="/css/darktheme.css?v=#{ASSET_COMMIT}">)
|
||||||
else
|
else
|
||||||
env.response.puts %(<link rel="stylesheet" href="/css/lighttheme.css?v=#{ASSET_COMMIT}">)
|
env.response.puts %(<link rel="stylesheet" href="/css/lighttheme.css?v=#{ASSET_COMMIT}">)
|
||||||
|
@ -24,6 +24,27 @@ end
|
|||||||
|
|
||||||
struct ConfigPreferences
|
struct ConfigPreferences
|
||||||
module StringToArray
|
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)
|
def self.to_yaml(value : Array(String), yaml : YAML::Nodes::Builder)
|
||||||
yaml.sequence do
|
yaml.sequence do
|
||||||
value.each do |element|
|
value.each do |element|
|
||||||
@ -44,11 +65,11 @@ struct ConfigPreferences
|
|||||||
node.raise "Expected scalar, not #{item.class}"
|
node.raise "Expected scalar, not #{item.class}"
|
||||||
end
|
end
|
||||||
|
|
||||||
result << item.value
|
result << HTML.escape(item.value[0, 100])
|
||||||
end
|
end
|
||||||
rescue ex
|
rescue ex
|
||||||
if node.is_a?(YAML::Nodes::Scalar)
|
if node.is_a?(YAML::Nodes::Scalar)
|
||||||
result = [node.value, ""]
|
result = [HTML.escape(node.value[0, 100]), ""]
|
||||||
else
|
else
|
||||||
result = ["", ""]
|
result = ["", ""]
|
||||||
end
|
end
|
||||||
@ -58,6 +79,53 @@ struct ConfigPreferences
|
|||||||
end
|
end
|
||||||
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({
|
yaml_mapping({
|
||||||
annotations: {type: Bool, default: false},
|
annotations: {type: Bool, default: false},
|
||||||
annotations_subscribed: {type: Bool, default: false},
|
annotations_subscribed: {type: Bool, default: false},
|
||||||
@ -66,7 +134,7 @@ struct ConfigPreferences
|
|||||||
comments: {type: Array(String), default: ["youtube", ""], converter: StringToArray},
|
comments: {type: Array(String), default: ["youtube", ""], converter: StringToArray},
|
||||||
continue: {type: Bool, default: false},
|
continue: {type: Bool, default: false},
|
||||||
continue_autoplay: {type: Bool, default: true},
|
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},
|
latest_only: {type: Bool, default: false},
|
||||||
listen: {type: Bool, default: false},
|
listen: {type: Bool, default: false},
|
||||||
local: {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
|
new parser, default
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds configurable 'default' to
|
# Adds configurable 'default'
|
||||||
macro patched_json_mapping(_properties_, strict = false)
|
macro patched_json_mapping(_properties_, strict = false)
|
||||||
{% for key, value in _properties_ %}
|
{% for key, value in _properties_ %}
|
||||||
{% _properties_[key] = {type: value} unless value.is_a?(HashLiteral) || value.is_a?(NamedTupleLiteral) %}
|
{% _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
|
return 0_i64, nil
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
struct Preferences
|
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
|
module ProcessString
|
||||||
def self.to_json(value : String, json : JSON::Builder)
|
def self.to_json(value : String, json : JSON::Builder)
|
||||||
json.string value
|
json.string value
|
||||||
@ -127,11 +71,11 @@ struct Preferences
|
|||||||
annotations: {type: Bool, default: CONFIG.default_user_preferences.annotations},
|
annotations: {type: Bool, default: CONFIG.default_user_preferences.annotations},
|
||||||
annotations_subscribed: {type: Bool, default: CONFIG.default_user_preferences.annotations_subscribed},
|
annotations_subscribed: {type: Bool, default: CONFIG.default_user_preferences.annotations_subscribed},
|
||||||
autoplay: {type: Bool, default: CONFIG.default_user_preferences.autoplay},
|
autoplay: {type: Bool, default: CONFIG.default_user_preferences.autoplay},
|
||||||
captions: {type: Array(String), default: CONFIG.default_user_preferences.captions, 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: StringToArray},
|
comments: {type: Array(String), default: CONFIG.default_user_preferences.comments, converter: ConfigPreferences::StringToArray},
|
||||||
continue: {type: Bool, default: CONFIG.default_user_preferences.continue},
|
continue: {type: Bool, default: CONFIG.default_user_preferences.continue},
|
||||||
continue_autoplay: {type: Bool, default: CONFIG.default_user_preferences.continue_autoplay},
|
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},
|
latest_only: {type: Bool, default: CONFIG.default_user_preferences.latest_only},
|
||||||
listen: {type: Bool, default: CONFIG.default_user_preferences.listen},
|
listen: {type: Bool, default: CONFIG.default_user_preferences.listen},
|
||||||
local: {type: Bool, default: CONFIG.default_user_preferences.local},
|
local: {type: Bool, default: CONFIG.default_user_preferences.local},
|
||||||
|
@ -122,8 +122,12 @@ function update_value(element) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<label for="dark_mode"><%= translate(locale, "Dark mode: ") %></label>
|
<label for="dark_mode"><%= translate(locale, "Theme: ") %></label>
|
||||||
<input name="dark_mode" id="dark_mode" type="checkbox" <% if preferences.dark_mode %>checked<% end %>>
|
<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>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<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/grids-responsive-min.css?v=<%= ASSET_COMMIT %>">
|
||||||
<link rel="stylesheet" href="/css/ionicons.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/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/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 %>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>
|
</head>
|
||||||
|
|
||||||
<% locale = LOCALES[env.get("preferences").as(Preferences).locale]? %>
|
<% locale = LOCALES[env.get("preferences").as(Preferences).locale]? %>
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<% if env.get? "user" %>
|
<% if env.get? "user" %>
|
||||||
<div class="pure-u-1-4">
|
<div class="pure-u-1-4">
|
||||||
<a id="toggle_theme" href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
<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>
|
<i class="icon ion-ios-sunny"></i>
|
||||||
<% else %>
|
<% else %>
|
||||||
<i class="icon ion-ios-moon"></i>
|
<i class="icon ion-ios-moon"></i>
|
||||||
@ -76,7 +76,7 @@
|
|||||||
<% else %>
|
<% else %>
|
||||||
<div class="pure-u-1-3">
|
<div class="pure-u-1-3">
|
||||||
<a id="toggle_theme" href="/toggle_theme?referer=<%= env.get?("current_page") %>" class="pure-menu-heading">
|
<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>
|
<i class="icon ion-ios-sunny"></i>
|
||||||
<% else %>
|
<% else %>
|
||||||
<i class="icon ion-ios-moon"></i>
|
<i class="icon ion-ios-moon"></i>
|
||||||
|
Loading…
Reference in New Issue
Block a user