* Add animate custom emoji param to embed pages * Rename param, use it for avatars and gifs * Fix issues pointed by codeclimate and breaking test * Ignore brakeman warningmaster
@@ -54,6 +54,7 @@ class StatusesController < ApplicationController | |||||
skip_session! | skip_session! | ||||
expires_in 180, public: true | expires_in 180, public: true | ||||
response.headers['X-Frame-Options'] = 'ALLOWALL' | response.headers['X-Frame-Options'] = 'ALLOWALL' | ||||
@autoplay = ActiveModel::Type::Boolean.new.cast(params[:autoplay]) | |||||
render 'stream_entries/embed', layout: 'embedded' | render 'stream_entries/embed', layout: 'embedded' | ||||
end | end | ||||
@@ -23,7 +23,7 @@ class Formatter | |||||
unless status.local? | unless status.local? | ||||
html = reformat(raw_content) | html = reformat(raw_content) | ||||
html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify] | |||||
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify] | |||||
return html.html_safe # rubocop:disable Rails/OutputSafety | return html.html_safe # rubocop:disable Rails/OutputSafety | ||||
end | end | ||||
@@ -33,7 +33,7 @@ class Formatter | |||||
html = raw_content | html = raw_content | ||||
html = "RT @#{prepend_reblog} #{html}" if prepend_reblog | html = "RT @#{prepend_reblog} #{html}" if prepend_reblog | ||||
html = encode_and_link_urls(html, linkable_accounts) | html = encode_and_link_urls(html, linkable_accounts) | ||||
html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify] | |||||
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify] | |||||
html = simple_format(html, {}, sanitize: false) | html = simple_format(html, {}, sanitize: false) | ||||
html = html.delete("\n") | html = html.delete("\n") | ||||
@@ -53,7 +53,7 @@ class Formatter | |||||
def simplified_format(account, **options) | def simplified_format(account, **options) | ||||
html = account.local? ? linkify(account.note) : reformat(account.note) | html = account.local? ? linkify(account.note) : reformat(account.note) | ||||
html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify] | |||||
html = encode_custom_emojis(html, account.emojis, options[:autoplay]) if options[:custom_emojify] | |||||
html.html_safe # rubocop:disable Rails/OutputSafety | html.html_safe # rubocop:disable Rails/OutputSafety | ||||
end | end | ||||
@@ -63,20 +63,20 @@ class Formatter | |||||
def format_spoiler(status) | def format_spoiler(status) | ||||
html = encode(status.spoiler_text) | html = encode(status.spoiler_text) | ||||
html = encode_custom_emojis(html, status.emojis) | |||||
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) | |||||
html.html_safe # rubocop:disable Rails/OutputSafety | html.html_safe # rubocop:disable Rails/OutputSafety | ||||
end | end | ||||
def format_display_name(account, **options) | def format_display_name(account, **options) | ||||
html = encode(account.display_name.presence || account.username) | html = encode(account.display_name.presence || account.username) | ||||
html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify] | |||||
html = encode_custom_emojis(html, account.emojis, options[:autoplay]) if options[:custom_emojify] | |||||
html.html_safe # rubocop:disable Rails/OutputSafety | html.html_safe # rubocop:disable Rails/OutputSafety | ||||
end | end | ||||
def format_field(account, str, **options) | 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 | ||||
html = encode_and_link_urls(str, me: true) | html = encode_and_link_urls(str, me: true) | ||||
html = encode_custom_emojis(html, account.emojis) if options[:custom_emojify] | |||||
html = encode_custom_emojis(html, account.emojis, options[:autoplay]) if options[:custom_emojify] | |||||
html.html_safe # rubocop:disable Rails/OutputSafety | html.html_safe # rubocop:disable Rails/OutputSafety | ||||
end | end | ||||
@@ -120,10 +120,14 @@ class Formatter | |||||
end | end | ||||
end | end | ||||
def encode_custom_emojis(html, emojis) | |||||
def encode_custom_emojis(html, emojis, animate = false) | |||||
return html if emojis.empty? | return html if emojis.empty? | ||||
emoji_map = emojis.map { |e| [e.shortcode, full_asset_url(e.image.url(:static))] }.to_h | |||||
emoji_map = if animate | |||||
emojis.map { |e| [e.shortcode, full_asset_url(e.image.url)] }.to_h | |||||
else | |||||
emojis.map { |e| [e.shortcode, full_asset_url(e.image.url(:static))] }.to_h | |||||
end | |||||
i = -1 | i = -1 | ||||
tag_open_index = nil | tag_open_index = nil | ||||
@@ -1,10 +1,13 @@ | |||||
.detailed-status.detailed-status--flex | .detailed-status.detailed-status--flex | ||||
= link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do | = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do | ||||
.detailed-status__display-avatar | .detailed-status__display-avatar | ||||
= image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'account__avatar u-photo' | |||||
- if current_account&.user&.setting_auto_play_gif || autoplay | |||||
= image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '', class: 'account__avatar u-photo' | |||||
- else | |||||
= image_tag status.account.avatar.url(:static), width: 48, height: 48, alt: '', class: 'account__avatar u-photo' | |||||
%span.display-name | %span.display-name | ||||
%bdi | %bdi | ||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true) | |||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) | |||||
%span.display-name__account | %span.display-name__account | ||||
= acct(status.account) | = acct(status.account) | ||||
= fa_icon('lock') if status.account.locked? | = fa_icon('lock') if status.account.locked? | ||||
@@ -16,14 +19,14 @@ | |||||
%p{ style: 'margin-bottom: 0' }< | %p{ style: 'margin-bottom: 0' }< | ||||
%span.p-summary> #{Formatter.instance.format_spoiler(status)} | %span.p-summary> #{Formatter.instance.format_spoiler(status)} | ||||
%a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') | %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') | ||||
.e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true) | |||||
.e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) | |||||
- if !status.media_attachments.empty? | - if !status.media_attachments.empty? | ||||
- if status.media_attachments.first.video? | - if status.media_attachments.first.video? | ||||
- video = status.media_attachments.first | - video = status.media_attachments.first | ||||
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true, inline: true, alt: video.description | = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 670, height: 380, detailed: true, inline: true, alt: video.description | ||||
- else | - else | ||||
= react_component :media_gallery, height: 380, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } | |||||
= react_component :media_gallery, height: 380, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } | |||||
- elsif status.preview_cards.first | - elsif status.preview_cards.first | ||||
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_cards.first, serializer: REST::PreviewCardSerializer).as_json | = react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_cards.first, serializer: REST::PreviewCardSerializer).as_json | ||||
@@ -7,10 +7,13 @@ | |||||
= link_to TagManager.instance.url_for(status.account), class: 'status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do | = link_to TagManager.instance.url_for(status.account), class: 'status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do | ||||
.status__avatar | .status__avatar | ||||
%div | %div | ||||
= image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo account__avatar' | |||||
- if current_account&.user&.setting_auto_play_gif || autoplay | |||||
= image_tag status.account.avatar(:original), width: 48, height: 48, alt: '', class: 'u-photo account__avatar' | |||||
- else | |||||
= image_tag status.account.avatar(:static), width: 48, height: 48, alt: '', class: 'u-photo account__avatar' | |||||
%span.display-name | %span.display-name | ||||
%bdi | %bdi | ||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true) | |||||
%strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) | |||||
%span.display-name__account | %span.display-name__account | ||||
= acct(status.account) | = acct(status.account) | ||||
= fa_icon('lock') if status.account.locked? | = fa_icon('lock') if status.account.locked? | ||||
@@ -19,14 +22,14 @@ | |||||
%p{ style: 'margin-bottom: 0' }< | %p{ style: 'margin-bottom: 0' }< | ||||
%span.p-summary> #{Formatter.instance.format_spoiler(status)} | %span.p-summary> #{Formatter.instance.format_spoiler(status)} | ||||
%a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') | %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') | ||||
.e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true) | |||||
.e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) | |||||
- unless status.media_attachments.empty? | - unless status.media_attachments.empty? | ||||
- if status.media_attachments.first.video? | - if status.media_attachments.first.video? | ||||
- video = status.media_attachments.first | - video = status.media_attachments.first | ||||
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true, alt: video.description | = react_component :video, src: video.file.url(:original), preview: video.file.url(:small), sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, width: 610, height: 343, inline: true, alt: video.description | ||||
- else | - else | ||||
= react_component :media_gallery, height: 343, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } | |||||
= react_component :media_gallery, height: 343, sensitive: status.sensitive? && !current_account&.user&.setting_display_sensitive_media, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } | |||||
.status__action-bar | .status__action-bar | ||||
.status__action-bar__counter | .status__action-bar__counter | ||||
@@ -5,6 +5,7 @@ | |||||
is_successor ||= false | is_successor ||= false | ||||
direct_reply_id ||= false | direct_reply_id ||= false | ||||
parent_id ||= false | parent_id ||= false | ||||
autoplay ||= current_account&.user&.setting_auto_play_gif | |||||
is_direct_parent = direct_reply_id == status.id | is_direct_parent = direct_reply_id == status.id | ||||
is_direct_child = parent_id == status.in_reply_to_id | is_direct_child = parent_id == status.in_reply_to_id | ||||
centered ||= include_threads && !is_predecessor && !is_successor | centered ||= include_threads && !is_predecessor && !is_successor | ||||
@@ -18,7 +19,7 @@ | |||||
.entry{ class: entry_classes } | .entry{ class: entry_classes } | ||||
= link_to_more TagManager.instance.url_for(@next_ancestor) | = link_to_more TagManager.instance.url_for(@next_ancestor) | ||||
= render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id } | |||||
= render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }, autoplay: autoplay | |||||
.entry{ class: entry_classes } | .entry{ class: entry_classes } | ||||
@@ -38,14 +39,14 @@ | |||||
%span | %span | ||||
= t('stream_entries.pinned') | = t('stream_entries.pinned') | ||||
= render (centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status'), status: status.proper | |||||
= render (centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status'), status: status.proper, autoplay: autoplay | |||||
- if include_threads | - if include_threads | ||||
- if @since_descendant_thread_id | - if @since_descendant_thread_id | ||||
.entry{ class: entry_classes } | .entry{ class: entry_classes } | ||||
= link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1) | = link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1) | ||||
- @descendant_threads.each do |thread| | - @descendant_threads.each do |thread| | ||||
= render partial: 'stream_entries/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id } | |||||
= render partial: 'stream_entries/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }, autoplay: autoplay | |||||
- if thread[:next_status] | - if thread[:next_status] | ||||
.entry{ class: entry_classes } | .entry{ class: entry_classes } | ||||
@@ -1,3 +1,3 @@ | |||||
- cache @stream_entry.activity do | - cache @stream_entry.activity do | ||||
.activity-stream.activity-stream--headless | .activity-stream.activity-stream--headless | ||||
= render "stream_entries/#{@type}", @type.to_sym => @stream_entry.activity, centered: true | |||||
= render "stream_entries/#{@type}", @type.to_sym => @stream_entry.activity, centered: true, autoplay: @autoplay |
@@ -84,7 +84,7 @@ | |||||
"check_name": "PermitAttributes", | "check_name": "PermitAttributes", | ||||
"message": "Potentially dangerous key allowed for mass assignment", | "message": "Potentially dangerous key allowed for mass assignment", | ||||
"file": "app/controllers/admin/reports_controller.rb", | "file": "app/controllers/admin/reports_controller.rb", | ||||
"line": 86, | |||||
"line": 80, | |||||
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/", | "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/", | ||||
"code": "params.permit(:account_id, :resolved, :target_account_id)", | "code": "params.permit(:account_id, :resolved, :target_account_id)", | ||||
"render_path": null, | "render_path": null, | ||||
@@ -100,25 +100,6 @@ | |||||
{ | { | ||||
"warning_type": "Dynamic Render Path", | "warning_type": "Dynamic Render Path", | ||||
"warning_code": 15, | "warning_code": 15, | ||||
"fingerprint": "44d3f14e05d8fbb5b23e13ac02f15aa38b2a2f0f03b9ba76bab7f98e155a4a4e", | |||||
"check_name": "Render", | |||||
"message": "Render path contains parameter value", | |||||
"file": "app/views/stream_entries/embed.html.haml", | |||||
"line": 3, | |||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/", | |||||
"code": "render(action => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :centered => true })", | |||||
"render_path": [{"type":"controller","class":"StatusesController","method":"embed","line":58,"file":"app/controllers/statuses_controller.rb"}], | |||||
"location": { | |||||
"type": "template", | |||||
"template": "stream_entries/embed" | |||||
}, | |||||
"user_input": "params[:id]", | |||||
"confidence": "Weak", | |||||
"note": "" | |||||
}, | |||||
{ | |||||
"warning_type": "Dynamic Render Path", | |||||
"warning_code": 15, | |||||
"fingerprint": "4b6a895e2805578d03ceedbe1d469cc75a0c759eba093722523edb4b8683c873", | "fingerprint": "4b6a895e2805578d03ceedbe1d469cc75a0c759eba093722523edb4b8683c873", | ||||
"check_name": "Render", | "check_name": "Render", | ||||
"message": "Render path contains parameter value", | "message": "Render path contains parameter value", | ||||
@@ -175,6 +156,25 @@ | |||||
"note": "" | "note": "" | ||||
}, | }, | ||||
{ | { | ||||
"warning_type": "Dynamic Render Path", | |||||
"warning_code": 15, | |||||
"fingerprint": "67afc0d5f7775fa5bd91d1912e1b5505aeedef61876347546fa20f92fd6915e6", | |||||
"check_name": "Render", | |||||
"message": "Render path contains parameter value", | |||||
"file": "app/views/stream_entries/embed.html.haml", | |||||
"line": 3, | |||||
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/", | |||||
"code": "render(action => \"stream_entries/#{Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase}\", { Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity_type.downcase.to_sym => Account.find_local!(params[:account_username]).statuses.find(params[:id]).stream_entry.activity, :centered => true, :autoplay => ActiveModel::Type::Boolean.new.cast(params[:autoplay]) })", | |||||
"render_path": [{"type":"controller","class":"StatusesController","method":"embed","line":59,"file":"app/controllers/statuses_controller.rb"}], | |||||
"location": { | |||||
"type": "template", | |||||
"template": "stream_entries/embed" | |||||
}, | |||||
"user_input": "params[:id]", | |||||
"confidence": "Weak", | |||||
"note": "" | |||||
}, | |||||
{ | |||||
"warning_type": "Cross-Site Scripting", | "warning_type": "Cross-Site Scripting", | ||||
"warning_code": 4, | "warning_code": 4, | ||||
"fingerprint": "82f7b0d09beb3ab68e0fa16be63cedf4e820f2490326e9a1cec05761d92446cd", | "fingerprint": "82f7b0d09beb3ab68e0fa16be63cedf4e820f2490326e9a1cec05761d92446cd", | ||||
@@ -388,6 +388,6 @@ | |||||
"note": "" | "note": "" | ||||
} | } | ||||
], | ], | ||||
"updated": "2018-08-18 00:49:25 +0200", | |||||
"updated": "2018-08-30 21:55:10 +0200", | |||||
"brakeman_version": "4.2.1" | "brakeman_version": "4.2.1" | ||||
} | } |
@@ -12,6 +12,7 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d | |||||
allow(view).to receive(:full_asset_url).and_return('//asset.host/image.svg') | allow(view).to receive(:full_asset_url).and_return('//asset.host/image.svg') | ||||
allow(view).to receive(:local_time) | allow(view).to receive(:local_time) | ||||
allow(view).to receive(:local_time_ago) | allow(view).to receive(:local_time_ago) | ||||
allow(view).to receive(:current_account).and_return(nil) | |||||
assign(:instance_presenter, InstancePresenter.new) | assign(:instance_presenter, InstancePresenter.new) | ||||
end | end | ||||