-
diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js
index b4a123753..41a3dfa5f 100644
--- a/app/javascript/mastodon/initial_state.js
+++ b/app/javascript/mastodon/initial_state.js
@@ -60,6 +60,8 @@ export const enableEmptyColumn = getMeta('enable_empty_column');
export const showReloadButton = getMeta('show_reload_button');
export const defaultColumnWidth = getMeta('default_column_width');
export const pickerEmojiSize = getMeta('picker_emoji_size');
+export const enableWideEmoji = getMeta('enable_wide_emoji');
+export const enableWideEmojiReaction = getMeta('enable_wide_emoji_reaction');
export const disablePost = getMeta('disable_post');
export const disableReactions = getMeta('disable_reactions');
export const disableFollow = getMeta('disable_follow');
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 9d3f17507..2cee92136 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -1946,7 +1946,8 @@ a.account__display-name {
}
}
-.notification__favourite-icon-wrapper {
+.notification__favourite-icon-wrapper,
+.notification__reaction-icon-wrapper {
left: -26px;
position: absolute;
@@ -1955,6 +1956,11 @@ a.account__display-name {
}
}
+.notification__reaction-message-wrapper.wide {
+ display: block;
+ margin-top: 22px;
+}
+
.icon-button.star-icon.active {
color: $gold-star;
}
diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb
index f82eb53f7..15a5da488 100644
--- a/app/lib/user_settings_decorator.rb
+++ b/app/lib/user_settings_decorator.rb
@@ -100,6 +100,8 @@ class UserSettingsDecorator
hide_link_preview
hide_photo_preview
hide_video_preview
+ enable_wide_emoji
+ enable_wide_emoji_reaction
).freeze
STRING_KEYS = %w(
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 0dbba4254..93e725392 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -18,13 +18,15 @@
# visible_in_picker :boolean default(TRUE), not null
# category_id :bigint(8)
# image_storage_schema_version :integer
+# width :integer
+# height :integer
#
class CustomEmoji < ApplicationRecord
include Attachmentable
- LOCAL_LIMIT = (ENV['MAX_EMOJI_SIZE'] || 50.kilobytes).to_i
- LIMIT = [LOCAL_LIMIT, (ENV['MAX_REMOTE_EMOJI_SIZE'] || 200.kilobytes).to_i].max
+ LOCAL_LIMIT = (ENV['MAX_EMOJI_SIZE'] || 256.kilobytes).to_i
+ LIMIT = [LOCAL_LIMIT, (ENV['MAX_REMOTE_EMOJI_SIZE'] || 256.kilobytes).to_i].max
SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}'
@@ -37,7 +39,7 @@ class CustomEmoji < ApplicationRecord
belongs_to :category, class_name: 'CustomEmojiCategory', optional: true
has_one :local_counterpart, -> { where(domain: nil) }, class_name: 'CustomEmoji', primary_key: :shortcode, foreign_key: :shortcode
- has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile exif' } }, validate_media_type: false
+ has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce +profile exif', file_geometry_parser: FastGeometryParser } }, processors: [:dimension_extractor], validate_media_type: false
before_validation :downcase_domain
diff --git a/app/models/user.rb b/app/models/user.rb
index e66679cc9..7be7c11ed 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -140,6 +140,7 @@ class User < ApplicationRecord
:post_reference_modal, :add_reference_modal, :unselect_reference_modal, :delete_scheduled_status_modal,
:hexagon_avatar, :enable_empty_column,
:content_font_size, :info_font_size, :content_emoji_reaction_size, :emoji_scale, :picker_emoji_size,
+ :enable_wide_emoji, :enable_wide_emoji_reaction,
:hide_bot_on_public_timeline, :confirm_follow_from_bot,
:default_search_searchability, :default_expires_in, :default_expires_action,
:show_reload_button, :default_column_width,
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index b508d8b9c..b116f8085 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -78,6 +78,8 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:content_emoji_reaction_size] = object.current_account.user.setting_content_emoji_reaction_size
store[:emoji_scale] = object.current_account.user.setting_emoji_scale
store[:picker_emoji_size] = object.current_account.user.setting_picker_emoji_size
+ store[:enable_wide_emoji] = object.current_account.user.setting_enable_wide_emoji
+ store[:enable_wide_emoji_reaction] = object.current_account.user.setting_enable_wide_emoji_reaction
store[:hide_bot_on_public_timeline] = object.current_account.user.setting_hide_bot_on_public_timeline
store[:confirm_follow_from_bot] = object.current_account.user.setting_confirm_follow_from_bot
store[:show_reload_button] = object.current_account.user.setting_show_reload_button
diff --git a/app/serializers/rest/custom_emoji_serializer.rb b/app/serializers/rest/custom_emoji_serializer.rb
index aff58e4d9..3aec3ee2b 100644
--- a/app/serializers/rest/custom_emoji_serializer.rb
+++ b/app/serializers/rest/custom_emoji_serializer.rb
@@ -6,6 +6,8 @@ class REST::CustomEmojiSerializer < ActiveModel::Serializer
attributes :shortcode, :url, :static_url, :visible_in_picker
attribute :category, if: :category_loaded?
+ attribute :width, if: :width?
+ attribute :height, if: :height?
def url
full_asset_url(object.image.url)
@@ -22,4 +24,20 @@ class REST::CustomEmojiSerializer < ActiveModel::Serializer
def category_loaded?
object.association(:category).loaded? && object.category.present?
end
+
+ def width
+ object.width
+ end
+
+ def height
+ object.height
+ end
+
+ def width?
+ !object.width.nil?
+ end
+
+ def height?
+ !object.height.nil?
+ end
end
diff --git a/app/serializers/rest/emoji_reaction_serializer.rb b/app/serializers/rest/emoji_reaction_serializer.rb
index 3e7e10927..57540a32a 100644
--- a/app/serializers/rest/emoji_reaction_serializer.rb
+++ b/app/serializers/rest/emoji_reaction_serializer.rb
@@ -8,6 +8,8 @@ class REST::EmojiReactionSerializer < ActiveModel::Serializer
attribute :url, if: :custom_emoji?
attribute :static_url, if: :custom_emoji?
attribute :domain, if: :custom_emoji?
+ attribute :width, if: :width?
+ attribute :height, if: :height?
belongs_to :account, serializer: REST::AccountSerializer
@@ -26,4 +28,20 @@ class REST::EmojiReactionSerializer < ActiveModel::Serializer
def domain
object.custom_emoji.domain
end
+
+ def width
+ object.custom_emoji.width
+ end
+
+ def height
+ object.custom_emoji.height
+ end
+
+ def width?
+ custom_emoji? && object.custom_emoji.width
+ end
+
+ def height?
+ custom_emoji? && object.custom_emoji.height
+ end
end
diff --git a/app/serializers/rest/grouped_emoji_reaction_serializer.rb b/app/serializers/rest/grouped_emoji_reaction_serializer.rb
index f885f2deb..ef4634258 100644
--- a/app/serializers/rest/grouped_emoji_reaction_serializer.rb
+++ b/app/serializers/rest/grouped_emoji_reaction_serializer.rb
@@ -9,6 +9,8 @@ class REST::GroupedEmojiReactionSerializer < ActiveModel::Serializer
attribute :url, if: :custom_emoji?
attribute :static_url, if: :custom_emoji?
attribute :domain, if: :custom_emoji?
+ attribute :width, if: :width?
+ attribute :height, if: :height?
attribute :account_ids, if: :has_account_ids?
def count
@@ -38,4 +40,20 @@ class REST::GroupedEmojiReactionSerializer < ActiveModel::Serializer
def domain
object.custom_emoji.domain
end
+
+ def width
+ object.custom_emoji.width
+ end
+
+ def height
+ object.custom_emoji.height
+ end
+
+ def width?
+ custom_emoji? && object.custom_emoji.width
+ end
+
+ def height?
+ custom_emoji? && object.custom_emoji.height
+ end
end
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
index ce52ebe96..9ef92ce28 100644
--- a/app/serializers/rest/instance_serializer.rb
+++ b/app/serializers/rest/instance_serializer.rb
@@ -148,6 +148,8 @@ class REST::InstanceSerializer < ActiveModel::Serializer
:searchability,
:status_compact_mode,
:account_conversations,
+ :enable_wide_emoji,
+ :enable_wide_emoji_reaction,
]
capabilities << :profile_search unless Chewy.enabled?
diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml
index 100d78b00..deab54557 100644
--- a/app/views/settings/preferences/appearance/show.html.haml
+++ b/app/views/settings/preferences/appearance/show.html.haml
@@ -33,6 +33,12 @@
= f.input :setting_content_emoji_reaction_size, as: :range, input_html: { min: 10, max: 48, list: 'emoji_reaction_size_label' }, wrapper: :with_label, false: true, fedibird_features: true
= f.input :setting_picker_emoji_size, as: :range, input_html: { min: 22, max: 48, list: 'picker_emoji_size_label' }, wrapper: :with_label, false: true, fedibird_features: true
+ .fields-group
+ = f.input :setting_enable_wide_emoji, as: :boolean, wrapper: :with_label, hint: true, fedibird_features: true
+
+ .fields-group
+ = f.input :setting_enable_wide_emoji_reaction, as: :boolean, wrapper: :with_label, hint: true, fedibird_features: true
+
.fields-group
= f.input :setting_theme_public, as: :boolean, wrapper: :with_label, hint: true, fedibird_features: true
diff --git a/config/application.rb b/config/application.rb
index 434e722f3..9245f498e 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -12,6 +12,7 @@ require_relative '../lib/sanitize_ext/sanitize_config'
require_relative '../lib/redis/namespace_extensions'
require_relative '../lib/paperclip/url_generator_extensions'
require_relative '../lib/paperclip/attachment_extensions'
+require_relative '../lib/paperclip/dimension_extractor'
require_relative '../lib/paperclip/lazy_thumbnail'
require_relative '../lib/paperclip/gif_transcoder'
require_relative '../lib/paperclip/transcoder'
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 033f9ab96..75cb03b7d 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -91,6 +91,8 @@ en:
setting_enable_personal_timeline: Enable a personal home to display personal post
setting_enable_reaction: Enable the reaction display on the timeline and display the reaction button
setting_enable_status_reference: Enable the feature where a post references another post
+ setting_enable_wide_emoji: Displays wide emoji derived from Misskey in their original proportions (for content)
+ setting_enable_wide_emoji_reaction: Displays wide emoji derived from Misskey in their original proportions (for reaction)
setting_follow_button_to_list_adder: Change the behavior of the Follow / Subscribe button, open a dialog where you can select a list to follow / subscribe, or opt out of receiving at home
setting_hexagon_avatar: Display everyone's avatar icon as a hollowed out hexagon (joke feature)
setting_hide_bot_on_public_timeline: Disable Bot accounts from appearing on federation & hashtag & domain & group timelines (overridden by column setting)
@@ -288,6 +290,8 @@ en:
setting_enable_personal_timeline: Enable personal timeline
setting_enable_reaction: Enable reaction
setting_enable_status_reference: Enable reference
+ setting_enable_wide_emoji: Enable wide emoji (for content)
+ setting_enable_wide_emoji_reaction: Enable wide emoji (for reaction)
setting_expand_spoilers: Always expand posts marked with content warnings
setting_follow_button_to_list_adder: Open list add dialog with follow button
setting_hexagon_avatar: Experience NFT Avatar
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index 520384d8d..32b8c6d21 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -87,6 +87,8 @@ ja:
setting_enable_personal_timeline: 自分限定を表示する自分限定ホームを有効にします
setting_enable_reaction: タイムラインでリアクションの表示を有効にし、リアクションボタンを表示する
setting_enable_status_reference: 投稿が別の投稿を参照する機能を有効にします
+ setting_enable_wide_emoji: Misskey由来の横幅の広い絵文字を元の比率で表示します(本文)
+ setting_enable_wide_emoji_reaction: Misskey由来の横幅の広い絵文字を元の比率で表示します(リアクション)
setting_follow_button_to_list_adder: フォロー・購読ボタンの動作を変更し、フォロー・購読するリストを選択したり、ホームで受け取らないよう設定するダイアログを開きます
setting_hexagon_avatar: 全員のアバターアイコンを6角形にくりぬいて表示します(ジョーク機能)
setting_hide_bot_on_public_timeline: 連合・ハッシュタグ・ドメイン・グループタイムライン上にBotアカウントが表示されないようにします(※カラム設定を優先)
@@ -284,6 +286,8 @@ ja:
setting_enable_personal_timeline: 自分限定ホームを有効にする
setting_enable_reaction: リアクションを有効にする
setting_enable_status_reference: 参照を有効にする
+ setting_enable_wide_emoji: ワイド絵文字を有効にする(本文)
+ setting_enable_wide_emoji_reaction: ワイド絵文字を有効にする(リアクション)
setting_expand_spoilers: 閲覧注意としてマークされた投稿を常に展開する
setting_follow_button_to_list_adder: フォローボタンでリスト追加ダイアログを開く
setting_hexagon_avatar: NFTアイコンを体験する
diff --git a/config/settings.yml b/config/settings.yml
index b197cd695..f94fd0cb9 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -73,6 +73,8 @@ defaults: &defaults
content_emoji_reaction_size: 16
emoji_scale: 1,
picker_emoji_size: 22,
+ enable_wide_emoji: true
+ enable_wide_emoji_reaction: true
notification_emails:
follow: false
reblog: false
diff --git a/db/migrate/20230221031206_add_width_height_to_custom_emoji.rb b/db/migrate/20230221031206_add_width_height_to_custom_emoji.rb
new file mode 100644
index 000000000..3dea9a698
--- /dev/null
+++ b/db/migrate/20230221031206_add_width_height_to_custom_emoji.rb
@@ -0,0 +1,6 @@
+class AddWidthHeightToCustomEmoji < ActiveRecord::Migration[6.1]
+ def change
+ add_column :custom_emojis, :width, :integer, null: true, default: nil
+ add_column :custom_emojis, :height, :integer, null: true, default: nil
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index e19670b44..fb1484e64 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2023_02_15_062659) do
+ActiveRecord::Schema.define(version: 2023_02_21_031206) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -371,6 +371,8 @@ ActiveRecord::Schema.define(version: 2023_02_15_062659) do
t.boolean "visible_in_picker", default: true, null: false
t.bigint "category_id"
t.integer "image_storage_schema_version"
+ t.integer "width"
+ t.integer "height"
t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true
end
diff --git a/lib/mastodon/emoji_cli.rb b/lib/mastodon/emoji_cli.rb
index 5bee70ea5..b54974fe0 100644
--- a/lib/mastodon/emoji_cli.rb
+++ b/lib/mastodon/emoji_cli.rb
@@ -7,6 +7,8 @@ require_relative 'cli_helper'
module Mastodon
class EmojiCLI < Thor
+ include CLIHelper
+
def self.exit_on_failure?
true
end
@@ -132,6 +134,38 @@ module Mastodon
say('OK', :green)
end
+ option :local_only, type: :boolean
+ option :remote_only, type: :boolean
+ option :all, type: :boolean
+ option :concurrency, type: :numeric, default: 5, aliases: [:c]
+ option :verbose, type: :boolean, aliases: [:v]
+ desc 'fix-dimension', 'Fix dimension all custom emoji'
+ long_desc <<-LONG_DESC
+ Fix dimension all custom emoji.
+
+ With the --local-only option, only local emoji will be fixed.
+ With the --remote-only option, only remote emoji will be fixed.
+ With the --all option, fix dimension of all emojis.
+ LONG_DESC
+ def fix_dimension
+ scope = CustomEmoji
+ scope = scope.local if options[:local_only]
+ scope = scope.remote if options[:remote_only]
+ scope = scope.where(width: nil) unless options[:all]
+
+ processed, fixed = parallelize_with_progress(scope) do |emoji|
+ width, height = FastImage.size(emoji.image.url)
+ next if width.nil?
+
+ emoji.update!(width: width, height: height)
+ 1
+ rescue
+ next
+ end
+
+ say("Checked #{processed} emojis, fixed #{fixed}", :green, true)
+ end
+
private
def color(green, _yellow, red)
diff --git a/lib/paperclip/dimension_extractor.rb b/lib/paperclip/dimension_extractor.rb
new file mode 100644
index 000000000..4b3b06753
--- /dev/null
+++ b/lib/paperclip/dimension_extractor.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Paperclip
+ class DimensionExtractor < Paperclip::Processor
+ def make
+ geometry = options.fetch(:file_geometry_parser).from_file(@file)
+
+ attachment.instance.width = geometry.width if attachment.instance.respond_to?(:width)
+ attachment.instance.height = geometry.height if attachment.instance.respond_to?(:height)
+
+ File.open(@file.path)
+ end
+ end
+end