Add categories for custom emojis (#11196)

Fix #7940
This commit is contained in:
Eugen Rochko
2019-06-28 15:54:10 +02:00
committed by GitHub
parent 072158ee97
commit e64e6a03dd
13 changed files with 86 additions and 18 deletions

View File

@ -7,7 +7,7 @@ class Api::V1::CustomEmojisController < Api::BaseController
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

View File

@ -6,7 +6,7 @@ import Overlay from 'react-overlays/lib/Overlay';
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' },
@ -31,19 +31,6 @@ let EmojiPicker, Emoji; // load asynchronously
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 = {
@ -241,8 +228,23 @@ class EmojiPickerMenu extends React.PureComponent {
}
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

View File

@ -92,8 +92,11 @@ export const buildCustomEmojis = (customEmojis) => {
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());

View File

@ -16,6 +16,7 @@
# uri :string
# image_remote_url :string
# visible_in_picker :boolean default(TRUE), not null
# category_id :bigint(8)
#
class CustomEmoji < ApplicationRecord
@ -27,6 +28,7 @@ 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' } }

View File

@ -0,0 +1,15 @@
# 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

View File

@ -5,6 +5,8 @@ class REST::CustomEmojiSerializer < ActiveModel::Serializer
attributes :shortcode, :url, :static_url, :visible_in_picker
attribute :category, if: :category_loaded?
def url
full_asset_url(object.image.url)
end
@ -12,4 +14,12 @@ class REST::CustomEmojiSerializer < ActiveModel::Serializer
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