Enable custom emojis in profiles (notes, field values, display names) (#7374)
Follow-up to #6124
This commit is contained in:
		
							parent
							
								
									bd10a7e480
								
							
						
					
					
						commit
						61a9018607
					
				
					 17 changed files with 43 additions and 27 deletions
				
			
		| 
						 | 
				
			
			@ -4,8 +4,8 @@ module StreamEntriesHelper
 | 
			
		|||
  EMBEDDED_CONTROLLER = 'statuses'
 | 
			
		||||
  EMBEDDED_ACTION = 'embed'
 | 
			
		||||
 | 
			
		||||
  def display_name(account)
 | 
			
		||||
    account.display_name.presence || account.username
 | 
			
		||||
  def display_name(account, **options)
 | 
			
		||||
    Formatter.instance.format_display_name(account, options)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def account_description(account)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,18 +3,25 @@ import emojify from '../../features/emoji/emoji';
 | 
			
		|||
 | 
			
		||||
const domParser = new DOMParser();
 | 
			
		||||
 | 
			
		||||
const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => {
 | 
			
		||||
  obj[`:${emoji.shortcode}:`] = emoji;
 | 
			
		||||
  return obj;
 | 
			
		||||
}, {});
 | 
			
		||||
 | 
			
		||||
export function normalizeAccount(account) {
 | 
			
		||||
  account = { ...account };
 | 
			
		||||
 | 
			
		||||
  const emojiMap = makeEmojiMap(account);
 | 
			
		||||
  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) {
 | 
			
		||||
    account.fields = account.fields.map(pair => ({
 | 
			
		||||
      ...pair,
 | 
			
		||||
      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');
 | 
			
		||||
  } else {
 | 
			
		||||
    const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
 | 
			
		||||
 | 
			
		||||
    const emojiMap = normalStatus.emojis.reduce((obj, emoji) => {
 | 
			
		||||
      obj[`:${emoji.shortcode}:`] = emoji;
 | 
			
		||||
      return obj;
 | 
			
		||||
    }, {});
 | 
			
		||||
    const emojiMap = makeEmojiMap(normalStatus);
 | 
			
		||||
 | 
			
		||||
    normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
 | 
			
		||||
    normalStatus.contentHtml  = emojify(normalStatus.content, emojiMap);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,9 +67,17 @@ class Formatter
 | 
			
		|||
    html.html_safe # rubocop:disable Rails/OutputSafety
 | 
			
		||||
  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
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
  def linkify(text)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -398,7 +398,7 @@ class Account < ApplicationRecord
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def emojis
 | 
			
		||||
    @emojis ||= CustomEmoji.from_text(note, domain)
 | 
			
		||||
    @emojis ||= CustomEmoji.from_text(emojifiable_text, domain)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  before_create :generate_keys
 | 
			
		||||
| 
						 | 
				
			
			@ -425,4 +425,8 @@ class Account < ApplicationRecord
 | 
			
		|||
 | 
			
		||||
    self.domain = TagManager.instance.normalize_domain(domain)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def emojifiable_text
 | 
			
		||||
    [note, display_name, fields.map(&:value)].join(' ')
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
 | 
			
		|||
             :followers_count, :following_count, :statuses_count
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
    attributes :name, :value
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
          .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" }
 | 
			
		||||
        %span.display-name
 | 
			
		||||
          %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}
 | 
			
		||||
    - else
 | 
			
		||||
      .account__display-name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@
 | 
			
		|||
        .avatar= image_tag contact.contact_account.avatar.url
 | 
			
		||||
        .name
 | 
			
		||||
          = 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}
 | 
			
		||||
    - else
 | 
			
		||||
      .owner
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
    .avatar= image_tag account.avatar.url(:original)
 | 
			
		||||
  .name
 | 
			
		||||
    = 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
 | 
			
		||||
        @#{account.local? ? account.local_username_and_domain : account.acct}
 | 
			
		||||
        = fa_icon('lock') if account.locked?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
 | 
			
		||||
  .card__bio
 | 
			
		||||
    %h1.name
 | 
			
		||||
      %span.p-name.emojify= display_name(account)
 | 
			
		||||
      %span.p-name.emojify= display_name(account, custom_emojify: true)
 | 
			
		||||
      %small<
 | 
			
		||||
        %span>< @#{account.local_username_and_domain}
 | 
			
		||||
        = fa_icon('lock') if account.locked?
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@
 | 
			
		|||
          - account.fields.each do |field|
 | 
			
		||||
            %dl
 | 
			
		||||
              %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
 | 
			
		||||
      .counter{ class: active_nav_class(short_account_url(account)) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
.moved-strip
 | 
			
		||||
  .moved-strip__message
 | 
			
		||||
    = 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
 | 
			
		||||
    = 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)}')" }
 | 
			
		||||
 | 
			
		||||
      %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}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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" }
 | 
			
		||||
        %span.display-name
 | 
			
		||||
          %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}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
    %span.display-name
 | 
			
		||||
      - 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
 | 
			
		||||
        %strong.emojify= display_name(account)
 | 
			
		||||
        %strong.emojify= display_name(account, custom_emojify: true)
 | 
			
		||||
        %span @#{account.acct}
 | 
			
		||||
 | 
			
		||||
  - if account.note?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
    %span.display-name
 | 
			
		||||
      - 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
 | 
			
		||||
        %strong.emojify= display_name(account)
 | 
			
		||||
        %strong.emojify= display_name(account, custom_emojify: true)
 | 
			
		||||
        %span @#{account.acct}
 | 
			
		||||
 | 
			
		||||
  - if account.note?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
  = image_tag asset_pack_path('logo.svg'), class: 'logo'
 | 
			
		||||
 | 
			
		||||
  %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?
 | 
			
		||||
      = t('landing_strip_signup_html', sign_up_path: new_user_registration_path)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
      .avatar
 | 
			
		||||
        = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'u-photo'
 | 
			
		||||
    %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)
 | 
			
		||||
 | 
			
		||||
  - if embedded_view?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
        %div
 | 
			
		||||
          = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo'
 | 
			
		||||
      %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)
 | 
			
		||||
 | 
			
		||||
  .status__content.p-name.emojify<
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@
 | 
			
		|||
        = fa_icon('retweet fw')
 | 
			
		||||
      %span
 | 
			
		||||
        = 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')
 | 
			
		||||
  - elsif pinned
 | 
			
		||||
    .pre-header
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue