def index
render_cached_json('api:v1:custom_emojis', expires_in: 1.minute) do
- ActiveModelSerializers::SerializableResource.new(CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer)
+ ActiveModelSerializers::SerializableResource.new(CustomEmoji.local.where(disabled: false).includes(:category), each_serializer: REST::CustomEmojiSerializer)
end
end
end
import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import detectPassiveEvents from 'detect-passive-events';
-import { buildCustomEmojis } from '../../emoji/emoji';
+import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
const messages = defineMessages({
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
-const categoriesSort = [
- 'recent',
- 'custom',
- 'people',
- 'nature',
- 'foods',
- 'activity',
- 'places',
- 'objects',
- 'symbols',
- 'flags',
-];
-
class ModifierPickerMenu extends React.PureComponent {
static propTypes = {
}
const title = intl.formatMessage(messages.emoji);
+
const { modifierOpen } = this.state;
+ const categoriesSort = [
+ 'recent',
+ 'people',
+ 'nature',
+ 'foods',
+ 'activity',
+ 'places',
+ 'objects',
+ 'symbols',
+ 'flags',
+ ];
+
+ categoriesSort.splice(1, 0, ...Array.from(categoriesFromEmojis(custom_emojis)).sort());
+
return (
<div className={classNames('emoji-picker-dropdown__menu', { selecting: modifierOpen })} style={style} ref={this.setRef}>
<EmojiPicker
keywords: [name],
imageUrl: url,
custom: true,
+ customCategory: emoji.get('category'),
});
});
return emojis;
};
+
+export const categoriesFromEmojis = customEmojis => customEmojis.reduce((set, emoji) => set.add(emoji.get('category') ? `custom-${emoji.get('category')}` : 'custom'), new Set());
# uri :string
# image_remote_url :string
# visible_in_picker :boolean default(TRUE), not null
+# category_id :bigint(8)
#
class CustomEmoji < ApplicationRecord
:(#{SHORTCODE_RE_FRAGMENT}):
(?=[^[:alnum:]:]|$)/x
+ 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 -strip' } }
--- /dev/null
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: custom_emoji_categories
+#
+# id :bigint(8) not null, primary key
+# name :string
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class CustomEmojiCategory < ApplicationRecord
+ has_many :emojis, class_name: 'CustomEmoji', foreign_key: 'category_id', inverse_of: :category
+end
attributes :shortcode, :url, :static_url, :visible_in_picker
+ attribute :category, if: :category_loaded?
+
def url
full_asset_url(object.image.url)
end
def static_url
full_asset_url(object.image.url(:static))
end
+
+ def category
+ object.category.name
+ end
+
+ def category_loaded?
+ object.association(:category).loaded? && object.category.present?
+ end
end
--- /dev/null
+class CreateCustomEmojiCategories < ActiveRecord::Migration[5.2]
+ def change
+ create_table :custom_emoji_categories do |t|
+ t.string :name, index: { unique: true }
+
+ t.timestamps
+ end
+ end
+end
--- /dev/null
+class AddCategoryIdToCustomEmojis < ActiveRecord::Migration[5.2]
+ def change
+ add_column :custom_emojis, :category_id, :bigint
+ end
+end
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_05_29_143559) do
+ActiveRecord::Schema.define(version: 2019_06_27_222826) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
t.index ["uri"], name: "index_conversations_on_uri", unique: true
end
+ create_table "custom_emoji_categories", force: :cascade do |t|
+ t.string "name"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["name"], name: "index_custom_emoji_categories_on_name", unique: true
+ end
+
create_table "custom_emojis", force: :cascade do |t|
t.string "shortcode", default: "", null: false
t.string "domain"
t.string "uri"
t.string "image_remote_url"
t.boolean "visible_in_picker", default: true, null: false
+ t.bigint "category_id"
t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true
end
option :suffix
option :overwrite, type: :boolean
option :unlisted, type: :boolean
+ option :category
desc 'import PATH', 'Import emoji from a TAR GZIP archive at PATH'
long_desc <<-LONG_DESC
Imports custom emoji from a TAR GZIP archive specified by PATH.
Existing emoji will be skipped unless the --overwrite option
is provided, in which case they will be overwritten.
+ You can specifiy a --category under which the emojis will be
+ grouped together.
+
With the --prefix option, a prefix can be added to all
generated shortcodes. Likewise, the --suffix option controls
the suffix of all shortcodes.
imported = 0
skipped = 0
failed = 0
+ category = options[:category] ? CustomEmojiCategory.find_or_create_by(name: options[:category]) : nil
Gem::Package::TarReader.new(Zlib::GzipReader.open(path)) do |tar|
tar.each do |entry|
custom_emoji.image = StringIO.new(entry.read)
custom_emoji.image_file_name = File.basename(entry.full_name)
custom_emoji.visible_in_picker = !options[:unlisted]
+ custom_emoji.category = category
if custom_emoji.save
imported += 1
--- /dev/null
+Fabricator(:custom_emoji_category) do
+ name "MyString"
+end
--- /dev/null
+require 'rails_helper'
+
+RSpec.describe CustomEmojiCategory, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
minimalistic-crypto-utils "^1.0.0"
emoji-mart@Gargron/emoji-mart#build:
- version "2.6.2"
- resolved "https://codeload.github.com/Gargron/emoji-mart/tar.gz/ff00dc470b5b2d9f145a6d6e977a54de5df2b4c9"
+ version "2.6.3"
+ resolved "https://codeload.github.com/Gargron/emoji-mart/tar.gz/934f314fd8322276765066e8a2a6be5bac61b1cf"
emoji-regex@^7.0.1, emoji-regex@^7.0.2:
version "7.0.3"