From 30d4303345a6a24c0e85579f9e9cefbc38109c50 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 25 Aug 2025 14:25:35 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Fix=20Edit=20as=20well=20as=20=E2=80=9CDele?= =?UTF-8?q?te=20&=20Redraft=E2=80=9D=20on=20a=20poll=20not=20inserting=20e?= =?UTF-8?q?mpty=20option=20(#35892)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/mastodon/actions/compose.js | 15 ++++++++++----- app/javascript/mastodon/actions/statuses.js | 13 +++++++++---- app/javascript/mastodon/reducers/compose.js | 14 ++++++++++++-- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 6abfd6157..6d05ef654 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -94,11 +94,16 @@ export const ensureComposeIsVisible = (getState, routerHistory) => { }; export function setComposeToStatus(status, text, spoiler_text) { - return{ - type: COMPOSE_SET_STATUS, - status, - text, - spoiler_text, + return (dispatch, getState) => { + const maxOptions = getState().server.getIn(['server', 'configuration', 'polls', 'max_options']); + + dispatch({ + type: COMPOSE_SET_STATUS, + status, + text, + spoiler_text, + maxOptions, + }); }; } diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 3aed80735..5809f1497 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -86,10 +86,15 @@ export function fetchStatusFail(id, error, skipLoading) { } export function redraft(status, raw_text) { - return { - type: REDRAFT, - status, - raw_text, + return (dispatch, getState) => { + const maxOptions = getState().server.getIn(['server', 'configuration', 'polls', 'max_options']); + + dispatch({ + type: REDRAFT, + status, + raw_text, + maxOptions, + }); }; } diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index ad367ea7b..b5fc29af9 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -492,8 +492,13 @@ export default function compose(state = initialState, action) { } if (action.status.get('poll')) { + let options = ImmutableList(action.status.get('poll').options.map(x => x.title)); + if (options.size < action.maxOptions) { + options = options.push(''); + } + map.set('poll', ImmutableMap({ - options: action.status.getIn(['poll', 'options']).map(x => x.get('title')), + options: options, multiple: action.status.getIn(['poll', 'multiple']), expires_in: expiresInFromExpiresAt(action.status.getIn(['poll', 'expires_at'])), })); @@ -521,8 +526,13 @@ export default function compose(state = initialState, action) { } if (action.status.get('poll')) { + let options = ImmutableList(action.status.get('poll').options.map(x => x.title)); + if (options.size < action.maxOptions) { + options = options.push(''); + } + map.set('poll', ImmutableMap({ - options: action.status.getIn(['poll', 'options']).map(x => x.get('title')), + options: options, multiple: action.status.getIn(['poll', 'multiple']), expires_in: expiresInFromExpiresAt(action.status.getIn(['poll', 'expires_at'])), })); From 91de5032852f57347d72cb490a97c2094697b520 Mon Sep 17 00:00:00 2001 From: fiona Date: Tue, 2 Sep 2025 12:25:55 +0000 Subject: [PATCH 2/3] Fix handling of edited status with new media and no text (#35970) --- .../process_status_update_service.rb | 2 ++ .../process_status_update_service_spec.rb | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 91e297649..75b9d0f58 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -102,6 +102,8 @@ class ActivityPub::ProcessStatusUpdateService < BaseService @status.ordered_media_attachment_ids = @next_media_attachments.map(&:id) @media_attachments_changed = true if @status.ordered_media_attachment_ids != previous_media_attachments_ids + + @status.media_attachments.reload if @media_attachments_changed end def download_media_files! diff --git a/spec/services/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index 4048f37f2..a9d2db16d 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -368,6 +368,42 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService, type: :service do end end + context 'when originally without media attachments and text is removed' do + before do + stub_request(:get, 'https://example.com/foo.png').to_return(body: attachment_fixture('emojo.png')) + end + + let(:payload) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: 'Note', + content: '', + updated: '2021-09-08T22:39:25Z', + attachment: [ + { type: 'Image', mediaType: 'image/png', url: 'https://example.com/foo.png' }, + ], + } + end + + it 'updates media attachments, fetches attachment, records media and text removal in edit' do + subject.call(status, json, json) + + expect(status.reload.ordered_media_attachments.first) + .to be_present + .and(have_attributes(remote_url: 'https://example.com/foo.png')) + + expect(a_request(:get, 'https://example.com/foo.png')) + .to have_been_made + + expect(status.edits.reload.last.ordered_media_attachment_ids) + .to_not be_empty + + expect(status.edits.reload.last.text) + .to_not be_present + end + end + context 'when originally with media attachments' do let(:media_attachments) { [Fabricate(:media_attachment, remote_url: 'https://example.com/foo.png'), Fabricate(:media_attachment, remote_url: 'https://example.com/unused.png')] } From 8ddb8382f40f5491aff5169a35c0c908af859918 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 15 Sep 2025 15:10:23 +0200 Subject: [PATCH 3/3] Bump version to v4.2.25 --- CHANGELOG.md | 6 ++++++ docker-compose.yml | 6 +++--- lib/mastodon/version.rb | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c79103a32..82ed72fdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [4.2.25] - 2025-09-16 + +### Fixed + +- Fix processing of remote edited statuses with new media and no text (#35970 by @unfokus) + ## [4.2.24] - 2025-08-05 ### Security diff --git a/docker-compose.yml b/docker-compose.yml index 4b1fe34b6..81c3477c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,7 @@ services: web: build: . - image: ghcr.io/mastodon/mastodon:v4.2.24 + image: ghcr.io/mastodon/mastodon:v4.2.25 restart: always env_file: .env.production command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" @@ -77,7 +77,7 @@ services: streaming: build: . - image: ghcr.io/mastodon/mastodon:v4.2.24 + image: ghcr.io/mastodon/mastodon:v4.2.25 restart: always env_file: .env.production command: node ./streaming @@ -95,7 +95,7 @@ services: sidekiq: build: . - image: ghcr.io/mastodon/mastodon:v4.2.24 + image: ghcr.io/mastodon/mastodon:v4.2.25 restart: always env_file: .env.production command: bundle exec sidekiq diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index 731bb5535..50fc54afa 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ module Mastodon end def patch - 24 + 25 end def default_prerelease