diff --git a/Gemfile b/Gemfile index a81cd7c31a..a3cd76fc4f 100644 --- a/Gemfile +++ b/Gemfile @@ -114,7 +114,7 @@ group :production, :test do end group :test do - gem 'capybara', '~> 3.36' + gem 'capybara', '~> 3.37' gem 'climate_control', '~> 0.2' gem 'faker', '~> 2.20' gem 'microformats', '~> 4.2' diff --git a/Gemfile.lock b/Gemfile.lock index ad5fd70556..472f4e19cc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -144,7 +144,7 @@ GEM sshkit (~> 1.3) capistrano-yarn (2.0.2) capistrano (~> 3.0) - capybara (3.36.0) + capybara (3.37.1) addressable matrix mini_mime (>= 0.1.3) @@ -308,7 +308,7 @@ GEM rainbow (>= 2.0.0) i18n (1.10.0) concurrent-ruby (~> 1.0) - i18n-tasks (1.0.9) + i18n-tasks (1.0.10) activesupport (>= 4.0.2) ast (>= 2.1.0) better_html (~> 1.0) @@ -469,7 +469,7 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.6) + public_suffix (4.0.7) puma (5.6.4) nio4r (~> 2.0) pundit (2.2.0) @@ -536,7 +536,7 @@ GEM redis (4.5.1) redis-namespace (1.8.2) redis (>= 3.0.4) - regexp_parser (2.3.1) + regexp_parser (2.4.0) request_store (1.5.1) rack (>= 1.4) responders (3.0.1) @@ -614,7 +614,7 @@ GEM rufus-scheduler (~> 3.2) sidekiq (>= 4) tilt (>= 1.4.0) - sidekiq-unique-jobs (7.1.21) + sidekiq-unique-jobs (7.1.22) brpoplpush-redis_script (> 0.1.1, <= 2.0.0) concurrent-ruby (~> 1.0, >= 1.0.5) sidekiq (>= 5.0, < 8.0) @@ -745,7 +745,7 @@ DEPENDENCIES capistrano-rails (~> 1.6) capistrano-rbenv (~> 2.2) capistrano-yarn (~> 2.0) - capybara (~> 3.36) + capybara (~> 3.37) charlock_holmes (~> 0.7.7) chewy (~> 7.2) climate_control (~> 0.2) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 03c07c50b0..9949206cb3 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -45,7 +45,6 @@ class AccountsController < ApplicationController limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE @statuses = filtered_statuses.without_reblogs.limit(limit) @statuses = cache_collection(@statuses, Status) - render xml: RSS::AccountSerializer.render(@account, @statuses, params[:tag]) end format.json do diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 64736e77fc..46821a200c 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -27,7 +27,6 @@ class TagsController < ApplicationController format.rss do expires_in 0, public: true - render xml: RSS::TagSerializer.render(@tag, @statuses) end format.json do diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1c670fde0b..b26e68c4da 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -244,7 +244,7 @@ module ApplicationHelper end.values end - def prerender_custom_emojis(html, custom_emojis) - EmojiFormatter.new(html, custom_emojis, animate: prefers_autoplay?).to_s + def prerender_custom_emojis(html, custom_emojis, other_options = {}) + EmojiFormatter.new(html, custom_emojis, other_options.merge(animate: prefers_autoplay?)).to_s end end diff --git a/app/helpers/formatting_helper.rb b/app/helpers/formatting_helper.rb index 53e100dd27..526efd766f 100644 --- a/app/helpers/formatting_helper.rb +++ b/app/helpers/formatting_helper.rb @@ -18,6 +18,32 @@ module FormattingHelper html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []), content_type: status.content_type) end + def rss_status_content_format(status) + html = status_content_format(status) + + before_html = begin + if status.spoiler_text? + "

#{I18n.t('rss.content_warning', locale: valid_locale_or_nil(status.language))} #{h(status.spoiler_text)}


" + else + '' + end + end.html_safe # rubocop:disable Rails/OutputSafety + + after_html = begin + if status.preloadable_poll + "

#{status.preloadable_poll.options.map { |o| " #{h(o)}" }.join('
')}

" + else + '' + end + end.html_safe # rubocop:disable Rails/OutputSafety + + prerender_custom_emojis( + safe_join([before_html, html, after_html]), + status.emojis, + style: 'width: 1.1em; height: 1.1em; object-fit: contain; vertical-align: middle; margin: -.2ex .15em .2ex' + ).to_str + end + def account_bio_format(account) html_aware_format(account.note, account.local?) end diff --git a/app/javascript/flavours/glitch/actions/accounts.js b/app/javascript/flavours/glitch/actions/accounts.js index 0cf64e0762..f5871beb3e 100644 --- a/app/javascript/flavours/glitch/actions/accounts.js +++ b/app/javascript/flavours/glitch/actions/accounts.js @@ -88,6 +88,8 @@ export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = 'PINNED_ACCOUNTS_EDITOR export const PINNED_ACCOUNTS_EDITOR_RESET = 'PINNED_ACCOUNTS_EDITOR_RESET'; +export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL'; + export function fetchAccount(id) { return (dispatch, getState) => { dispatch(fetchRelationships([id])); @@ -798,6 +800,11 @@ export function unpinAccountFail(error) { }; }; +export const revealAccount = id => ({ + type: ACCOUNT_REVEAL, + id, +}); + export function fetchPinnedAccounts() { return (dispatch, getState) => { dispatch(fetchPinnedAccountsRequest()); diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.js index 396a36ea0f..489f607363 100644 --- a/app/javascript/flavours/glitch/components/account.js +++ b/app/javascript/flavours/glitch/components/account.js @@ -16,8 +16,10 @@ const messages = defineMessages({ requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, - mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'You are not currently muting notifications from @{name}. Click to mute notifications' }, - unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'You are currently muting notifications from @{name}. Click to unmute notifications' }, + mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' }, + unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, }); export default @injectIntl @@ -34,6 +36,7 @@ class Account extends ImmutablePureComponent { small: PropTypes.bool, actionIcon: PropTypes.string, actionTitle: PropTypes.string, + defaultAction: PropTypes.string, onActionClick: PropTypes.func, }; @@ -70,6 +73,7 @@ class Account extends ImmutablePureComponent { onActionClick, actionIcon, actionTitle, + defaultAction, } = this.props; if (!account) { @@ -114,6 +118,10 @@ class Account extends ImmutablePureComponent { {hidingNotificationsButton} ); + } else if (defaultAction === 'mute') { + buttons = ; + } else if (defaultAction === 'block') { + buttons = ; } else if (!account.get('moved') || following) { buttons = ; } diff --git a/app/javascript/flavours/glitch/components/avatar.js b/app/javascript/flavours/glitch/components/avatar.js index c5e9072c4a..6d53a5298d 100644 --- a/app/javascript/flavours/glitch/components/avatar.js +++ b/app/javascript/flavours/glitch/components/avatar.js @@ -1,13 +1,13 @@ -import classNames from 'classnames'; import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { autoPlayGif } from 'flavours/glitch/util/initial_state'; +import classNames from 'classnames'; export default class Avatar extends React.PureComponent { static propTypes = { - account: ImmutablePropTypes.map.isRequired, + account: ImmutablePropTypes.map, className: PropTypes.string, size: PropTypes.number.isRequired, style: PropTypes.object, @@ -45,11 +45,6 @@ export default class Avatar extends React.PureComponent { } = this.props; const { hovering } = this.state; - const src = account.get('avatar'); - const staticSrc = account.get('avatar_static'); - - const computedClass = classNames('account__avatar', { 'account__avatar-inline': inline }, className); - const style = { ...this.props.style, width: `${size}px`, @@ -57,19 +52,24 @@ export default class Avatar extends React.PureComponent { backgroundSize: `${size}px ${size}px`, }; - if (hovering || animate) { - style.backgroundImage = `url(${src})`; - } else { - style.backgroundImage = `url(${staticSrc})`; + if (account) { + const src = account.get('avatar'); + const staticSrc = account.get('avatar_static'); + + if (hovering || animate) { + style.backgroundImage = `url(${src})`; + } else { + style.backgroundImage = `url(${staticSrc})`; + } } return (
); } diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 68c6bae8ee..45aba53f74 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -82,6 +82,7 @@ class Header extends ImmutablePureComponent { onEditAccountNote: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; openEditProfile = () => { @@ -115,7 +116,7 @@ class Header extends ImmutablePureComponent { } render () { - const { account, intl, domain, identity_proofs } = this.props; + const { account, hidden, intl, domain } = this.props; if (!account) { return null; @@ -270,23 +271,29 @@ class Header extends ImmutablePureComponent { {info}
- + {!(suspended || hidden) && }
- +
-
- {actionBtn} - {bellBtn} + {!suspended && ( +
+ {!hidden && ( + + {actionBtn} + {bellBtn} + + )} - -
+ +
+ )}
@@ -298,23 +305,11 @@ class Header extends ImmutablePureComponent { - {!suspended && ( + {!(suspended || hidden) && (
- { (fields.size > 0 || identity_proofs.size > 0) && ( + { fields.size > 0 && (
- {identity_proofs.map((proof, i) => ( -
-
- -
- - - - -
-
- ))} {fields.map((pair, i) => (
diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index d6e607a373..645ff29ea4 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -12,7 +12,6 @@ export default class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, - identity_proofs: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, @@ -26,6 +25,7 @@ export default class Header extends ImmutablePureComponent { onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; static contextTypes = { @@ -93,7 +93,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs, identity_proofs } = this.props; + const { account, hidden, hideTabs } = this.props; if (account === null) { return null; @@ -101,11 +101,10 @@ export default class Header extends ImmutablePureComponent { return (
- {account.get('moved') && } + {(!hidden && account.get('moved')) && }