From 08476f17ff641736b80f75fa5cbfa404fdba36ed Mon Sep 17 00:00:00 2001
From: Jan Cernik <66427541+cernikkk@users.noreply.github.com>
Date: Fri, 7 Oct 2022 12:00:44 -0300
Subject: [PATCH] FEATURE: Add dark mode option for category logos (#18460)
Adds a new upload field for a second dark mode category logo.
This alternative will be used when the browser is in dark mode (similar to the global site setting for a dark logo).
---
.../discourse/app/components/category-logo.js | 3 +++
.../app/components/edit-category-images.js | 13 +++++++++++++
.../discourse/app/models/category.js | 1 +
.../categories-boxes-with-topics.hbs | 2 +-
.../templates/components/categories-boxes.hbs | 6 ++++--
.../app/templates/components/category-logo.hbs | 10 ++++++++++
.../components/category-title-link.hbs | 2 +-
.../app/templates/components/cdn-img.hbs | 4 +---
.../components/edit-category-images.hbs | 5 +++++
.../app/templates/navigation/category.hbs | 3 +--
.../stylesheets/common/base/_topic-list.scss | 2 +-
.../stylesheets/common/base/category-list.scss | 8 ++++----
app/controllers/categories_controller.rb | 1 +
app/models/category.rb | 6 ++++--
app/models/category_list.rb | 1 +
app/models/site.rb | 2 +-
app/serializers/basic_category_serializer.rb | 1 +
config/locales/client.en.yml | 1 +
...4122343_add_dark_mode_logo_to_categories.rb | 7 +++++++
lib/tasks/site.rake | 1 +
lib/tasks/uploads.rake | 1 +
lib/upload_security.rb | 1 +
spec/jobs/clean_up_uploads_spec.rb | 18 ++++++++++++++----
spec/models/upload_reference_spec.rb | 7 ++++---
.../schemas/json/category_create_response.json | 7 +++++++
.../schemas/json/category_list_response.json | 7 +++++++
.../schemas/json/category_update_response.json | 7 +++++++
.../api/schemas/json/site_response.json | 7 +++++++
28 files changed, 110 insertions(+), 24 deletions(-)
create mode 100644 app/assets/javascripts/discourse/app/components/category-logo.js
create mode 100644 app/assets/javascripts/discourse/app/templates/components/category-logo.hbs
create mode 100644 db/migrate/20221004122343_add_dark_mode_logo_to_categories.rb
diff --git a/app/assets/javascripts/discourse/app/components/category-logo.js b/app/assets/javascripts/discourse/app/components/category-logo.js
new file mode 100644
index 00000000000..742bb3c18ef
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/category-logo.js
@@ -0,0 +1,3 @@
+import templateOnly from "@ember/component/template-only";
+
+export default templateOnly();
diff --git a/app/assets/javascripts/discourse/app/components/edit-category-images.js b/app/assets/javascripts/discourse/app/components/edit-category-images.js
index 174a8ed6148..a11669854f5 100644
--- a/app/assets/javascripts/discourse/app/components/edit-category-images.js
+++ b/app/assets/javascripts/discourse/app/components/edit-category-images.js
@@ -13,6 +13,11 @@ export default buildCategoryPanel("images").extend({
return uploadedLogoUrl || "";
},
+ @discourseComputed("category.uploaded_logo_dark.url")
+ logoImageDarkUrl(uploadedLogoDarkUrl) {
+ return uploadedLogoDarkUrl || "";
+ },
+
actions: {
logoUploadDone(upload) {
this._setFromUpload("category.uploaded_logo", upload);
@@ -22,6 +27,14 @@ export default buildCategoryPanel("images").extend({
this._deleteUpload("category.uploaded_logo");
},
+ logoDarkUploadDone(upload) {
+ this._setFromUpload("category.uploaded_logo_dark", upload);
+ },
+
+ logoDarkUploadDeleted() {
+ this._deleteUpload("category.uploaded_logo_dark");
+ },
+
backgroundUploadDone(upload) {
this._setFromUpload("category.uploaded_background", upload);
},
diff --git a/app/assets/javascripts/discourse/app/models/category.js b/app/assets/javascripts/discourse/app/models/category.js
index 5fff896ceed..2453ffc140d 100644
--- a/app/assets/javascripts/discourse/app/models/category.js
+++ b/app/assets/javascripts/discourse/app/models/category.js
@@ -216,6 +216,7 @@ const Category = RestModel.extend({
mailinglist_mirror: this.mailinglist_mirror,
parent_category_id: this.parent_category_id,
uploaded_logo_id: this.get("uploaded_logo.id"),
+ uploaded_logo_dark_id: this.get("uploaded_logo_dark.id"),
uploaded_background_id: this.get("uploaded_background.id"),
allow_badges: this.allow_badges,
custom_fields: this.custom_fields,
diff --git a/app/assets/javascripts/discourse/app/templates/components/categories-boxes-with-topics.hbs b/app/assets/javascripts/discourse/app/templates/components/categories-boxes-with-topics.hbs
index f2b2c622ec8..5a3b241b2c3 100644
--- a/app/assets/javascripts/discourse/app/templates/components/categories-boxes-with-topics.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/categories-boxes-with-topics.hbs
@@ -5,7 +5,7 @@
{{#unless c.isMuted}}
{{#if c.uploaded_logo.url}}
-
{{dir-span this.category.description htmlSafe="true"}}
{{/if}} diff --git a/app/assets/stylesheets/common/base/_topic-list.scss b/app/assets/stylesheets/common/base/_topic-list.scss index 90646ddcac3..b04e40e97c8 100644 --- a/app/assets/stylesheets/common/base/_topic-list.scss +++ b/app/assets/stylesheets/common/base/_topic-list.scss @@ -116,7 +116,7 @@ width: 100%; height: inherit; max-width: initial; - max-height: initial; + max-height: var(--max-height); } } } diff --git a/app/assets/stylesheets/common/base/category-list.scss b/app/assets/stylesheets/common/base/category-list.scss index 09f0f5682e7..f3b52df42fb 100644 --- a/app/assets/stylesheets/common/base/category-list.scss +++ b/app/assets/stylesheets/common/base/category-list.scss @@ -78,7 +78,7 @@ } } - .logo.aspect-image img { + .category-logo.aspect-image img { display: block; width: auto; height: 40px; @@ -86,7 +86,7 @@ } @supports (--custom: property) { - .logo.aspect-image img { + .category-logo.aspect-image img { --height: 40px; height: var(--height); width: calc(var(--height) * var(--aspect-ratio)); @@ -110,7 +110,7 @@ } &.no-logos { - .logo { + .category-logo { display: none; } } @@ -241,7 +241,7 @@ min-width: 0; @include ellipsis; } - .logo img { + .category-logo img { display: inline-block; --height: 20px; height: var(--height); diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 2ac24151601..33325cf61c2 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -353,6 +353,7 @@ class CategoriesController < ApplicationController :auto_close_hours, :auto_close_based_on_last_post, :uploaded_logo_id, + :uploaded_logo_dark_id, :uploaded_background_id, :slug, :allow_badges, diff --git a/app/models/category.rb b/app/models/category.rb index f9052ce3979..adafc49a0f2 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -35,6 +35,7 @@ class Category < ActiveRecord::Base belongs_to :user belongs_to :latest_post, class_name: "Post" belongs_to :uploaded_logo, class_name: "Upload" + belongs_to :uploaded_logo_dark, class_name: "Upload" belongs_to :uploaded_background, class_name: "Upload" has_many :topics @@ -82,8 +83,8 @@ class Category < ActiveRecord::Base after_save :update_reviewables after_save do - if saved_change_to_uploaded_logo_id? || saved_change_to_uploaded_background_id? - upload_ids = [self.uploaded_logo_id, self.uploaded_background_id] + if saved_change_to_uploaded_logo_id? || saved_change_to_uploaded_logo_dark_id? || saved_change_to_uploaded_background_id? + upload_ids = [self.uploaded_logo_id, self.uploaded_logo_dark_id, self.uploaded_background_id] UploadReference.ensure_exist!(upload_ids: upload_ids, target: self) end end @@ -1064,6 +1065,7 @@ end # default_list_filter :string(20) default("all") # allow_unlimited_owner_edits_on_first_post :boolean default(FALSE), not null # default_slow_mode_seconds :integer +# uploaded_logo_dark_id :integer # # Indexes # diff --git a/app/models/category_list.rb b/app/models/category_list.rb index 743a4cc4466..ef8e78329e1 100644 --- a/app/models/category_list.rb +++ b/app/models/category_list.rb @@ -99,6 +99,7 @@ class CategoryList @categories = Category.includes( :uploaded_background, :uploaded_logo, + :uploaded_logo_dark, :topic_only_relative_url, subcategories: [:topic_only_relative_url] ).secured(@guardian) diff --git a/app/models/site.rb b/app/models/site.rb index b76a0fa2a0b..4a9c08488ac 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -69,7 +69,7 @@ class Site # corresponding ActiveRecord callback to clear the categories cache. Discourse.cache.fetch(categories_cache_key, expires_in: 30.minutes) do categories = Category - .includes(:uploaded_logo, :uploaded_background, :tags, :tag_groups, category_required_tag_groups: :tag_group) + .includes(:uploaded_logo, :uploaded_logo_dark, :uploaded_background, :tags, :tag_groups, category_required_tag_groups: :tag_group) .joins('LEFT JOIN topics t on t.id = categories.topic_id') .select('categories.*, t.slug topic_slug') .order(:position) diff --git a/app/serializers/basic_category_serializer.rb b/app/serializers/basic_category_serializer.rb index 87c02a67a92..fe1b8cd2f71 100644 --- a/app/serializers/basic_category_serializer.rb +++ b/app/serializers/basic_category_serializer.rb @@ -34,6 +34,7 @@ class BasicCategorySerializer < ApplicationSerializer :custom_fields has_one :uploaded_logo, embed: :object, serializer: CategoryUploadSerializer + has_one :uploaded_logo_dark, embed: :object, serializer: CategoryUploadSerializer has_one :uploaded_background, embed: :object, serializer: CategoryUploadSerializer def include_parent_category_id? diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index e8f39b3f018..b8321bc94e9 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -3450,6 +3450,7 @@ en: name: "Category Name" description: "Description" logo: "Category Logo Image" + logo_dark: "Dark Mode Category Logo Image" background_image: "Category Background Image" badge_colors: "Badge colors" background_color: "Background color" diff --git a/db/migrate/20221004122343_add_dark_mode_logo_to_categories.rb b/db/migrate/20221004122343_add_dark_mode_logo_to_categories.rb new file mode 100644 index 00000000000..6fa8ba03dda --- /dev/null +++ b/db/migrate/20221004122343_add_dark_mode_logo_to_categories.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddDarkModeLogoToCategories < ActiveRecord::Migration[7.0] + def change + add_column :categories, :uploaded_logo_dark_id, :integer, index: true + end +end diff --git a/lib/tasks/site.rake b/lib/tasks/site.rake index 9a05d5fd96c..870e31dc1b8 100644 --- a/lib/tasks/site.rake +++ b/lib/tasks/site.rake @@ -210,6 +210,7 @@ task 'site:export_structure', [:zip_path] => :environment do |task, args| sort_order: c.sort_order, sort_ascending: c.sort_ascending, uploaded_logo_id: data.set_upload(c.uploaded_logo_id), + uploaded_logo_dark_id: data.set_upload(c.uploaded_logo_dark_id), uploaded_background_id: data.set_upload(c.uploaded_background_id), topic_featured_link_allowed: c.topic_featured_link_allowed, all_topics_wiki: c.all_topics_wiki, diff --git a/lib/tasks/uploads.rake b/lib/tasks/uploads.rake index 4d685580b40..bfc2806faaa 100644 --- a/lib/tasks/uploads.rake +++ b/lib/tasks/uploads.rake @@ -905,6 +905,7 @@ def analyze_missing_s3 [:user_profiles, :profile_background_upload_id], [:user_profiles, :card_background_upload_id], [:categories, :uploaded_logo_id], + [:categories, :uploaded_logo_dark_id], [:categories, :uploaded_background_id], [:custom_emojis, :upload_id], [:theme_fields, :upload_id], diff --git a/lib/upload_security.rb b/lib/upload_security.rb index dcaa7f10980..c784b25aa28 100644 --- a/lib/upload_security.rb +++ b/lib/upload_security.rb @@ -29,6 +29,7 @@ class UploadSecurity profile_background card_background category_logo + category_logo_dark category_background group_flair badge_image diff --git a/spec/jobs/clean_up_uploads_spec.rb b/spec/jobs/clean_up_uploads_spec.rb index 842f3e0d1be..461123394b4 100644 --- a/spec/jobs/clean_up_uploads_spec.rb +++ b/spec/jobs/clean_up_uploads_spec.rb @@ -242,14 +242,24 @@ RSpec.describe Jobs::CleanUpUploads do expect(Upload.exists?(id: category_logo_upload.id)).to eq(true) end - it "does not delete category background url uploads" do - category_logo_upload = fabricate_upload - Fabricate(:category, uploaded_background: category_logo_upload) + it "does not delete category dark logo uploads" do + category_logo_dark_upload = fabricate_upload + Fabricate(:category, uploaded_logo_dark: category_logo_dark_upload) Jobs::CleanUpUploads.new.execute(nil) expect(Upload.exists?(id: expired_upload.id)).to eq(false) - expect(Upload.exists?(id: category_logo_upload.id)).to eq(true) + expect(Upload.exists?(id: category_logo_dark_upload.id)).to eq(true) + end + + it "does not delete category background uploads" do + category_background_upload = fabricate_upload + Fabricate(:category, uploaded_background: category_background_upload) + + Jobs::CleanUpUploads.new.execute(nil) + + expect(Upload.exists?(id: expired_upload.id)).to eq(false) + expect(Upload.exists?(id: category_background_upload.id)).to eq(true) end it "does not delete post uploads" do diff --git a/spec/models/upload_reference_spec.rb b/spec/models/upload_reference_spec.rb index 50a027a3f90..cd7a826957c 100644 --- a/spec/models/upload_reference_spec.rb +++ b/spec/models/upload_reference_spec.rb @@ -21,17 +21,18 @@ RSpec.describe UploadReference do describe 'category uploads' do fab!(:upload1) { Fabricate(:upload) } fab!(:upload2) { Fabricate(:upload) } + fab!(:upload3) { Fabricate(:upload) } it 'creates upload references' do category = nil - expect { category = Fabricate(:category, uploaded_logo_id: upload1.id, uploaded_background_id: upload2.id) } - .to change { UploadReference.count }.by(2) + expect { category = Fabricate(:category, uploaded_logo_id: upload1.id, uploaded_logo_dark_id: upload2.id, uploaded_background_id: upload3.id) } + .to change { UploadReference.count }.by(3) upload_reference = UploadReference.last expect(upload_reference.target).to eq(category) expect { category.destroy! } - .to change { UploadReference.count }.by(-2) + .to change { UploadReference.count }.by(-3) end end diff --git a/spec/requests/api/schemas/json/category_create_response.json b/spec/requests/api/schemas/json/category_create_response.json index 7cef34b393e..e13c1642f6a 100644 --- a/spec/requests/api/schemas/json/category_create_response.json +++ b/spec/requests/api/schemas/json/category_create_response.json @@ -239,6 +239,12 @@ "null" ] }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, "uploaded_background": { "type": [ "string", @@ -293,6 +299,7 @@ "topic_featured_link_allowed", "search_priority", "uploaded_logo", + "uploaded_logo_dark", "uploaded_background" ] } diff --git a/spec/requests/api/schemas/json/category_list_response.json b/spec/requests/api/schemas/json/category_list_response.json index f1dac8b3e7b..ab9da835689 100644 --- a/spec/requests/api/schemas/json/category_list_response.json +++ b/spec/requests/api/schemas/json/category_list_response.json @@ -156,6 +156,12 @@ "null" ] }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, "uploaded_background": { "type": [ "string", @@ -199,6 +205,7 @@ "topics_all_time", "subcategory_ids", "uploaded_logo", + "uploaded_logo_dark", "uploaded_background" ] } diff --git a/spec/requests/api/schemas/json/category_update_response.json b/spec/requests/api/schemas/json/category_update_response.json index ed4e9aaece3..402828ec080 100644 --- a/spec/requests/api/schemas/json/category_update_response.json +++ b/spec/requests/api/schemas/json/category_update_response.json @@ -242,6 +242,12 @@ "null" ] }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, "uploaded_background": { "type": [ "string", @@ -296,6 +302,7 @@ "topic_featured_link_allowed", "search_priority", "uploaded_logo", + "uploaded_logo_dark", "uploaded_background" ] } diff --git a/spec/requests/api/schemas/json/site_response.json b/spec/requests/api/schemas/json/site_response.json index 5703ede25fd..1401d223119 100644 --- a/spec/requests/api/schemas/json/site_response.json +++ b/spec/requests/api/schemas/json/site_response.json @@ -629,6 +629,12 @@ "null" ] }, + "uploaded_logo_dark": { + "type": [ + "string", + "null" + ] + }, "uploaded_background": { "type": [ "string", @@ -680,6 +686,7 @@ "required_tag_groups", "read_only_banner", "uploaded_logo", + "uploaded_logo_dark", "uploaded_background", "can_edit" ]