Class: ColorScheme
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- ColorScheme
- Defined in:
- app/models/color_scheme.rb
Constant Summary collapse
- CUSTOM_SCHEMES =
rubocop:disable Layout/HashAlignment
{ Dark: { "primary" => "dddddd", "secondary" => "222222", "tertiary" => "099dd7", "quaternary" => "c14924", "header_background" => "111111", "header_primary" => "dddddd", "highlight" => "a87137", "selected" => "2c2c2c", "hover" => "313131", "danger" => "e45735", "success" => "1ca551", "love" => "fa6c8d", }, # By @itsbhanusharma Neutral: { "primary" => "000000", "secondary" => "ffffff", "tertiary" => "51839b", "quaternary" => "b85e48", "header_background" => "333333", "header_primary" => "f3f3f3", "highlight" => "ecec70", "selected" => "e6e6e6", "hover" => "f0f0f0", "danger" => "b85e48", "success" => "518751", "love" => "fa6c8d", }, # By @Flower_Child "Grey Amber": { "primary" => "d9d9d9", "secondary" => "3d4147", "tertiary" => "fdd459", "quaternary" => "fdd459", "header_background" => "36393e", "header_primary" => "d9d9d9", "highlight" => "fdd459", "selected" => "272727", "hover" => "2F2F30", "danger" => "e45735", "success" => "fdd459", "love" => "fdd459", }, # By @rafafotes "Shades of Blue": { "primary" => "203243", "secondary" => "eef4f7", "tertiary" => "416376", "quaternary" => "5e99b9", "header_background" => "86bddb", "header_primary" => "203243", "highlight" => "86bddb", "selected" => "bee0f2", "hover" => "d2efff", "danger" => "bf3c3c", "success" => "70db82", "love" => "fc94cb", }, # By @mikechristopher Latte: { "primary" => "f2e5d7", "secondary" => "262322", "tertiary" => "f7f2ed", "quaternary" => "d7c9aa", "header_background" => "d7c9aa", "header_primary" => "262322", "highlight" => "d7c9aa", "selected" => "3e2a14", "hover" => "4c3319", "danger" => "db9584", "success" => "78be78", "love" => "8f6201", }, # By @Flower_Child Summer: { "primary" => "874342", "secondary" => "fffff4", "tertiary" => "fe9896", "quaternary" => "fcc9d0", "header_background" => "96ccbf", "header_primary" => "fff1e7", "highlight" => "f3c07f", "selected" => "f5eaea", "hover" => "f9f3f3", "danger" => "cfebdc", "success" => "fcb4b5", "love" => "f3c07f", }, # By @Flower_Child "Dark Rose": { "primary" => "ca9cb2", "secondary" => "3a2a37", "tertiary" => "fdd459", "quaternary" => "7e566a", "header_background" => "a97189", "header_primary" => "d9b2bb", "highlight" => "bd36a3", "selected" => "2a1620", "hover" => "331b27", "danger" => "6c3e63", "success" => "d9b2bb", "love" => "d9b2bb", }, WCAG: { "primary" => "000000", "primary-medium" => "696969", "primary-low-mid" => "909090", "secondary" => "ffffff", "tertiary" => "0033CC", "quaternary" => "3369FF", "header_background" => "ffffff", "header_primary" => "000000", "highlight" => "ffff00", "highlight-high" => "0036E6", "highlight-medium" => "e0e9ff", "highlight-low" => "e0e9ff", "selected" => "E2E9FE", "hover" => "F0F4FE", "danger" => "BB1122", "success" => "3d854d", "love" => "9D256B", }, "WCAG Dark": { "primary" => "ffffff", "primary-medium" => "999999", "primary-low-mid" => "888888", "secondary" => "0c0c0c", "tertiary" => "759AFF", "quaternary" => "759AFF", "header_background" => "000000", "header_primary" => "ffffff", "highlight" => "3369FF", "selected" => "0d2569", "hover" => "002382", "danger" => "FF697A", "success" => "70B880", "love" => "9D256B", }, # By @zenorocha Dracula: { "primary_very_low" => "373A47", "primary_low" => "414350", "primary_low_mid" => "8C8D94", "primary_medium" => "A3A4AA", "primary_high" => "CCCCCF", "primary" => "f2f2f2", "primary-50" => "3F414E", "primary-100" => "535460", "primary-200" => "666972", "primary-300" => "7A7C84", "primary-400" => "8D8F96", "primary-500" => "A2A3A9", "primary-600" => "B6B7BC", "primary-700" => "C7C7C7", "primary-800" => "DEDFE0", "primary-900" => "F5F5F5", "secondary_low" => "CCCCCF", "secondary_medium" => "91939A", "secondary_high" => "6A6C76", "secondary_very_high" => "3D404C", "secondary" => "2d303e", "tertiary_low" => "4A4463", "tertiary_medium" => "6E5D92", "tertiary" => "bd93f9", "tertiary_high" => "9275C1", "quaternary_low" => "6AA8BA", "quaternary" => "8be9fd", "header_background" => "373A47", "header_primary" => "f2f2f2", "highlight_low" => "686D55", "highlight_medium" => "52592B", "highlight_high" => "C0C879", "selected" => "4A4463", "hover" => "61597f", "danger_low" => "957279", "danger" => "ff5555", "success_low" => "386D50", "success_medium" => "44B366", "success" => "50fa7b", "love_low" => "6C4667", "love" => "ff79c6", }, # By @altercation "Solarized Light": { "primary_very_low" => "F0ECD7", "primary_low" => "D6D8C7", "primary_low_mid" => "A4AFA5", "primary_medium" => "7E918C", "primary_high" => "4C6869", "primary" => "002B36", "primary-50" => "F0EBDA", "primary-100" => "DAD8CA", "primary-200" => "B2B9B3", "primary-300" => "839496", "primary-400" => "76898C", "primary-500" => "697F83", "primary-600" => "627A7E", "primary-700" => "556F74", "primary-800" => "415F66", "primary-900" => "21454E", "secondary_low" => "325458", "secondary_medium" => "6C8280", "secondary_high" => "97A59D", "secondary_very_high" => "E8E6D3", "secondary" => "FCF6E1", "tertiary_low" => "D6E6DE", "tertiary_medium" => "7EBFD7", "tertiary" => "0088cc", "tertiary_high" => "329ED0", "quaternary" => "e45735", "header_background" => "FCF6E1", "header_primary" => "002B36", "highlight_low" => "FDF9AD", "highlight_medium" => "E3D0A3", "highlight" => "F2F481", "highlight_high" => "BCAA7F", "selected" => "E8E6D3", "hover" => "F0EBDA", "danger_low" => "F8D9C2", "danger" => "e45735", "success_low" => "CFE5B9", "success_medium" => "4CB544", "success" => "009900", "love_low" => "FCDDD2", "love" => "fa6c8d", }, # By @altercation "Solarized Dark": { "primary_very_low" => "0D353F", "primary_low" => "193F47", "primary_low_mid" => "798C88", "primary_medium" => "97A59D", "primary_high" => "B5BDB1", "primary" => "FCF6E1", "primary-50" => "21454E", "primary-100" => "415F66", "primary-200" => "556F74", "primary-300" => "627A7E", "primary-400" => "697F83", "primary-500" => "76898C", "primary-600" => "839496", "primary-700" => "B2B9B3", "primary-800" => "DAD8CA", "primary-900" => "F0EBDA", "secondary_low" => "B5BDB1", "secondary_medium" => "81938D", "secondary_high" => "4E6A6B", "secondary_very_high" => "143B44", "secondary" => "002B36", "tertiary_low" => "003E54", "tertiary_medium" => "00557A", "tertiary" => "1a97d5", "tertiary_high" => "006C9F", "quaternary_low" => "944835", "quaternary" => "e45735", "header_background" => "002B36", "header_primary" => "FCF6E1", "highlight_low" => "4D6B3D", "highlight_medium" => "464C33", "highlight" => "F2F481", "highlight_high" => "BFCA47", "selected" => "143B44", "hover" => "21454E", "danger_low" => "443836", "danger_medium" => "944835", "danger" => "e45735", "success_low" => "004C26", "success_medium" => "007313", "success" => "009900", "love_low" => "4B3F50", "love" => "fa6c8d", }, }
- LIGHT_THEME_ID =
rubocop:enable Layout/HashAlignment
"Light"
- BASE_COLORS_FILE =
"#{Rails.root}/app/assets/stylesheets/common/foundation/colors.scss"
- COLOR_TRANSFORMATION_FILE =
"#{Rails.root}/app/assets/stylesheets/common/foundation/color_transformations.scss"
Instance Attribute Summary collapse
-
#is_base ⇒ Object
Returns the value of attribute is_base.
-
#skip_publish ⇒ Object
Returns the value of attribute skip_publish.
Class Method Summary collapse
- .base ⇒ Object
- .base_color_scheme_colors ⇒ Object
- .base_color_schemes ⇒ Object
- .base_colors ⇒ Object
- .color_transformation_variables ⇒ Object
-
.create_from_base(params) ⇒ Object
create_from_base will create a new ColorScheme that overrides Discourse’s base color scheme with the given colors.
- .hex_cache ⇒ Object
- .hex_for_name(name, scheme_id = nil) ⇒ Object
- .is_base?(scheme_name) ⇒ Boolean
- .lookup_hex_for_name(name, scheme_id = nil) ⇒ Object
- .publish_discourse_stylesheets!(id = nil) ⇒ Object
Instance Method Summary collapse
- #base_colors ⇒ Object
- #bump_version ⇒ Object
- #clear_colors_cache ⇒ Object
- #colors=(arr) ⇒ Object
- #colors_by_name ⇒ Object
- #colors_hashes ⇒ Object
- #dump_caches ⇒ Object
- #is_dark? ⇒ Boolean
- #is_wcag? ⇒ Boolean
- #publish_discourse_stylesheet ⇒ Object
- #resolved_colors ⇒ Object
Instance Attribute Details
#is_base ⇒ Object
Returns the value of attribute is_base.
306 307 308 |
# File 'app/models/color_scheme.rb', line 306 def is_base @is_base end |
#skip_publish ⇒ Object
Returns the value of attribute skip_publish.
307 308 309 |
# File 'app/models/color_scheme.rb', line 307 def skip_publish @skip_publish end |
Class Method Details
.base ⇒ Object
372 373 374 375 376 377 378 |
# File 'app/models/color_scheme.rb', line 372 def self.base return @base_color_scheme if @base_color_scheme @base_color_scheme = new(name: I18n.t("color_schemes.base_theme_name")) @base_color_scheme.colors = base_colors.map { |name, hex| { name: name, hex: hex } } @base_color_scheme.is_base = true @base_color_scheme end |
.base_color_scheme_colors ⇒ Object
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'app/models/color_scheme.rb', line 286 def self.base_color_scheme_colors base_with_hash = [] base_colors.each { |name, color| base_with_hash << { name: name, hex: "#{color}" } } list = [{ id: LIGHT_THEME_ID, colors: base_with_hash }] CUSTOM_SCHEMES.each do |k, v| colors = [] v.each { |name, color| colors << { name: name, hex: "#{color}" } } list.push(id: k.to_s, colors: colors) end list end |
.base_color_schemes ⇒ Object
359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'app/models/color_scheme.rb', line 359 def self.base_color_schemes base_color_scheme_colors.map do |hash| scheme = new( name: I18n.t("color_schemes.#{hash[:id].downcase.gsub(" ", "_")}"), base_scheme_id: hash[:id], ) scheme.colors = hash[:colors].map { |k| { name: k[:name], hex: k[:hex] } } scheme.is_base = true scheme end end |
.base_colors ⇒ Object
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
# File 'app/models/color_scheme.rb', line 327 def self.base_colors return @base_colors if @base_colors @mutex.synchronize do return @base_colors if @base_colors base_colors = {} File .readlines(BASE_COLORS_FILE) .each do |line| matches = /\$([\w]+):\s*#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:[;]|\s)/.match(line.strip) base_colors[matches[1]] = matches[2] if matches end @base_colors = base_colors end @base_colors end |
.color_transformation_variables ⇒ Object
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# File 'app/models/color_scheme.rb', line 343 def self.color_transformation_variables return @transformation_variables if @transformation_variables @mutex.synchronize do return @transformation_variables if @transformation_variables transformation_variables = [] File .readlines(COLOR_TRANSFORMATION_FILE) .each do |line| matches = /\$([\w\-_]+):.*/.match(line.strip) transformation_variables.append(matches[1]) if matches end @transformation_variables = transformation_variables end @transformation_variables end |
.create_from_base(params) ⇒ Object
create_from_base will create a new ColorScheme that overrides Discourse’s base color scheme with the given colors.
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'app/models/color_scheme.rb', line 385 def self.create_from_base(params) new_color_scheme = new(name: params[:name]) new_color_scheme.via_wizard = true if params[:via_wizard] new_color_scheme.base_scheme_id = params[:base_scheme_id] new_color_scheme.user_selectable = true colors = CUSTOM_SCHEMES[params[:base_scheme_id].to_sym]&.map do |name, hex| { name: name, hex: hex } end if params[:base_scheme_id] colors ||= base.colors_hashes # Override base values params[:colors].each do |name, hex| c = colors.find { |x| x[:name].to_s == name.to_s } c[:hex] = hex end if params[:colors] new_color_scheme.colors = colors new_color_scheme.skip_publish if params[:skip_publish] new_color_scheme.save new_color_scheme end |
.hex_cache ⇒ Object
302 303 304 |
# File 'app/models/color_scheme.rb', line 302 def self.hex_cache @hex_cache ||= DistributedCache.new("scheme_hex_for_name") end |
.hex_for_name(name, scheme_id = nil) ⇒ Object
415 416 417 418 419 |
# File 'app/models/color_scheme.rb', line 415 def self.hex_for_name(name, scheme_id = nil) hex_cache.defer_get_set(scheme_id ? name + "_#{scheme_id}" : name) do lookup_hex_for_name(name, scheme_id) end end |
.is_base?(scheme_name) ⇒ Boolean
380 381 382 |
# File 'app/models/color_scheme.rb', line 380 def self.is_base?(scheme_name) base_color_scheme_colors.map { |c| c[:id] }.include?(scheme_name) end |
.lookup_hex_for_name(name, scheme_id = nil) ⇒ Object
409 410 411 412 413 |
# File 'app/models/color_scheme.rb', line 409 def self.lookup_hex_for_name(name, scheme_id = nil) enabled_color_scheme = find_by(id: scheme_id) if scheme_id enabled_color_scheme ||= Theme.where(id: SiteSetting.default_theme_id).first&.color_scheme (enabled_color_scheme || base).colors.find { |c| c.name == name }.try(:hex) end |
.publish_discourse_stylesheets!(id = nil) ⇒ Object
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 |
# File 'app/models/color_scheme.rb', line 480 def self.publish_discourse_stylesheets!(id = nil) Stylesheet::Manager.clear_color_scheme_cache! theme_ids = [] if id theme_ids = Theme.where(color_scheme_id: id).pluck(:id) else theme_ids = Theme.all.pluck(:id) end if theme_ids.present? Stylesheet::Manager.cache.clear Theme.notify_theme_change( theme_ids, with_scheme: true, clear_manager_cache: false, all_themes: true, ) end end |
Instance Method Details
#base_colors ⇒ Object
444 445 446 447 448 |
# File 'app/models/color_scheme.rb', line 444 def base_colors colors = nil colors = CUSTOM_SCHEMES[base_scheme_id.to_sym] if base_scheme_id && base_scheme_id != "Light" colors || ColorScheme.base_colors end |
#bump_version ⇒ Object
506 507 508 |
# File 'app/models/color_scheme.rb', line 506 def bump_version self.version += 1 if self.id end |
#clear_colors_cache ⇒ Object
436 437 438 |
# File 'app/models/color_scheme.rb', line 436 def clear_colors_cache @colors_by_name = nil end |
#colors=(arr) ⇒ Object
421 422 423 424 |
# File 'app/models/color_scheme.rb', line 421 def colors=(arr) @colors_by_name = nil arr.each { |c| self.color_scheme_colors << ColorSchemeColor.new(name: c[:name], hex: c[:hex]) } end |
#colors_by_name ⇒ Object
426 427 428 429 430 431 432 433 434 |
# File 'app/models/color_scheme.rb', line 426 def colors_by_name @colors_by_name ||= self .colors .inject({}) do |sum, c| sum[c.name] = c sum end end |
#colors_hashes ⇒ Object
440 441 442 |
# File 'app/models/color_scheme.rb', line 440 def colors_hashes color_scheme_colors.map { |c| { name: c.name, hex: c.hex } } end |
#dump_caches ⇒ Object
501 502 503 504 |
# File 'app/models/color_scheme.rb', line 501 def dump_caches self.class.hex_cache.clear ApplicationSerializer.expire_cache_fragment!("user_color_schemes") end |
#is_dark? ⇒ Boolean
510 511 512 513 514 515 516 517 |
# File 'app/models/color_scheme.rb', line 510 def is_dark? return if colors.to_a.empty? primary_b = ColorMath.brightness(resolved_colors["primary"]) secondary_b = ColorMath.brightness(resolved_colors["secondary"]) primary_b > secondary_b end |
#is_wcag? ⇒ Boolean
519 520 521 |
# File 'app/models/color_scheme.rb', line 519 def is_wcag? base_scheme_id&.start_with?("WCAG") end |
#publish_discourse_stylesheet ⇒ Object
476 477 478 |
# File 'app/models/color_scheme.rb', line 476 def publish_discourse_stylesheet self.class.publish_discourse_stylesheets!(self.id) if self.id end |
#resolved_colors ⇒ Object
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
# File 'app/models/color_scheme.rb', line 450 def resolved_colors from_base = ColorScheme.base_colors from_custom_scheme = base_colors from_db = colors.map { |c| [c.name, c.hex] }.to_h resolved = from_base.merge(from_custom_scheme).except("hover", "selected").merge(from_db) # Equivalent to primary-100 in light mode, or primary-low in dark mode resolved["hover"] ||= ColorMath.dark_light_diff( resolved["primary"], resolved["secondary"], 0.94, -0.78, ) # Equivalent to primary-low in light mode, or primary-100 in dark mode resolved["selected"] ||= ColorMath.dark_light_diff( resolved["primary"], resolved["secondary"], 0.9, -0.8, ) resolved end |