Adjusting public display of statuses to look similar to logged-in UI,
fix #361 with rich OEmbed display via iframe, fix #237 by hiding sensitive content behind a spoiler on public pages
This commit is contained in:
		
					parent
					
						
							
								aed25932b5
							
						
					
				
			
			
				commit
				
					
						5ae1b39ec9
					
				
			
		
					 13 changed files with 339 additions and 209 deletions
				
			
		|  | @ -1,8 +1,20 @@ | |||
| import emojify from './components/emoji' | ||||
| 
 | ||||
| $(() => { | ||||
|   $.each($('.entry .content, .name, .account__header__content'), (_, content) => { | ||||
|   $.each($('.entry .content, .entry .status__content, .display-name, .name, .account__header__content'), (_, content) => { | ||||
|     const $content = $(content); | ||||
|     $content.html(emojify($content.html())); | ||||
|   }); | ||||
| 
 | ||||
|   $('.video-player video').on('click', e => { | ||||
|     if (e.target.paused) { | ||||
|       e.target.play(); | ||||
|     } else { | ||||
|       e.target.pause(); | ||||
|     } | ||||
|   }); | ||||
| 
 | ||||
|   $('.media-spoiler').on('click', e => { | ||||
|     $(e.target).hide(); | ||||
|   }); | ||||
| }); | ||||
|  |  | |||
|  | @ -3,232 +3,281 @@ | |||
|   box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); | ||||
| 
 | ||||
|   .entry { | ||||
|     border-bottom: 1px solid #d9e1e8; | ||||
|     background: #fff; | ||||
|     border-left: 2px solid #fff; | ||||
| 
 | ||||
|     &.entry-reblog { | ||||
|       border-left-color: #2b90d9; | ||||
|     .status.light, .detailed-status.light { | ||||
|       border-bottom: 1px solid #d9e1e8; | ||||
|     } | ||||
| 
 | ||||
|     &.entry-predecessor, &.entry-successor { | ||||
|       background: #d9e1e8; | ||||
|       border-left-color: #d9e1e8; | ||||
|       border-bottom-color: darken(#d9e1e8, 10%); | ||||
|     &:last-child { | ||||
|       .status.light, .detailed-status.light { | ||||
|         border-bottom: 0; | ||||
|         border-radius: 0 0 4px 4px; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|       .header { | ||||
|         .header__right { | ||||
|           .counter-btn { | ||||
|             color: darken(#d9e1e8, 15%); | ||||
|           } | ||||
|     &:first-child { | ||||
|       .status.light, .detailed-status.light { | ||||
|         border-radius: 4px 4px 0 0; | ||||
|       } | ||||
| 
 | ||||
|       &:last-child { | ||||
|         .status.light, .detailed-status.light { | ||||
|           border-radius: 4px; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .status.light { | ||||
|     padding: 14px 14px 14px (48px + 14px*2); | ||||
|     position: relative; | ||||
|     min-height: 48px; | ||||
|     cursor: default; | ||||
|     background: lighten(#d9e1e8, 8%); | ||||
| 
 | ||||
|     .status__header { | ||||
|       font-size: 15px; | ||||
| 
 | ||||
|       .status__meta { | ||||
|         float: right; | ||||
|         font-size: 14px; | ||||
| 
 | ||||
|         .status__relative-time { | ||||
|           color: #9baec8; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &.entry-center { | ||||
|       border-bottom-color: darken(#d9e1e8, 10%); | ||||
|     .status__display-name { | ||||
|       display: block; | ||||
|       max-width: 100%; | ||||
|       padding-right: 25px; | ||||
|       color: #282c37; | ||||
|     } | ||||
| 
 | ||||
|     &.entry-follow, &.entry-favourite { | ||||
|       .content { | ||||
|         padding-top: 10px; | ||||
|         padding-bottom: 10px; | ||||
|     .status__avatar { | ||||
|       position: absolute; | ||||
|       left: 14px; | ||||
|       top: 14px; | ||||
|       width: 48px; | ||||
|       height: 48px; | ||||
| 
 | ||||
|       & > div { | ||||
|         width: 48px; | ||||
|         height: 48px; | ||||
|       } | ||||
| 
 | ||||
|       img { | ||||
|         display: block; | ||||
|         border-radius: 4px; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .display-name { | ||||
|       display: block; | ||||
|       max-width: 100%; | ||||
|       overflow: hidden; | ||||
|       white-space: nowrap; | ||||
|       text-overflow: ellipsis; | ||||
| 
 | ||||
|       strong { | ||||
|         font-weight: 500; | ||||
|         color: #282c37; | ||||
|       } | ||||
| 
 | ||||
|       span { | ||||
|         font-size: 14px; | ||||
|         color: #9baec8; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .status__content { | ||||
|       color: #282c37; | ||||
| 
 | ||||
|       a { | ||||
|         color: #2b90d9; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .status__attachments { | ||||
|       margin-top: 8px; | ||||
|       overflow: hidden; | ||||
|       width: 100%; | ||||
|       box-sizing: border-box; | ||||
|       height: 110px; | ||||
|       display: flex; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .detailed-status.light { | ||||
|     padding: 14px; | ||||
|     background: #fff; | ||||
|     cursor: default; | ||||
| 
 | ||||
|     .detailed-status__display-name { | ||||
|       display: block; | ||||
|       overflow: hidden; | ||||
|       margin-bottom: 15px; | ||||
| 
 | ||||
|       & > div { | ||||
|         float: left; | ||||
|         margin-right: 10px; | ||||
|       } | ||||
| 
 | ||||
|       .display-name { | ||||
|         display: block; | ||||
|         max-width: 100%; | ||||
|         overflow: hidden; | ||||
|         white-space: nowrap; | ||||
|         text-overflow: ellipsis; | ||||
| 
 | ||||
|         strong { | ||||
|           font-weight: 500; | ||||
|           color: #282c37; | ||||
|         } | ||||
| 
 | ||||
|         span { | ||||
|           font-size: 14px; | ||||
|           color: #9baec8; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     &:last-child { | ||||
|       border-bottom: 0; | ||||
|       border-radius: 0 0 4px 4px; | ||||
|     } | ||||
|   } | ||||
|     .avatar { | ||||
|       width: 48px; | ||||
|       height: 48px; | ||||
| 
 | ||||
|   .entry:first-child { | ||||
|     border-radius: 4px 4px 0 0; | ||||
| 
 | ||||
|     &:last-child { | ||||
|       border-radius: 4px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @media screen and (max-width: 700px) { | ||||
|     border-radius: 0; | ||||
|     box-shadow: none; | ||||
| 
 | ||||
|     .entry { | ||||
|       &:last-child { | ||||
|         border-radius: 0; | ||||
|       } | ||||
| 
 | ||||
|       &:first-child { | ||||
|         border-radius: 0; | ||||
| 
 | ||||
|         &:last-child { | ||||
|           border-radius: 0; | ||||
|         } | ||||
|       img { | ||||
|         display: block; | ||||
|         border-radius: 4px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .entry__container { | ||||
|     overflow: hidden; | ||||
|   } | ||||
|     .status__content { | ||||
|       color: #282c37; | ||||
| 
 | ||||
|   .avatar { | ||||
|     width: 56px; | ||||
|     padding: 15px 10px; | ||||
|     padding-right: 5px; | ||||
|     float: left; | ||||
| 
 | ||||
|     img { | ||||
|       width: 56px; | ||||
|       height: 56px; | ||||
|       display: block; | ||||
|       border-radius: 4px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .entry__container__container { | ||||
|     margin-left: 71px; | ||||
|   } | ||||
| 
 | ||||
|   .header { | ||||
|     margin-bottom: 10px; | ||||
|     padding: 15px; | ||||
|     padding-bottom: 0; | ||||
|     padding-left: 8px; | ||||
|     display: flex; | ||||
| 
 | ||||
|     .header__left { | ||||
|       flex: 1; | ||||
|       a { | ||||
|         color: #2b90d9; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .header__right { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     .name { | ||||
|       text-decoration: none; | ||||
|     .detailed-status__meta { | ||||
|       margin-top: 15px; | ||||
|       color: #9baec8; | ||||
|       font-size: 14px; | ||||
|       line-height: 18px; | ||||
| 
 | ||||
|       strong { | ||||
|         color: #282c37; | ||||
|       a { | ||||
|         color: inherit; | ||||
|       } | ||||
| 
 | ||||
|       span > span { | ||||
|         font-weight: 500; | ||||
|         font-size: 12px; | ||||
|         margin-left: 6px; | ||||
|         display: inline-block; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|       &:hover { | ||||
|         strong { | ||||
|           text-decoration: underline; | ||||
|         } | ||||
|     .detailed-status__attachments { | ||||
|       margin-top: 8px; | ||||
|       overflow: hidden; | ||||
|       width: 100%; | ||||
|       box-sizing: border-box; | ||||
|       height: 300px; | ||||
|       display: flex; | ||||
|     } | ||||
| 
 | ||||
|     .video-player { | ||||
|       margin-top: 8px; | ||||
|       height: 300px; | ||||
|       overflow: hidden; | ||||
| 
 | ||||
|       video { | ||||
|         position: relative; | ||||
|         z-index: 1; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         object-fit: cover; | ||||
|         top: 50%; | ||||
|         transform: translateY(-50%); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .pre-header { | ||||
|     border-bottom: 1px solid #d9e1e8; | ||||
|     color: #2b90d9; | ||||
|     padding: 5px 10px; | ||||
|     padding-left: 8px; | ||||
|     clear: both; | ||||
|   .media-item, .video-item { | ||||
|     box-sizing: border-box; | ||||
|     position: relative; | ||||
|     left: auto; | ||||
|     top: auto; | ||||
|     right: auto; | ||||
|     bottom: auto; | ||||
|     float: left; | ||||
|     border: medium none; | ||||
|     display: block; | ||||
|     flex: 1 1 auto; | ||||
|     height: 100%; | ||||
|     margin-right: 2px; | ||||
| 
 | ||||
|     .name { | ||||
|       color: #2b90d9; | ||||
|       font-weight: 500; | ||||
|       text-decoration: none; | ||||
| 
 | ||||
|       &:hover { | ||||
|         text-decoration: underline; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .content { | ||||
|     font-size: 14px; | ||||
|     padding: 0 15px; | ||||
|     padding-left: 8px; | ||||
|     padding-bottom: 15px; | ||||
|     color: #282c37; | ||||
|     word-wrap: break-word; | ||||
|     overflow: hidden; | ||||
|     white-space: pre-wrap; | ||||
| 
 | ||||
|     p { | ||||
|       margin-bottom: 18px; | ||||
| 
 | ||||
|       &:last-child { | ||||
|         margin-bottom: 0; | ||||
|       } | ||||
|     &:last-child { | ||||
|       margin-right: 0; | ||||
|     } | ||||
| 
 | ||||
|     a { | ||||
|       color: #2b90d9; | ||||
|       display: block; | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       background: no-repeat scroll center center / cover; | ||||
|       text-decoration: none; | ||||
| 
 | ||||
|       &:hover { | ||||
|         text-decoration: underline; | ||||
|       } | ||||
| 
 | ||||
|       &.mention { | ||||
|         &:hover { | ||||
|           text-decoration: none; | ||||
| 
 | ||||
|           span { | ||||
|             text-decoration: underline; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       cursor: zoom-in; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .time { | ||||
|     text-decoration: none; | ||||
|     color: #9baec8; | ||||
|   .video-item { | ||||
|     max-width: 196px; | ||||
| 
 | ||||
|     a { | ||||
|       cursor: pointer; | ||||
|     } | ||||
| 
 | ||||
|     .video-item__play { | ||||
|       position: absolute; | ||||
|       top: 50%; | ||||
|       left: 50%; | ||||
|       font-size: 36px; | ||||
|       transform: translate(-50%, -50%); | ||||
|       padding: 5px; | ||||
|       border-radius: 100px; | ||||
|       color: rgba(255, 255, 255, 0.8); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .media-spoiler { | ||||
|     background: #9baec8; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     cursor: pointer; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     flex-direction: column; | ||||
|     text-align: center; | ||||
|     transition: all 100ms linear; | ||||
| 
 | ||||
|     &:hover { | ||||
|       text-decoration: underline; | ||||
|       background: darken(#9baec8, 5%); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .media-attachments { | ||||
|     list-style: none; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|     display: block; | ||||
|     overflow: hidden; | ||||
|     padding-left: 10px; | ||||
|     margin-bottom: 15px; | ||||
| 
 | ||||
|     li { | ||||
|     span { | ||||
|       display: block; | ||||
|       float: left; | ||||
|       width: 120px; | ||||
|       height: 100px; | ||||
|       border-radius: 4px; | ||||
|       margin-right: 4px; | ||||
|       margin-bottom: 4px; | ||||
| 
 | ||||
|       a { | ||||
|         display: block; | ||||
|         width: 120px; | ||||
|         height: 100px; | ||||
|         border-radius: 4px; | ||||
|         background-position: center; | ||||
|         background-repeat: none; | ||||
|         background-size: cover; | ||||
|       &:first-child { | ||||
|         font-size: 14px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @media screen and (max-width: 360px) { | ||||
|     .avatar { | ||||
|       display: none; | ||||
|     } | ||||
| 
 | ||||
|     .entry__container__container { | ||||
|       margin-left: 7px; | ||||
|       &:last-child { | ||||
|         font-size: 11px; | ||||
|         font-weight: 500; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ class Api::OembedController < ApiController | |||
| 
 | ||||
|   def show | ||||
|     @stream_entry = stream_entry_from_url(params[:url]) | ||||
|     @width        = [300, params[:maxwidth].to_i].max | ||||
|     @height       = [200, params[:maxheight].to_i].max | ||||
|     @width        = params[:maxwidth].present?  ? params[:maxwidth].to_i  : 400 | ||||
|     @height       = params[:maxheight].present? ? params[:maxheight].to_i : 600 | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
|  |  | |||
|  | @ -9,8 +9,6 @@ class StreamEntriesController < ApplicationController | |||
|   before_action :check_account_suspension | ||||
| 
 | ||||
|   def show | ||||
|     @type = @stream_entry.activity_type.downcase | ||||
| 
 | ||||
|     respond_to do |format| | ||||
|       format.html do | ||||
|         return gone if @stream_entry.activity.nil? | ||||
|  | @ -27,7 +25,7 @@ class StreamEntriesController < ApplicationController | |||
| 
 | ||||
|   def embed | ||||
|     response.headers['X-Frame-Options'] = 'ALLOWALL' | ||||
|     @type = @stream_entry.activity_type.downcase | ||||
|     @external_links = true | ||||
| 
 | ||||
|     return gone if @stream_entry.activity.nil? | ||||
| 
 | ||||
|  | @ -46,6 +44,7 @@ class StreamEntriesController < ApplicationController | |||
| 
 | ||||
|   def set_stream_entry | ||||
|     @stream_entry = @account.stream_entries.find(params[:id]) | ||||
|     @type         = @stream_entry.activity_type.downcase | ||||
|   end | ||||
| 
 | ||||
|   def check_account_suspension | ||||
|  |  | |||
|  | @ -5,6 +5,10 @@ module StreamEntriesHelper | |||
|     account.display_name.blank? ? account.username : account.display_name | ||||
|   end | ||||
| 
 | ||||
|   def acct(account) | ||||
|     "@#{account.acct}#{@external_links && account.local? ? "@#{Rails.configuration.x.local_domain}" : ''}" | ||||
|   end | ||||
| 
 | ||||
|   def avatar_for_status_url(status) | ||||
|     status.reblog? ? status.reblog.account.avatar.url( :original) : status.account.avatar.url( :original) | ||||
|   end | ||||
|  |  | |||
|  | @ -9,6 +9,6 @@ node(:author_url) { |entry| account_url(entry.account) } | |||
| node(:provider_name) { Rails.configuration.x.local_domain } | ||||
| node(:provider_url) { root_url } | ||||
| node(:cache_age) { 86_400 } | ||||
| node(:html) { |entry| "<div style=\"position: relative; height: 0; overflow: hidden; padding-top: 30px; padding-bottom: 56.25%\"><iframe src=\"#{embed_account_stream_entry_url(entry.account, entry)}\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden\" frameborder=\"0\" width=\"#{@width}\" scrolling=\"no\"></iframe></div>" } | ||||
| node(:html) { |entry| "<iframe src=\"#{embed_account_stream_entry_url(entry.account, entry)}\" style=\"width: 100%; overflow: hidden\" frameborder=\"0\" width=\"#{@width}\" height=\"#{@height}\" scrolling=\"no\"></iframe>" } | ||||
| node(:width) { @width } | ||||
| node(:height) { nil } | ||||
|  |  | |||
							
								
								
									
										3
									
								
								app/views/stream_entries/_content_spoiler.html.haml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/views/stream_entries/_content_spoiler.html.haml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| .media-spoiler | ||||
|   %span= t('stream_entries.sensitive_content') | ||||
|   %span= t('stream_entries.click_to_show') | ||||
							
								
								
									
										36
									
								
								app/views/stream_entries/_detailed_status.html.haml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/views/stream_entries/_detailed_status.html.haml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| .detailed-status.light | ||||
|   = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name', target: @external_links ? '_blank' : nil, rel: 'noopener' do | ||||
|     %div | ||||
|       %div.avatar | ||||
|         = image_tag status.account.avatar.url(:original), width: 48, height: 48, alt: '' | ||||
|     %span.display-name | ||||
|       %strong= display_name(status.account) | ||||
|       %span= acct(status.account) | ||||
| 
 | ||||
|   .status__content= Formatter.instance.format(status) | ||||
| 
 | ||||
|   - unless status.media_attachments.empty? | ||||
|     - if status.media_attachments.first.video? | ||||
|       .video-player | ||||
|         - if status.sensitive? | ||||
|           = render partial: 'stream_entries/content_spoiler' | ||||
|         %video{ src: status.media_attachments.first.file.url(:original), loop: true } | ||||
|     - else | ||||
|       .detailed-status__attachments | ||||
|         - if status.sensitive? | ||||
|           = render partial: 'stream_entries/content_spoiler' | ||||
|         - status.media_attachments.each do |media| | ||||
|           .media-item | ||||
|             = link_to '', (media.remote_url.blank? ? media.file.url(:original) : media.remote_url), style: "background-image: url(#{media.file.url(:original)})", target: '_blank', rel: 'noopener' | ||||
| 
 | ||||
|   %div.detailed-status__meta | ||||
|     = link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: @external_links ? '_blank' : nil, rel: 'noopener' do | ||||
|       %span= l(status.created_at) | ||||
|     · | ||||
|     %span | ||||
|       = fa_icon('retweet') | ||||
|       %span= status.reblogs.count | ||||
|     · | ||||
|     %span | ||||
|       = fa_icon('star') | ||||
|       %span= status.favourites.count | ||||
							
								
								
									
										28
									
								
								app/views/stream_entries/_simple_status.html.haml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/views/stream_entries/_simple_status.html.haml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| .status.light | ||||
|   .status__header | ||||
|     .status__meta | ||||
|       = link_to time_ago_in_words(status.created_at), TagManager.instance.url_for(status), class: 'status__relative-time', title: l(status.created_at), target: @external_links ? '_blank' : nil, rel: 'noopener' | ||||
| 
 | ||||
|     = link_to TagManager.instance.url_for(status.account), class: 'status__display-name', target: @external_links ? '_blank' : nil, rel: 'noopener' do | ||||
|       .status__avatar | ||||
|         %div | ||||
|           = image_tag status.account.avatar(:original), width: 48, height: 48, alt: '' | ||||
|       %span.display-name | ||||
|         %strong= display_name(status.account) | ||||
|         %span= acct(status.account) | ||||
| 
 | ||||
|   .status__content= Formatter.instance.format(status) | ||||
| 
 | ||||
|   - unless status.media_attachments.empty? | ||||
|     .status__attachments | ||||
|       - if status.sensitive? | ||||
|         = render partial: 'stream_entries/content_spoiler' | ||||
|       - if status.media_attachments.first.video? | ||||
|         .video-item | ||||
|           = link_to (status.media_attachments.first.remote_url.blank? ? status.media_attachments.first.file.url(:original) : status.media_attachments.first.remote_url), style: "background-image: url(#{status.media_attachments.first.file.url(:small)})", target: '_blank', rel: 'noopener' do | ||||
|             .video-item__play | ||||
|               = fa_icon('play') | ||||
|       - else | ||||
|         - status.media_attachments.each do |media| | ||||
|           .media-item | ||||
|             = link_to '', (media.remote_url.blank? ? media.file.url(:original) : media.remote_url), style: "background-image: url(#{media.file.url(:original)})", target: '_blank', rel: 'noopener' | ||||
|  | @ -1,7 +1,7 @@ | |||
| - include_threads ||= false | ||||
| - is_predecessor  ||= false | ||||
| - is_successor    ||= false | ||||
| - centered          = include_threads && !is_predecessor && !is_successor | ||||
| - centered        ||= include_threads && !is_predecessor && !is_successor | ||||
| 
 | ||||
| - if status.reply? && include_threads | ||||
|   = render partial: 'status', collection: @ancestors, as: :status, locals: { is_predecessor: true } | ||||
|  | @ -13,28 +13,7 @@ | |||
|       Shared by | ||||
|       = link_to display_name(status.account), TagManager.instance.url_for(status.account), class: 'name' | ||||
| 
 | ||||
|   .entry__container | ||||
|     .avatar | ||||
|       = image_tag avatar_for_status_url(status) | ||||
| 
 | ||||
|     .entry__container__container | ||||
|       .header | ||||
|         .header__left | ||||
|           = link_to TagManager.instance.url_for(proper_status(status).account), class: 'name' do | ||||
|             %strong= display_name(proper_status(status).account) | ||||
|             = "@#{proper_status(status).account.acct}" | ||||
| 
 | ||||
|         .header__right | ||||
|           = link_to TagManager.instance.url_for(proper_status(status)), class: 'time' do | ||||
|             %span{ title: proper_status(status).created_at } | ||||
|               = relative_time(proper_status(status).created_at) | ||||
| 
 | ||||
|       .content= Formatter.instance.format(proper_status(status)) | ||||
| 
 | ||||
|       - if (status.reblog? ? status.reblog : status).media_attachments.size > 0 | ||||
|         %ul.media-attachments | ||||
|           - (status.reblog? ? status.reblog : status).media_attachments.each do |media| | ||||
|             %li.transparent-background= link_to '', media.file.url( :original), style: "background-image: url(#{media.file.url( :small)})", target: '_blank' | ||||
|   = render partial: centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status', locals: { status: proper_status(status) } | ||||
| 
 | ||||
| - if include_threads | ||||
|   = render partial: 'status', collection: @descendants, as: :status, locals: { is_successor: true } | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| .activity-stream.activity-stream-headless | ||||
|   = render partial: @type, locals: { @type.to_sym => @stream_entry.activity } | ||||
|   = render partial: @type, locals: { @type.to_sym => @stream_entry.activity, centered: true } | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ search: | |||
| ignore_unused: | ||||
|   - 'activerecord.attributes.*' | ||||
|   - '{devise,will_paginate,doorkeeper}.*' | ||||
|   - '{datetime,time}.*' | ||||
|   - 'simple_form.{yes,no}' | ||||
|   - 'simple_form.{placeholders,hints,labels}.*' | ||||
|   - 'simple_form.{error_notification,required}.:' | ||||
|  |  | |||
|  | @ -26,6 +26,20 @@ en: | |||
|     resend_confirmation: Resend confirmation instructions | ||||
|     reset_password: Reset password | ||||
|     set_new_password: Set new password | ||||
|   datetime: | ||||
|     distance_in_words: | ||||
|       about_x_hours: "%{count}h" | ||||
|       about_x_months: "%{count}mo" | ||||
|       about_x_years: "%{count}y" | ||||
|       almost_x_years: "%{count}y" | ||||
|       half_a_minute: Just now | ||||
|       less_than_x_minutes: "%{count}m" | ||||
|       less_than_x_seconds: Just now | ||||
|       over_x_years: "%{count}y" | ||||
|       x_days: "%{count}d" | ||||
|       x_minutes: "%{count}m" | ||||
|       x_months: "%{count}mo" | ||||
|       x_seconds: "%{count}s" | ||||
|   generic: | ||||
|     changes_saved_msg: Changes successfully saved! | ||||
|     powered_by: powered by %{link} | ||||
|  | @ -53,8 +67,13 @@ en: | |||
|     edit_profile: Edit profile | ||||
|     preferences: Preferences | ||||
|   stream_entries: | ||||
|     click_to_show: Click to show | ||||
|     favourited: favourited a post by | ||||
|     is_now_following: is now following | ||||
|     sensitive_content: Sensitive content | ||||
|   time: | ||||
|     formats: | ||||
|       default: "%b %d, %Y, %H:%M" | ||||
|   users: | ||||
|     invalid_email: The e-mail address is invalid | ||||
|   will_paginate: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue