Enable custom emojis in profiles (notes, field values, display names) (#7374)

Follow-up to #6124
This commit is contained in:
Eugen Rochko 2018-05-06 11:48:51 +02:00 committed by GitHub
parent bd10a7e480
commit 61a9018607
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 43 additions and 27 deletions

View File

@ -4,8 +4,8 @@ module StreamEntriesHelper
EMBEDDED_CONTROLLER = 'statuses' EMBEDDED_CONTROLLER = 'statuses'
EMBEDDED_ACTION = 'embed' EMBEDDED_ACTION = 'embed'
def display_name(account) def display_name(account, **options)
account.display_name.presence || account.username Formatter.instance.format_display_name(account, options)
end end
def account_description(account) def account_description(account)

View File

@ -3,18 +3,25 @@ import emojify from '../../features/emoji/emoji';
const domParser = new DOMParser(); const domParser = new DOMParser();
const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => {
obj[`:${emoji.shortcode}:`] = emoji;
return obj;
}, {});
export function normalizeAccount(account) { export function normalizeAccount(account) {
account = { ...account }; account = { ...account };
const emojiMap = makeEmojiMap(account);
const displayName = account.display_name.length === 0 ? account.username : account.display_name; const displayName = account.display_name.length === 0 ? account.username : account.display_name;
account.display_name_html = emojify(escapeTextContentForBrowser(displayName));
account.note_emojified = emojify(account.note); account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap);
account.note_emojified = emojify(account.note, emojiMap);
if (account.fields) { if (account.fields) {
account.fields = account.fields.map(pair => ({ account.fields = account.fields.map(pair => ({
...pair, ...pair,
name_emojified: emojify(escapeTextContentForBrowser(pair.name)), name_emojified: emojify(escapeTextContentForBrowser(pair.name)),
value_emojified: emojify(pair.value), value_emojified: emojify(pair.value, emojiMap),
})); }));
} }
@ -42,11 +49,7 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.hidden = normalOldStatus.get('hidden'); normalStatus.hidden = normalOldStatus.get('hidden');
} else { } else {
const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
const emojiMap = makeEmojiMap(normalStatus);
const emojiMap = normalStatus.emojis.reduce((obj, emoji) => {
obj[`:${emoji.shortcode}:`] = emoji;
return obj;
}, {});
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);

View File

@ -67,9 +67,17 @@ class Formatter
html.html_safe # rubocop:disable Rails/OutputSafety html.html_safe # rubocop:disable Rails/OutputSafety
end end
def format_field(account, str) def format_display_name(account, **options)
html = encode(account.display_name.presence || account.username)
html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify]
html.html_safe # rubocop:disable Rails/OutputSafety
end
def format_field(account, str, **options)
return reformat(str).html_safe unless account.local? # rubocop:disable Rails/OutputSafety return reformat(str).html_safe unless account.local? # rubocop:disable Rails/OutputSafety
encode_and_link_urls(str, me: true).html_safe # rubocop:disable Rails/OutputSafety html = encode_and_link_urls(str, me: true)
html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify]
html.html_safe # rubocop:disable Rails/OutputSafety
end end
def linkify(text) def linkify(text)

View File

@ -398,7 +398,7 @@ class Account < ApplicationRecord
end end
def emojis def emojis
@emojis ||= CustomEmoji.from_text(note, domain) @emojis ||= CustomEmoji.from_text(emojifiable_text, domain)
end end
before_create :generate_keys before_create :generate_keys
@ -425,4 +425,8 @@ class Account < ApplicationRecord
self.domain = TagManager.instance.normalize_domain(domain) self.domain = TagManager.instance.normalize_domain(domain)
end end
def emojifiable_text
[note, display_name, fields.map(&:value)].join(' ')
end
end end

View File

@ -8,6 +8,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
:followers_count, :following_count, :statuses_count :followers_count, :following_count, :statuses_count
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested? has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
has_many :emojis, serializer: REST::CustomEmojiSerializer
class FieldSerializer < ActiveModel::Serializer class FieldSerializer < ActiveModel::Serializer
attributes :name, :value attributes :name, :value

View File

@ -6,7 +6,7 @@
.account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" } .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" }
%span.display-name %span.display-name
%bdi %bdi
%strong.display-name__html.emojify= display_name(@instance_presenter.contact_account) %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account, custom_emojify: true)
%span.display-name__account @#{@instance_presenter.contact_account.acct} %span.display-name__account @#{@instance_presenter.contact_account.acct}
- else - else
.account__display-name .account__display-name

View File

@ -12,7 +12,7 @@
.avatar= image_tag contact.contact_account.avatar.url .avatar= image_tag contact.contact_account.avatar.url
.name .name
= link_to TagManager.instance.url_for(contact.contact_account) do = link_to TagManager.instance.url_for(contact.contact_account) do
%span.display_name.emojify= display_name(contact.contact_account) %span.display_name.emojify= display_name(contact.contact_account, custom_emojify: true)
%span.username @#{contact.contact_account.acct} %span.username @#{contact.contact_account.acct}
- else - else
.owner .owner

View File

@ -5,7 +5,7 @@
.avatar= image_tag account.avatar.url(:original) .avatar= image_tag account.avatar.url(:original)
.name .name
= link_to TagManager.instance.url_for(account) do = link_to TagManager.instance.url_for(account) do
%span.display_name.emojify= display_name(account) %span.display_name.emojify= display_name(account, custom_emojify: true)
%span.username %span.username
@#{account.local? ? account.local_username_and_domain : account.acct} @#{account.local? ? account.local_username_and_domain : account.acct}
= fa_icon('lock') if account.locked? = fa_icon('lock') if account.locked?

View File

@ -5,7 +5,7 @@
.card__bio .card__bio
%h1.name %h1.name
%span.p-name.emojify= display_name(account) %span.p-name.emojify= display_name(account, custom_emojify: true)
%small< %small<
%span>< @#{account.local_username_and_domain} %span>< @#{account.local_username_and_domain}
= fa_icon('lock') if account.locked? = fa_icon('lock') if account.locked?
@ -28,7 +28,7 @@
- account.fields.each do |field| - account.fields.each do |field|
%dl %dl
%dt.emojify{ title: field.name }= field.name %dt.emojify{ title: field.name }= field.name
%dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value) %dd.emojify{ title: field.value }= Formatter.instance.format_field(account, field.value, custom_emojify: true)
.details-counters .details-counters
.counter{ class: active_nav_class(short_account_url(account)) } .counter{ class: active_nav_class(short_account_url(account)) }

View File

@ -3,7 +3,7 @@
.moved-strip .moved-strip
.moved-strip__message .moved-strip__message
= fa_icon 'suitcase' = fa_icon 'suitcase'
= t('accounts.moved_html', name: content_tag(:strong, display_name(account), class: :emojify), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention')) = t('accounts.moved_html', name: content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention'))
.moved-strip__card .moved-strip__card
= link_to TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do = link_to TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
@ -13,5 +13,5 @@
.account__avatar-overlay-overlay{ style: "background-image: url('#{account.avatar.url(:original)}')" } .account__avatar-overlay-overlay{ style: "background-image: url('#{account.avatar.url(:original)}')" }
%span.display-name %span.display-name
%strong.emojify= display_name(moved_to_account) %strong.emojify= display_name(moved_to_account, custom_emojify: true)
%span @#{moved_to_account.acct} %span @#{moved_to_account.acct}

View File

@ -15,5 +15,5 @@
.account__avatar{ style: "background-image: url(#{account.avatar.url}); width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px" } .account__avatar{ style: "background-image: url(#{account.avatar.url}); width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px" }
%span.display-name %span.display-name
%bdi %bdi
%strong.display-name__html.emojify= display_name(account) %strong.display-name__html.emojify= display_name(account, custom_emojify: true)
%span.display-name__account @#{account.acct} %span.display-name__account @#{account.acct}

View File

@ -6,7 +6,7 @@
%span.display-name %span.display-name
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account) - account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
= link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do = link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
%strong.emojify= display_name(account) %strong.emojify= display_name(account, custom_emojify: true)
%span @#{account.acct} %span @#{account.acct}
- if account.note? - if account.note?

View File

@ -6,7 +6,7 @@
%span.display-name %span.display-name
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account) - account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
= link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do = link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
%strong.emojify= display_name(account) %strong.emojify= display_name(account, custom_emojify: true)
%span @#{account.acct} %span @#{account.acct}
- if account.note? - if account.note?

View File

@ -2,7 +2,7 @@
= image_tag asset_pack_path('logo.svg'), class: 'logo' = image_tag asset_pack_path('logo.svg'), class: 'logo'
%div %div
= t('landing_strip_html', name: content_tag(:span, display_name(account), class: :emojify), link_to_root_path: link_to(content_tag(:strong, site_hostname), root_path)) = t('landing_strip_html', name: content_tag(:span, display_name(account, custom_emojify: true), class: :emojify), link_to_root_path: link_to(content_tag(:strong, site_hostname), root_path))
- if open_registrations? - if open_registrations?
= t('landing_strip_signup_html', sign_up_path: new_user_registration_path) = t('landing_strip_signup_html', sign_up_path: new_user_registration_path)

View File

@ -4,7 +4,7 @@
.avatar .avatar
= image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo' = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo'
%span.display-name %span.display-name
%strong.p-name.emojify= display_name(status.account) %strong.p-name.emojify= display_name(status.account, custom_emojify: true)
%span= acct(status.account) %span= acct(status.account)
- if embedded_view? - if embedded_view?

View File

@ -10,7 +10,7 @@
%div %div
= image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo' = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo'
%span.display-name %span.display-name
%strong.p-name.emojify= display_name(status.account) %strong.p-name.emojify= display_name(status.account, custom_emojify: true)
%span= acct(status.account) %span= acct(status.account)
.status__content.p-name.emojify< .status__content.p-name.emojify<

View File

@ -28,7 +28,7 @@
= fa_icon('retweet fw') = fa_icon('retweet fw')
%span %span
= link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do = link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do
%strong.emojify= display_name(status.account) %strong.emojify= display_name(status.account, custom_emojify: true)
= t('stream_entries.reblogged') = t('stream_entries.reblogged')
- elsif pinned - elsif pinned
.pre-header .pre-header