diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/api/v1/accounts/credentials_controller.rb | 2 | ||||
-rw-r--r-- | app/javascript/mastodon/actions/search.js | 2 | ||||
-rw-r--r-- | app/javascript/mastodon/components/media_gallery.js | 6 | ||||
-rw-r--r-- | app/javascript/styles/mastodon/basics.scss | 1 | ||||
-rw-r--r-- | app/javascript/styles/mastodon/components.scss | 20 | ||||
-rw-r--r-- | app/javascript/styles/mastodon/stream_entries.scss | 20 | ||||
-rw-r--r-- | app/lib/activitypub/activity.rb | 2 | ||||
-rw-r--r-- | app/lib/ostatus/activity/creation.rb | 2 | ||||
-rw-r--r-- | app/models/account_domain_block.rb | 8 | ||||
-rw-r--r-- | app/models/block.rb | 4 | ||||
-rw-r--r-- | app/models/concerns/account_avatar.rb | 12 | ||||
-rw-r--r-- | app/models/concerns/account_header.rb | 12 | ||||
-rw-r--r-- | app/models/concerns/relationship_cacheable.rb | 16 | ||||
-rw-r--r-- | app/models/follow.rb | 1 | ||||
-rw-r--r-- | app/models/follow_request.rb | 1 | ||||
-rw-r--r-- | app/models/mute.rb | 4 | ||||
-rw-r--r-- | app/models/status.rb | 6 | ||||
-rw-r--r-- | app/presenters/account_relationships_presenter.rb | 68 |
18 files changed, 144 insertions, 43 deletions
diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb index da534d960..68af22529 100644 --- a/app/controllers/api/v1/accounts/credentials_controller.rb +++ b/app/controllers/api/v1/accounts/credentials_controller.rb @@ -20,6 +20,6 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController private def account_params - params.permit(:display_name, :note, :avatar, :header) + params.permit(:display_name, :note, :avatar, :header, :locked) end end diff --git a/app/javascript/mastodon/actions/search.js b/app/javascript/mastodon/actions/search.js index 78c6109f7..73cb106ec 100644 --- a/app/javascript/mastodon/actions/search.js +++ b/app/javascript/mastodon/actions/search.js @@ -1,4 +1,5 @@ import api from '../api'; +import { fetchRelationships } from './accounts'; export const SEARCH_CHANGE = 'SEARCH_CHANGE'; export const SEARCH_CLEAR = 'SEARCH_CLEAR'; @@ -38,6 +39,7 @@ export function submitSearch() { }, }).then(response => { dispatch(fetchSearchSuccess(response.data)); + dispatch(fetchRelationships(response.data.accounts.map(item => item.id))); }).catch(error => { dispatch(fetchSearchFail(error)); }); diff --git a/app/javascript/mastodon/components/media_gallery.js b/app/javascript/mastodon/components/media_gallery.js index 00943e205..a3ffc45ea 100644 --- a/app/javascript/mastodon/components/media_gallery.js +++ b/app/javascript/mastodon/components/media_gallery.js @@ -227,12 +227,8 @@ export default class MediaGallery extends React.PureComponent { const style = {}; if (this.isStandaloneEligible()) { - if (!visible && width) { - // only need to forcibly set the height in "sensitive" mode + if (width) { style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']); - } else { - // layout automatically, using image's natural aspect ratio - style.height = ''; } } else { // crop the image diff --git a/app/javascript/styles/mastodon/basics.scss b/app/javascript/styles/mastodon/basics.scss index 0e3b9ad6b..bec0d4d91 100644 --- a/app/javascript/styles/mastodon/basics.scss +++ b/app/javascript/styles/mastodon/basics.scss @@ -122,5 +122,6 @@ button { height: 100%; align-items: center; justify-content: center; + outline: 0 !important; } } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index d57481f97..66e4adc2b 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -686,12 +686,13 @@ background: transparent; border: 0; color: lighten($ui-base-color, 8%); - font-weight: 500; + font-weight: 700; font-size: 11px; padding: 0 6px; text-transform: uppercase; - line-height: inherit; + line-height: 20px; cursor: pointer; + vertical-align: middle; } .status__prepend-icon-wrapper { @@ -899,6 +900,11 @@ height: 24px; margin: -1px 0 0; } + + .status__content__spoiler-link { + line-height: 24px; + margin: -1px 0 0; + } } .video-player { @@ -2667,12 +2673,16 @@ a.status-card { background: $base-overlay-background; color: $ui-primary-color; border: 0; + padding: 0; width: 100%; height: 100%; + border-radius: 4px; + appearance: none; &:hover, &:active, &:focus { + padding: 0; color: lighten($ui-primary-color, 8%); } } @@ -2685,7 +2695,7 @@ a.status-card { .media-spoiler__trigger { display: block; font-size: 11px; - font-weight: 500; + font-weight: 700; } .spoiler-button { @@ -4091,6 +4101,7 @@ a.status-card { box-sizing: border-box; margin-top: 8px; overflow: hidden; + border-radius: 4px; position: relative; width: 100%; } @@ -4101,6 +4112,8 @@ a.status-card { display: block; float: left; position: relative; + border-radius: 4px; + overflow: hidden; &.standalone { .media-gallery__item-gifv-thumbnail { @@ -4113,6 +4126,7 @@ a.status-card { cursor: zoom-in; display: block; text-decoration: none; + color: $ui-secondary-color; height: 100%; line-height: 0; diff --git a/app/javascript/styles/mastodon/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss index e11ca29d9..442b143a0 100644 --- a/app/javascript/styles/mastodon/stream_entries.scss +++ b/app/javascript/styles/mastodon/stream_entries.scss @@ -146,10 +146,10 @@ a.status__content__spoiler-link { color: $primary-text-color; - background: $ui-primary-color; + background: $ui-base-color; &:hover { - background: lighten($ui-primary-color, 8%); + background: lighten($ui-base-color, 8%); } } } @@ -214,10 +214,10 @@ a.status__content__spoiler-link { color: $primary-text-color; - background: $ui-primary-color; + background: $ui-base-color; &:hover { - background: lighten($ui-primary-color, 8%); + background: lighten($ui-base-color, 8%); } } } @@ -260,16 +260,8 @@ } .media-spoiler { - background: $ui-primary-color; - color: $white; - transition: all 40ms linear; - - &:hover, - &:active, - &:focus { - background: darken($ui-primary-color, 2%); - color: unset; - } + background: $ui-base-color; + color: $ui-primary-color; } .pre-header { diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 0f9e4f263..4617905c6 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -74,7 +74,7 @@ class ActivityPub::Activity # Only continue if the status is supposed to have # arrived in real-time - return unless @options[:override_timestamps] + return unless @options[:override_timestamps] || status.within_realtime_window? distribute_to_followers(status) end diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb index b38407cd3..7cf2d90dc 100644 --- a/app/lib/ostatus/activity/creation.rb +++ b/app/lib/ostatus/activity/creation.rb @@ -61,7 +61,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base Rails.logger.debug "Queuing remote status #{status.id} (#{id}) for distribution" LinkCrawlWorker.perform_async(status.id) unless status.spoiler_text? - DistributionWorker.perform_async(status.id) if @options[:override_timestamps] + DistributionWorker.perform_async(status.id) if @options[:override_timestamps] || status.within_realtime_window? status end diff --git a/app/models/account_domain_block.rb b/app/models/account_domain_block.rb index abcc923b3..bc00b4f32 100644 --- a/app/models/account_domain_block.rb +++ b/app/models/account_domain_block.rb @@ -16,12 +16,16 @@ class AccountDomainBlock < ApplicationRecord belongs_to :account validates :domain, presence: true, uniqueness: { scope: :account_id } - after_create :remove_blocking_cache - after_destroy :remove_blocking_cache + after_commit :remove_blocking_cache + after_commit :remove_relationship_cache private def remove_blocking_cache Rails.cache.delete("exclude_domains_for:#{account_id}") end + + def remove_relationship_cache + Rails.cache.delete_matched("relationship:#{account_id}:*") + end end diff --git a/app/models/block.rb b/app/models/block.rb index 441e6bca3..d6ecabd3b 100644 --- a/app/models/block.rb +++ b/app/models/block.rb @@ -12,14 +12,14 @@ class Block < ApplicationRecord include Paginable + include RelationshipCacheable belongs_to :account belongs_to :target_account, class_name: 'Account' validates :account_id, uniqueness: { scope: :target_account_id } - after_create :remove_blocking_cache - after_destroy :remove_blocking_cache + after_commit :remove_blocking_cache private diff --git a/app/models/concerns/account_avatar.rb b/app/models/concerns/account_avatar.rb index 8a5c9a22c..53d0d876f 100644 --- a/app/models/concerns/account_avatar.rb +++ b/app/models/concerns/account_avatar.rb @@ -7,9 +7,15 @@ module AccountAvatar class_methods do def avatar_styles(file) - styles = { original: '120x120#' } - styles[:static] = { format: 'png', convert_options: '-coalesce' } if file.content_type == 'image/gif' + styles = {} + geometry = Paperclip::Geometry.from_file(file) + + styles[:original] = '120x120#' if geometry.width != geometry.height || geometry.width > 120 || geometry.height > 120 + styles[:static] = { format: 'png', convert_options: '-coalesce' } if file.content_type == 'image/gif' + styles + rescue Paperclip::Errors::NotIdentifiedByImageMagickError + {} end private :avatar_styles @@ -17,7 +23,7 @@ module AccountAvatar included do # Avatar upload - has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '-quality 80 -strip' } + has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '-strip' } validates_attachment_content_type :avatar, content_type: IMAGE_MIME_TYPES validates_attachment_size :avatar, less_than: 2.megabytes end diff --git a/app/models/concerns/account_header.rb b/app/models/concerns/account_header.rb index aff2aa3f9..991473d8c 100644 --- a/app/models/concerns/account_header.rb +++ b/app/models/concerns/account_header.rb @@ -7,9 +7,15 @@ module AccountHeader class_methods do def header_styles(file) - styles = { original: '700x335#' } - styles[:static] = { format: 'png', convert_options: '-coalesce' } if file.content_type == 'image/gif' + styles = {} + geometry = Paperclip::Geometry.from_file(file) + + styles[:original] = '700x335#' unless geometry.width == 700 && geometry.height == 335 + styles[:static] = { format: 'png', convert_options: '-coalesce' } if file.content_type == 'image/gif' + styles + rescue Paperclip::Errors::NotIdentifiedByImageMagickError + {} end private :header_styles @@ -17,7 +23,7 @@ module AccountHeader included do # Header upload - has_attached_file :header, styles: ->(f) { header_styles(f) }, convert_options: { all: '-quality 80 -strip' } + has_attached_file :header, styles: ->(f) { header_styles(f) }, convert_options: { all: '-strip' } validates_attachment_content_type :header, content_type: IMAGE_MIME_TYPES validates_attachment_size :header, less_than: 2.megabytes end diff --git a/app/models/concerns/relationship_cacheable.rb b/app/models/concerns/relationship_cacheable.rb new file mode 100644 index 000000000..0d9359f7e --- /dev/null +++ b/app/models/concerns/relationship_cacheable.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module RelationshipCacheable + extend ActiveSupport::Concern + + included do + after_commit :remove_relationship_cache + end + + private + + def remove_relationship_cache + Rails.cache.delete("relationship:#{account_id}:#{target_account_id}") + Rails.cache.delete("relationship:#{target_account_id}:#{account_id}") + end +end diff --git a/app/models/follow.rb b/app/models/follow.rb index f953b8e3e..8e6fe537a 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -13,6 +13,7 @@ class Follow < ApplicationRecord include Paginable + include RelationshipCacheable belongs_to :account, counter_cache: :following_count diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb index bd6c4a0b9..cde26ceed 100644 --- a/app/models/follow_request.rb +++ b/app/models/follow_request.rb @@ -13,6 +13,7 @@ class FollowRequest < ApplicationRecord include Paginable + include RelationshipCacheable belongs_to :account belongs_to :target_account, class_name: 'Account' diff --git a/app/models/mute.rb b/app/models/mute.rb index da4787179..ebb3818c7 100644 --- a/app/models/mute.rb +++ b/app/models/mute.rb @@ -13,14 +13,14 @@ class Mute < ApplicationRecord include Paginable + include RelationshipCacheable belongs_to :account belongs_to :target_account, class_name: 'Account' validates :account_id, uniqueness: { scope: :target_account_id } - after_create :remove_blocking_cache - after_destroy :remove_blocking_cache + after_commit :remove_blocking_cache private diff --git a/app/models/status.rb b/app/models/status.rb index 6fb9b15dd..86bf3deba 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -83,6 +83,8 @@ class Status < ApplicationRecord delegate :domain, to: :account, prefix: true + REAL_TIME_WINDOW = 6.hours + def searchable_by(preloaded = nil) ids = [account_id] @@ -111,6 +113,10 @@ class Status < ApplicationRecord !reblog_of_id.nil? end + def within_realtime_window? + created_at >= REAL_TIME_WINDOW.ago + end + def verb if destroyed? :delete diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index bf1ba3716..d27fb7b01 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -5,11 +5,67 @@ class AccountRelationshipsPresenter :muting, :requested, :domain_blocking def initialize(account_ids, current_account_id, **options) - @following = Account.following_map(account_ids, current_account_id).merge(options[:following_map] || {}) - @followed_by = Account.followed_by_map(account_ids, current_account_id).merge(options[:followed_by_map] || {}) - @blocking = Account.blocking_map(account_ids, current_account_id).merge(options[:blocking_map] || {}) - @muting = Account.muting_map(account_ids, current_account_id).merge(options[:muting_map] || {}) - @requested = Account.requested_map(account_ids, current_account_id).merge(options[:requested_map] || {}) - @domain_blocking = Account.domain_blocking_map(account_ids, current_account_id).merge(options[:domain_blocking_map] || {}) + @account_ids = account_ids.map { |a| a.is_a?(Account) ? a.id : a } + @current_account_id = current_account_id + + @following = cached[:following].merge(Account.following_map(@uncached_account_ids, @current_account_id)) + @followed_by = cached[:followed_by].merge(Account.followed_by_map(@uncached_account_ids, @current_account_id)) + @blocking = cached[:blocking].merge(Account.blocking_map(@uncached_account_ids, @current_account_id)) + @muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id)) + @requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id)) + @domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id)) + + cache_uncached! + + @following.merge!(options[:following_map] || {}) + @followed_by.merge!(options[:followed_by_map] || {}) + @blocking.merge!(options[:blocking_map] || {}) + @muting.merge!(options[:muting_map] || {}) + @requested.merge!(options[:requested_map] || {}) + @domain_blocking.merge!(options[:domain_blocking_map] || {}) + end + + private + + def cached + return @cached if defined?(@cached) + + @cached = { + following: {}, + followed_by: {}, + blocking: {}, + muting: {}, + requested: {}, + domain_blocking: {}, + } + + @uncached_account_ids = [] + + @account_ids.each do |account_id| + maps_for_account = Rails.cache.read("relationship:#{@current_account_id}:#{account_id}") + + if maps_for_account.is_a?(Hash) + @cached.merge!(maps_for_account) + else + @uncached_account_ids << account_id + end + end + + @cached + end + + def cache_uncached! + @uncached_account_ids.each do |account_id| + maps_for_account = { + following: { account_id => following[account_id] }, + followed_by: { account_id => followed_by[account_id] }, + blocking: { account_id => blocking[account_id] }, + muting: { account_id => muting[account_id] }, + requested: { account_id => requested[account_id] }, + domain_blocking: { account_id => domain_blocking[account_id] }, + } + + Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day) + end end end |