diff options
Diffstat (limited to 'app')
24 files changed, 89 insertions, 56 deletions
diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index af51e32d5..8f5e1887e 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -36,6 +36,6 @@ class ActivityPub::InboxesController < Api::BaseController end def process_payload - ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8')) + ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body.force_encoding('UTF-8'), @account&.id) end end diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index fc299f74c..f2190ddf9 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -9,6 +9,13 @@ module Admin before_action :require_staff! before_action :set_pack + before_action :set_body_classes + + private + + def set_body_classes + @body_classes = 'admin' + end def set_pack use_pack 'admin' diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index 0d1200fcc..f1e110d87 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -8,6 +8,7 @@ class FiltersController < ApplicationController before_action :set_filters, only: :index before_action :set_filter, only: [:edit, :update, :destroy] before_action :set_pack + before_action :set_body_classes def index @filters = current_account.custom_filters @@ -59,4 +60,8 @@ class FiltersController < ApplicationController def resource_params params.require(:custom_filter).permit(:phrase, :expires_in, :irreversible, :whole_word, context: []) end + + def set_body_classes + @body_classes = 'admin' + end end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 3dc934761..52cddc404 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -7,6 +7,7 @@ class InvitesController < ApplicationController before_action :authenticate_user! before_action :set_pack + before_action :set_body_classes def index authorize :invite, :create? @@ -49,4 +50,8 @@ class InvitesController < ApplicationController def resource_params params.require(:invite).permit(:max_uses, :expires_in, :autofollow) end + + def set_body_classes + @body_classes = 'admin' + end end diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 7322d461b..34ef16568 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -5,8 +5,13 @@ class Settings::BaseController < ApplicationController before_action :authenticate_user! before_action :set_pack + before_action :set_body_classes def set_pack use_pack 'settings' end + + def set_body_classes + @body_classes = 'admin' + end end diff --git a/app/controllers/settings/follower_domains_controller.rb b/app/controllers/settings/follower_domains_controller.rb index 83945df52..8aae379aa 100644 --- a/app/controllers/settings/follower_domains_controller.rb +++ b/app/controllers/settings/follower_domains_controller.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'sidekiq-bulk' - class Settings::FollowerDomainsController < Settings::BaseController def show @account = current_account diff --git a/app/controllers/settings/sessions_controller.rb b/app/controllers/settings/sessions_controller.rb index 780ea64b4..f235dd477 100644 --- a/app/controllers/settings/sessions_controller.rb +++ b/app/controllers/settings/sessions_controller.rb @@ -3,6 +3,7 @@ # Intentionally does not inherit from BaseController class Settings::SessionsController < ApplicationController before_action :set_session, only: :destroy + before_action :set_body_classes def destroy @session.destroy! @@ -15,4 +16,8 @@ class Settings::SessionsController < ApplicationController def set_session @session = current_user.session_activations.find(params[:id]) end + + def set_body_classes + @body_classes = 'admin' + end end diff --git a/app/javascript/core/settings.js b/app/javascript/core/settings.js index af97c84f9..23a303747 100644 --- a/app/javascript/core/settings.js +++ b/app/javascript/core/settings.js @@ -1,30 +1,16 @@ // This file will be loaded on settings pages, regardless of theme. -const { length } = require('stringz'); const { delegate } = require('rails-ujs'); import emojify from '../mastodon/features/emoji/emoji'; delegate(document, '#account_display_name', 'input', ({ target }) => { - const nameCounter = document.querySelector('.name-counter'); - const name = document.querySelector('.card .display-name strong'); - - if (nameCounter) { - nameCounter.textContent = 30 - length(target.value); - } + const name = document.querySelector('.card .display-name strong'); if (name) { name.innerHTML = emojify(target.value); } }); -delegate(document, '#account_note', 'input', ({ target }) => { - const noteCounter = document.querySelector('.note-counter'); - - if (noteCounter) { - noteCounter.textContent = 500 - length(target.value); - } -}); - delegate(document, '#account_avatar', 'change', ({ target }) => { const avatar = document.querySelector('.card .avatar img'); const [file] = target.files || []; diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index fac8d32a1..86d83122f 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -142,7 +142,7 @@ export function submitCompose(routerHistory) { } }; - if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0) { + if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0 && routerHistory) { routerHistory.push('/timelines/direct'); } else if (response.data.visibility !== 'direct') { insertIfOnline('home'); diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 1b1a4f8d4..4b56c7fdd 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -89,7 +89,7 @@ class ComposeForm extends ImmutablePureComponent { return; } - this.props.onSubmit(this.context.router.history); + this.props.onSubmit(this.context.router ? this.context.router.history : null); } onSuggestionsClearRequested = () => { diff --git a/app/javascript/mastodon/features/compose/components/upload.js b/app/javascript/mastodon/features/compose/components/upload.js index 66c93452c..a1e99dcbb 100644 --- a/app/javascript/mastodon/features/compose/components/upload.js +++ b/app/javascript/mastodon/features/compose/components/upload.js @@ -44,11 +44,13 @@ class Upload extends ImmutablePureComponent { this.props.onSubmit(this.context.router.history); } - handleUndoClick = () => { + handleUndoClick = e => { + e.stopPropagation(); this.props.onUndo(this.props.media.get('id')); } - handleFocalPointClick = () => { + handleFocalPointClick = e => { + e.stopPropagation(); this.props.onOpenFocalPoint(this.props.media.get('id')); } @@ -68,6 +70,10 @@ class Upload extends ImmutablePureComponent { this.setState({ focused: true }); } + handleClick = () => { + this.setState({ focused: true }); + } + handleInputBlur = () => { const { dirtyDescription } = this.state; @@ -88,7 +94,7 @@ class Upload extends ImmutablePureComponent { const y = ((focusY / -2) + .5) * 100; return ( - <div className='compose-form__upload' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> + <div className='compose-form__upload' tabIndex='0' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClick} role='button'> <Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}> {({ scale }) => ( <div className='compose-form__upload-thumbnail' style={{ transform: `scale(${scale})`, backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}> diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.js b/app/javascript/mastodon/features/direct_timeline/components/conversation.js index 7277b7f0f..ffcd6d281 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversation.js +++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.js @@ -56,6 +56,7 @@ export default class Conversation extends ImmutablePureComponent { otherAccounts={accounts} onMoveUp={this.handleHotkeyMoveUp} onMoveDown={this.handleHotkeyMoveDown} + onClick={this.handleClick} /> ); } diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversations_list.js b/app/javascript/mastodon/features/direct_timeline/components/conversations_list.js index 4684548e0..635c03c1d 100644 --- a/app/javascript/mastodon/features/direct_timeline/components/conversations_list.js +++ b/app/javascript/mastodon/features/direct_timeline/components/conversations_list.js @@ -9,14 +9,14 @@ import { debounce } from 'lodash'; export default class ConversationsList extends ImmutablePureComponent { static propTypes = { - conversationIds: ImmutablePropTypes.list.isRequired, + conversations: ImmutablePropTypes.list.isRequired, hasMore: PropTypes.bool, isLoading: PropTypes.bool, onLoadMore: PropTypes.func, shouldUpdateScroll: PropTypes.func, }; - getCurrentIndex = id => this.props.conversationIds.indexOf(id) + getCurrentIndex = id => this.props.conversations.findIndex(x => x.get('id') === id) handleMoveUp = id => { const elementIndex = this.getCurrentIndex(id) - 1; @@ -41,22 +41,22 @@ export default class ConversationsList extends ImmutablePureComponent { } handleLoadOlder = debounce(() => { - const last = this.props.conversationIds.last(); + const last = this.props.conversations.last(); - if (last) { - this.props.onLoadMore(last); + if (last && last.get('last_status')) { + this.props.onLoadMore(last.get('last_status')); } }, 300, { leading: true }) render () { - const { conversationIds, onLoadMore, ...other } = this.props; + const { conversations, onLoadMore, ...other } = this.props; return ( <ScrollableList {...other} onLoadMore={onLoadMore && this.handleLoadOlder} scrollKey='direct' ref={this.setRef}> - {conversationIds.map(item => ( + {conversations.map(item => ( <ConversationContainer - key={item} - conversationId={item} + key={item.get('id')} + conversationId={item.get('id')} onMoveUp={this.handleMoveUp} onMoveDown={this.handleMoveDown} /> diff --git a/app/javascript/mastodon/features/direct_timeline/containers/conversations_list_container.js b/app/javascript/mastodon/features/direct_timeline/containers/conversations_list_container.js index 81ea812ad..57e17d96f 100644 --- a/app/javascript/mastodon/features/direct_timeline/containers/conversations_list_container.js +++ b/app/javascript/mastodon/features/direct_timeline/containers/conversations_list_container.js @@ -3,7 +3,7 @@ import ConversationsList from '../components/conversations_list'; import { expandConversations } from '../../../actions/conversations'; const mapStateToProps = state => ({ - conversationIds: state.getIn(['conversations', 'items']).map(x => x.get('id')), + conversations: state.getIn(['conversations', 'items']), isLoading: state.getIn(['conversations', 'isLoading'], true), hasMore: state.getIn(['conversations', 'hasMore'], false), }); diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index a62974ec0..9cf783c84 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -5,7 +5,6 @@ import { start } from '../mastodon/common'; start(); function main() { - const { length } = require('stringz'); const IntlMessageFormat = require('intl-messageformat').default; const { timeAgoString } = require('../mastodon/components/relative_timestamp'); const { delegate } = require('rails-ujs'); diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index a86e3e632..ccb53a090 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -130,17 +130,6 @@ body.rtl { float: left; } - .activity-stream .detailed-status.light .detailed-status__display-name > div { - float: right; - margin-right: 0; - margin-left: 10px; - } - - .activity-stream .detailed-status.light .detailed-status__meta span > span { - margin-left: 0; - margin-right: 6px; - } - .status__action-bar { &__counter { @@ -174,6 +163,10 @@ body.rtl { margin-right: 0; } + .detailed-status__display-name .display-name { + text-align: right; + } + .detailed-status__display-avatar { margin-right: 0; margin-left: 10px; diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 7e6702a63..ea9017b82 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -81,11 +81,22 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @mentions << Mention.new(account: account, silent: true) # If there is at least one silent mention, then the status can be considered - # as a limited-audience status, and not strictly a direct message + # as a limited-audience status, and not strictly a direct message, but only + # if we considered a direct message in the first place next unless @params[:visibility] == :direct @params[:visibility] = :limited end + + # If the payload was delivered to a specific inbox, the inbox owner must have + # access to it, unless they already have access to it anyway + return if @options[:delivered_to_account_id].nil? || @mentions.any? { |mention| mention.account_id == @options[:delivered_to_account_id] } + + @mentions << Mention.new(account_id: @options[:delivered_to_account_id], silent: true) + + return unless @params[:visibility] == :direct + + @params[:visibility] = :limited end def attach_tags(status) diff --git a/app/models/account_conversation.rb b/app/models/account_conversation.rb index b7447d805..cc6b39279 100644 --- a/app/models/account_conversation.rb +++ b/app/models/account_conversation.rb @@ -58,6 +58,9 @@ class AccountConversation < ApplicationRecord def add_status(recipient, status) conversation = find_or_initialize_by(account: recipient, conversation_id: status.conversation_id, participant_account_ids: participants_from_status(recipient, status)) + + return conversation if conversation.status_ids.include?(status.id) + conversation.status_ids << status.id conversation.unread = status.account_id != recipient.id conversation.save diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 4169c685b..4551aa7e0 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -17,7 +17,8 @@ class FetchLinkCardService < BaseService return if @url.nil? || @status.preview_cards.any? - @url = @url.to_s + @mentions = status.mentions + @url = @url.to_s RedisLock.acquire(lock_options) do |lock| if lock.acquired? @@ -81,9 +82,16 @@ class FetchLinkCardService < BaseService uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) end + def mention_link?(a) + return false if @mentions.nil? + @mentions.any? do |mention| + a['href'] == TagManager.instance.url_for(mention.target) + end + end + def skip_link?(a) # Avoid links for hashtags and mentions (microformats) - a['rel']&.include?('tag') || a['class']&.include?('u-url') + a['rel']&.include?('tag') || a['class']&.include?('u-url') || mention_link?(a) end def attempt_oembed diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index 3453b54c5..9f56249c7 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -25,7 +25,7 @@ class VerifyLinkService < BaseService end def link_back_present? - return false if @body.empty? + return false if @body.blank? links = Nokogiri::HTML(@body).xpath('//a[contains(concat(" ", normalize-space(@rel), " "), " me ")]|//link[contains(concat(" ", normalize-space(@rel), " "), " me ")]') diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 66382db50..0e52702dc 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -14,4 +14,4 @@ = yield -= render template: 'layouts/application', locals: { body_classes: 'admin' } += render template: 'layouts/application' diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index 6b61fa9c9..516851b04 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -6,8 +6,8 @@ .fields-row .fields-row__column.fields-group.fields-row__column-6 - = f.input :display_name, wrapper: :with_label, hint: t('simple_form.hints.defaults.display_name', count: 30 - @account.display_name.size).html_safe - = f.input :note, wrapper: :with_label, hint: t('simple_form.hints.defaults.note', count: 500 - @account.note.size).html_safe + = f.input :display_name, wrapper: :with_label, input_html: { maxlength: 30 }, hint: false + = f.input :note, wrapper: :with_label, input_html: { maxlength: 500 }, hint: false .fields-row .fields-row__column.fields-row__column-6 @@ -36,8 +36,8 @@ = f.simple_fields_for :fields do |fields_f| .row - = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name') - = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value') + = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name'), input_html: { maxlength: 255 } + = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value'), input_html: { maxlength: 255 } .fields-row__column.fields-group.fields-row__column-6 %h6= t('verification.verification') diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index cd0531ba2..e996d5052 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -15,6 +15,7 @@ %span.display-name %bdi %strong.display-name__html.p-name.emojify= display_name(status.account, custom_emojify: true, autoplay: autoplay) + %span.display-name__account = acct(status.account) = fa_icon('lock') if status.account.locked? diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index 0e2e0eddd..a8a3ebf0f 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -5,7 +5,7 @@ class ActivityPub::ProcessingWorker sidekiq_options backtrace: true - def perform(account_id, body) - ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true) + def perform(account_id, body, delivered_to_account_id = nil) + ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id) end end |