Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add categories for custom emojis #11196

Merged
merged 1 commit into from Jun 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/api/v1/custom_emojis_controller.rb
Expand Up @@ -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
Expand Up @@ -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' },
Expand All @@ -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 = {
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/mastodon/features/emoji/emoji.js
Expand Up @@ -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());
2 changes: 2 additions & 0 deletions app/models/custom_emoji.rb
Expand Up @@ -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
Expand All @@ -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' } }
Expand Down
15 changes: 15 additions & 0 deletions app/models/custom_emoji_category.rb
@@ -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
10 changes: 10 additions & 0 deletions app/serializers/rest/custom_emoji_serializer.rb
Expand Up @@ -5,11 +5,21 @@ 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

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
9 changes: 9 additions & 0 deletions db/migrate/20190627222225_create_custom_emoji_categories.rb
@@ -0,0 +1,9 @@
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
5 changes: 5 additions & 0 deletions db/migrate/20190627222826_add_category_id_to_custom_emojis.rb
@@ -0,0 +1,5 @@
class AddCategoryIdToCustomEmojis < ActiveRecord::Migration[5.2]
def change
add_column :custom_emojis, :category_id, :bigint
end
end
10 changes: 9 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# 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"
Expand Down Expand Up @@ -208,6 +208,13 @@
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"
Expand All @@ -221,6 +228,7 @@
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

Expand Down
6 changes: 6 additions & 0 deletions lib/mastodon/emoji_cli.rb
Expand Up @@ -15,13 +15,17 @@ def self.exit_on_failure?
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.
Expand All @@ -33,6 +37,7 @@ def import(path)
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|
Expand All @@ -50,6 +55,7 @@ def import(path)
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
Expand Down
3 changes: 3 additions & 0 deletions spec/fabricators/custom_emoji_category_fabricator.rb
@@ -0,0 +1,3 @@
Fabricator(:custom_emoji_category) do
name "MyString"
end
5 changes: 5 additions & 0 deletions spec/models/custom_emoji_category_spec.rb
@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe CustomEmojiCategory, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
4 changes: 2 additions & 2 deletions yarn.lock
Expand Up @@ -3384,8 +3384,8 @@ elliptic@^6.0.0:
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"
Expand Down