diff --git a/.rubocop/naming.yml b/.rubocop/naming.yml index da6ad4ac57..37d3a17efd 100644 --- a/.rubocop/naming.yml +++ b/.rubocop/naming.yml @@ -1,3 +1,6 @@ --- Naming/BlockForwarding: EnforcedStyle: explicit + +Naming/PredicateMethod: + Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f2078bfc07..06db0a4fc6 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.75.8. +# using RuboCop version 1.76.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -33,7 +33,6 @@ Style/FetchEnvVar: Exclude: - 'config/initializers/2_limited_federation_mode.rb' - 'config/initializers/paperclip.rb' - - 'lib/tasks/repo.rake' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. diff --git a/Gemfile b/Gemfile index 58b152579b..76e4340c86 100644 --- a/Gemfile +++ b/Gemfile @@ -110,7 +110,7 @@ group :opentelemetry do gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.22.0', require: false gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.22.0', require: false gem 'opentelemetry-instrumentation-excon', '~> 0.23.0', require: false - gem 'opentelemetry-instrumentation-faraday', '~> 0.26.0', require: false + gem 'opentelemetry-instrumentation-faraday', '~> 0.27.0', require: false gem 'opentelemetry-instrumentation-http', '~> 0.24.0', require: false gem 'opentelemetry-instrumentation-http_client', '~> 0.23.0', require: false gem 'opentelemetry-instrumentation-net_http', '~> 0.23.0', require: false diff --git a/Gemfile.lock b/Gemfile.lock index ab93f78ebd..e8f8bf0513 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,7 +90,7 @@ GEM public_suffix (>= 2.0.2, < 7.0) aes_key_wrap (1.1.0) android_key_attestation (0.3.0) - annotaterb (4.14.0) + annotaterb (4.15.0) ast (2.4.3) attr_required (1.0.2) aws-eventstream (1.3.2) @@ -544,7 +544,7 @@ GEM opentelemetry-instrumentation-excon (0.23.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.23.0) - opentelemetry-instrumentation-faraday (0.26.0) + opentelemetry-instrumentation-faraday (0.27.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.23.0) opentelemetry-instrumentation-http (0.24.0) @@ -751,7 +751,7 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 9) rspec-support (3.13.3) - rubocop (1.75.8) + rubocop (1.76.0) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -759,10 +759,10 @@ GEM parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.44.0, < 2.0) + rubocop-ast (>= 1.45.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.44.1) + rubocop-ast (1.45.0) parser (>= 3.3.7.2) prism (~> 1.4) rubocop-capybara (2.22.1) @@ -1026,7 +1026,7 @@ DEPENDENCIES opentelemetry-instrumentation-active_model_serializers (~> 0.22.0) opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0) opentelemetry-instrumentation-excon (~> 0.23.0) - opentelemetry-instrumentation-faraday (~> 0.26.0) + opentelemetry-instrumentation-faraday (~> 0.27.0) opentelemetry-instrumentation-http (~> 0.24.0) opentelemetry-instrumentation-http_client (~> 0.23.0) opentelemetry-instrumentation-net_http (~> 0.23.0) diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 973724cf7c..3b42dc48ba 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -138,7 +138,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController set_locale { render :rules } end - def is_flashing_format? # rubocop:disable Naming/PredicateName + def is_flashing_format? # rubocop:disable Naming/PredicatePrefix if params[:action] == 'create' false # Disable flash messages for sign-up else diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index d821381ce0..b4157a502e 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -2,6 +2,7 @@ import { browserHistory } from 'mastodon/components/router'; import { debounceWithDispatchAndArguments } from 'mastodon/utils/debounce'; import api, { getLinks } from '../api'; +import { me } from '../initial_state'; import { followAccountSuccess, unfollowAccountSuccess, @@ -12,6 +13,7 @@ import { blockAccountSuccess, unblockAccountSuccess, pinAccountSuccess, unpinAccountSuccess, fetchRelationshipsSuccess, + fetchEndorsedAccounts, } from './accounts_typed'; import { importFetchedAccount, importFetchedAccounts } from './importer'; @@ -634,6 +636,7 @@ export function pinAccount(id) { api().post(`/api/v1/accounts/${id}/pin`).then(response => { dispatch(pinAccountSuccess({ relationship: response.data })); + dispatch(fetchEndorsedAccounts({ accountId: me })); }).catch(error => { dispatch(pinAccountFail(error)); }); @@ -646,6 +649,7 @@ export function unpinAccount(id) { api().post(`/api/v1/accounts/${id}/unpin`).then(response => { dispatch(unpinAccountSuccess({ relationship: response.data })); + dispatch(fetchEndorsedAccounts({ accountId: me })); }).catch(error => { dispatch(unpinAccountFail(error)); }); diff --git a/app/javascript/mastodon/components/account.tsx b/app/javascript/mastodon/components/account.tsx index cad7575f25..375f759f42 100644 --- a/app/javascript/mastodon/components/account.tsx +++ b/app/javascript/mastodon/components/account.tsx @@ -12,6 +12,8 @@ import { muteAccount, unmuteAccount, followAccountSuccess, + unpinAccount, + pinAccount, } from 'mastodon/actions/accounts'; import { showAlertForError } from 'mastodon/actions/alerts'; import { openModal } from 'mastodon/actions/modal'; @@ -62,14 +64,23 @@ const messages = defineMessages({ }, }); -export const Account: React.FC<{ +interface AccountProps { size?: number; id: string; hidden?: boolean; minimal?: boolean; defaultAction?: 'block' | 'mute'; withBio?: boolean; -}> = ({ id, size = 46, hidden, minimal, defaultAction, withBio }) => { +} + +export const Account: React.FC = ({ + id, + size = 46, + hidden, + minimal, + defaultAction, + withBio, +}) => { const intl = useIntl(); const { signedIn } = useIdentity(); const account = useAppSelector((state) => state.accounts.get(id)); @@ -119,8 +130,6 @@ export const Account: React.FC<{ }, ]; } else if (defaultAction !== 'block') { - arr = []; - if (isRemote && accountUrl) { arr.push({ text: intl.formatMessage(messages.openOriginalPage), @@ -173,6 +182,25 @@ export const Account: React.FC<{ text: intl.formatMessage(messages.addToLists), action: handleAddToLists, }); + + if (id !== me && (relationship?.following || relationship?.requested)) { + const handleEndorseToggle = () => { + if (relationship.endorsed) { + dispatch(unpinAccount(id)); + } else { + dispatch(pinAccount(id)); + } + }; + arr.push({ + text: intl.formatMessage( + // Defined in features/account_timeline/components/account_header.tsx + relationship.endorsed + ? { id: 'account.unendorse' } + : { id: 'account.endorse' }, + ), + action: handleEndorseToggle, + }); + } } } diff --git a/app/javascript/mastodon/features/account/components/account_note.jsx b/app/javascript/mastodon/features/account/components/account_note.jsx index df7312eafc..855a1f4fc8 100644 --- a/app/javascript/mastodon/features/account/components/account_note.jsx +++ b/app/javascript/mastodon/features/account/components/account_note.jsx @@ -8,6 +8,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import Textarea from 'react-textarea-autosize'; +import { LoadingIndicator } from '@/mastodon/components/loading_indicator'; + const messages = defineMessages({ placeholder: { id: 'account_note.placeholder', defaultMessage: 'Click to add a note' }, }); @@ -153,17 +155,23 @@ class AccountNote extends ImmutablePureComponent { -