Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e4291e9
Fix SMTP configuration with `mail` 2.9.0 (#36646)
ClearlyClaire Oct 30, 2025
214d59b
Show error when submitting empty post rather than failing silently (#…
diondiondion Oct 30, 2025
e1b6e28
chore(deps): update dependency libvips to v8.17.3 (#36654)
renovate[bot] Oct 31, 2025
ea710df
chore(deps): update dependency axios to v1.13.1 (#36633)
renovate[bot] Oct 31, 2025
adfabf8
New Crowdin Translations for stable-4.5 (automated) (#36670)
github-actions[bot] Oct 31, 2025
aa579ce
Fix initially selected language in Rules panel, hide selector when no…
diondiondion Oct 31, 2025
af4c372
Bump version to v4.5.0-rc.2
ClearlyClaire Oct 31, 2025
d22d654
Revert "Fix media URL inconsistency when deleting statuses via API (#…
kmycode Nov 1, 2025
34fc61c
Revert "Refactor carousel components (#36425)"
kmycode Nov 1, 2025
769ac0e
Merge remote-tracking branch 'parent/stable-4.5' into kb-draft-21.0-lts
kmycode Nov 1, 2025
a209b8e
chore(deps): update dependency rubyzip to v3.2.2 (#36687)
renovate[bot] Nov 3, 2025
93acfdd
chore(deps): update dependency irb to v1.15.3 (#36682)
renovate[bot] Nov 3, 2025
6d53ca6
Disable paste-link-to-quote flow when composing Private Mentions (#36…
ClearlyClaire Nov 3, 2025
16a54f7
Fix issuance of quote approval for remote private statuses (#36693)
ClearlyClaire Nov 3, 2025
05964f5
Prevent creation of Private Mentions quoting someone who is not menti…
ClearlyClaire Nov 3, 2025
b5a6feb
Move "Privacy and reach" from "Public profile" to top-level navigatio…
ChaelCodes Nov 3, 2025
e62baac
Increase number of quote approval job retries (#36698)
ClearlyClaire Nov 4, 2025
a7ecfc1
fix(deps): update dependency @rails/ujs to v7.1.600 (#36634)
renovate[bot] Nov 4, 2025
1baede0
chore(deps): update dependency brakeman to v7.1.1 (#35434)
renovate[bot] Nov 4, 2025
449eb03
chore(deps): update dependency sidekiq to v8.0.9 (#36699)
renovate[bot] Nov 4, 2025
dd70829
Remove option to disable access to local topic feeds for logged-in us…
ClearlyClaire Nov 4, 2025
a978e37
Fix quote dropdown menu item in detailed status view (#36704)
ClearlyClaire Nov 4, 2025
0b50789
Fix Skeleton placeholders being animated when setting to reduce anima…
ClearlyClaire Nov 4, 2025
5253527
Add CSS Module support (#36637)
ChaosExAnima Oct 30, 2025
5bae08d
Quote Posts: Add notifications for DMs and private posts (#36696)
ChaosExAnima Nov 4, 2025
ba498ae
Change quote action to error instead of insert link in Private Mentio…
ClearlyClaire Nov 4, 2025
cfdd939
Change paste-link-to-quote loading state from generic loading bar to …
ClearlyClaire Nov 4, 2025
e91c764
Bump version to v4.5.0-rc.3
ClearlyClaire Nov 4, 2025
3e6a937
Fix spoiler toggle button being able to submit compose form (#36736)
diondiondion Nov 5, 2025
ef3a95a
Add default visualizer for audio upload without poster (#36734)
ChaosExAnima Nov 5, 2025
d45b4db
Fix: correctly dismisses announcement when viewed (#36750)
ChaosExAnima Nov 6, 2025
048430f
New Crowdin Translations for stable-4.5 (automated) (#36745)
github-actions[bot] Nov 6, 2025
26c7839
Bump version to v4.5.0 (#36732)
ClearlyClaire Nov 6, 2025
24b8b7d
Merge commit '26c78392f88afccebb8a88b68bc9994a9ce12648' into kb-draft…
kmycode Nov 6, 2025
a5e3bf1
Bump version to 21.0-lts
kmycode Nov 6, 2025
ad85f1a
Fix lint
kmycode Nov 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,41 @@

All notable changes to this project will be documented in this file.

## [4.5.0] - UNRELEASED
## [4.5.0] - 2025-11-06

### Added

- **Add support for allowing and authoring quotes** (#35355, #35578, #35614, #35618, #35624, #35626, #35652, #35629, #35665, #35653, #35670, #35677, #35690, #35697, #35689, #35699, #35700, #35701, #35709, #35714, #35713, #35715, #35725, #35749, #35769, #35780, #35762, #35804, #35808, #35805, #35819, #35824, #35828, #35822, #35835, #35865, #35860, #35832, #35891, #35894, #35895, #35820, #35917, #35924, #35925, #35914, #35930, #35941, #35939, #35948, #35955, #35967, #35990, #35991, #35975, #35971, #36002, #35986, #36031, #36034, #36038, #36054, #36052, #36055, #36065, #36068, #36083, #36087, #36080, #36091, #36090, #36118, #36119, #36128, #36094, #36129, #36138, #36132, #36151, #36158, #36171, #36194, #36220, #36169, #36130, #36249, #36153, #36299, #36291, #36301, #36315, #36317, #36364, #36383, #36381, #36459, #36464, #36461, #36516, #36528, #36549, #36550 and #36559 by @ChaosExAnima, @ClearlyClaire, @Lycolia, @diondiondion, and @tribela)\
- **Add support for allowing and authoring quotes** (#35355, #35578, #35614, #35618, #35624, #35626, #35652, #35629, #35665, #35653, #35670, #35677, #35690, #35697, #35689, #35699, #35700, #35701, #35709, #35714, #35713, #35715, #35725, #35749, #35769, #35780, #35762, #35804, #35808, #35805, #35819, #35824, #35828, #35822, #35835, #35865, #35860, #35832, #35891, #35894, #35895, #35820, #35917, #35924, #35925, #35914, #35930, #35941, #35939, #35948, #35955, #35967, #35990, #35991, #35975, #35971, #36002, #35986, #36031, #36034, #36038, #36054, #36052, #36055, #36065, #36068, #36083, #36087, #36080, #36091, #36090, #36118, #36119, #36128, #36094, #36129, #36138, #36132, #36151, #36158, #36171, #36194, #36220, #36169, #36130, #36249, #36153, #36299, #36291, #36301, #36315, #36317, #36364, #36383, #36381, #36459, #36464, #36461, #36516, #36528, #36549, #36550, #36559, #36693, #36704, #36690, #36689, #36696, #36721, #36695 and #36736 by @ChaosExAnima, @ClearlyClaire, @Lycolia, @diondiondion, and @tribela)\
This includes a revamp of the composer interface.\
See https://blog.joinmastodon.org/2025/09/introducing-quote-posts/ for a user-centric overview of the feature, and https://docs.joinmastodon.org/client/quotes/ for API documentation.
- **Add support for fetching and refreshing replies to the web UI** (#35210, #35496, #35575, #35500, #35577, #35602, #35603, #35654, #36141, #36237, #36172, #36256, #36271, #36334, #36382, #36239, #36484, #36481, #36583, #36627 and #36547 by @ClearlyClaire, @diondiondion, @Gargron and @renchap)
- **Add ability to block words in usernames** (#35407, #35655, and #35806 by @ClearlyClaire and @Gargron)
- Add ability to individually disable local or remote feeds for visitors or logged-in users `disabled` value to server setting for live and topic feeds, as well as user permission to bypass that (#36338, #36467, #36497, #36563, #36577, #36585, and #36607 by @ClearlyClaire)\
This splits the `timeline_preview` setting into four more granular settings controlling live feeds and topic (hashtag, trending link) feeds, with 3 values each: `public`, `authenticated`, `disabled`.\
- Add ability to individually disable local or remote feeds for visitors or logged-in users `disabled` value to server setting for live and topic feeds, as well as user permission to bypass that (#36338, #36467, #36497, #36563, #36577, #36585, #36607 and #36703 by @ClearlyClaire)\
This splits the `timeline_preview` setting into four more granular settings controlling live feeds and topic (hashtag, trending link) feeds.\
The setting for local topic feeds has 2 values: `public` and `authenticated`. Every other setting has 3 values: `public`, `authenticated`, `disabled`.\
When `disabled`, users with the “View live and topic feeds” will still be able to view them.
- Add support for displaying of quote posts in Moderator UI (#35964 by @ThisIsMissEm)
- Add support for displaying link previews for Admin UI (#35958 by @ThisIsMissEm)
- Add a new server setting to choose the server landing page (#36588 and #36602 by @ClearlyClaire and @renchap)
- Add support for `Update` activities on converted object types (#36322 by @ClearlyClaire)
- Add support for dynamic viewport height (#36272 by @e1berd)
- Add support for numeric-based URIs for new local accounts (#32724, #36304, #36316, and #36365 by @ClearlyClaire)
- Add default visualizer for audio upload without poster (#36734 by @ChaosExAnima)
- Add Traditional Mongolian to posting languages (#36196 by @shimon1024)
- Add example post with manual quote approval policy to `dev:populate_sample_data` (#36099 by @ClearlyClaire)
- Add server-side support for handling posts with a quote policy allowing followers to quote (#36093 and #36127 by @ClearlyClaire)
- Add schema.org markup to SEO-enabled posts (#36075 by @Gargron)
- Add migration to fill unset default quote policy based on default post privacy (#36041 by @ClearlyClaire)
- Add “Posting defaults” setting page, moving existing settings from “Other” (#35896, #36033, #35966, #35969, and #36084 by @ClearlyClaire and @diondiondion)
- Added emoji from Twemoji v16 (#36501 and #36530 by @ChaosExAnima)
- Add feature to select custom emoji rendering (#35229, #35282, #35253, #35424, #35473, #35483, #35505, #35568, #35605, #35659, #35664, #35739, #35985, #36051, #36071, #36137, #36165, #36248, #36262, #36275, #36293, #36341, #36342, #36366, #36377, #36378, #36385, #36393, #36397, #36403, #36413, #36410, #36454, #36402, #36503, #36502, #36532, #36603, #36409, #36638 and #36750 by @ChaosExAnima, @ClearlyClaire and @braddunbar)\
This also completely reworks the processing and rendering of emojis and server-rendered HTML in statuses and other places.
- Add support for exposing conversation context for new public conversations according to FEP-7888 (#35959 and #36064 by @ClearlyClaire and @jesseplusplus)
- Add digest re-check before removing followers in synchronization mechanism (#34273 by @ClearlyClaire)
- Add “Posting defaults” setting page, moving existing settings from “Other” (#35896, #36033, #35966, #35969, and #36084 by @ClearlyClaire and @diondiondion)
- Add support for displaying Valkey version on admin dashboard (#35785 by @ykzts)
- Add delivery failure tracking and handling to FASP jobs (#35625, #35628, and #35723 by @oneiros)
- Add example of quote post with a preview card to development sample data (#35616 by @ClearlyClaire)
- Add second set of blocked text that applies to accounts regardless of account age for spam-blocking (#35563 by @ClearlyClaire)
- Added emoji from Twemoji v16 (#36501 and #36530 by @ChaosExAnima)
- Add feature to select custom emoji rendering (#35229, #35282, #35253, #35424, #35473, #35483, #35505, #35568, #35605, #35659, #35664, #35739, #35985, #36051, #36071, #36137, #36165, #36248, #36262, #36275, #36293, #36341, #36342, #36366, #36377, #36378, #36385, #36393, #36397, #36403, #36413, #36410, #36454, #36402, #36503, #36502, #36532, #36603, #36409 and #36638 by @ChaosExAnima, @ClearlyClaire and @braddunbar)\
This also completely reworks the processing and rendering of emojis and server-rendered HTML in statuses and other places.

### Changed

Expand All @@ -43,6 +45,9 @@ All notable changes to this project will be documented in this file.
- Change appearance settings to introduce new Advanced settings section (#36496 and #36506 by @diondiondion)
- Change display of blocked and muted quoted users (#36619 by @ClearlyClaire)\
This adds `blocked_account`, `blocked_domain` and `muted_account` values to the `state` attribute of `Quote` and `ShallowQuote` REST API entities.
- Change submitting an empty post to show an error rather than failing silently (#36650 by @diondiondion)
- Change "Privacy and reach" settings from "Public profile" to their own top-level category (#27294 by @ChaelCodes)
- Change number of times quote verification is retried to better deal with temporary failures (#36698 by @ClearlyClaire)
- Change display of content warnings in Admin UI (#35935 by @ThisIsMissEm)
- Change styling of column banners (#36531 by @ClearlyClaire)
- Change recommended Node version to 24 (LTS) (#36539 by @renchap)
Expand Down Expand Up @@ -70,9 +75,11 @@ All notable changes to this project will be documented in this file.
- Fix relationship not being fetched to evaluate whether to show a quote post (#36517 by @ClearlyClaire)
- Fix rendering of poll options in status history modal (#35633 by @ThisIsMissEm)
- Fix “mute” button being displayed to unauthenticated visitors in hashtag dropdown (#36353 by @mkljczk)
- Fix initially selected language in Rules panel, hide selector when no alternative translations exist (#36672 by @diondiondion)
- Fix URL comparison for mentions in case of empty path (#36613 and #36626 by @ClearlyClaire)
- Fix hashtags not being picked up when full-width hash sign is used (#36103 and #36625 by @ClearlyClaire and @Gargron)
- Fix layout of severed relationships when purged events are listed (#36593 by @mejofi)
- Fix Skeleton placeholders being animated when setting to reduce animations is enabled (#36716 by @ClearlyClaire)
- Fix vacuum tasks being interrupted by a single batch failure (#36606 by @Gargron)
- Fix handling of unreachable network error for search services (#36587 by @mjankowski)
- Fix bookmarks export when a bookmarked status is soft-deleted (#36576 by @ClearlyClaire)
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ FROM build AS libvips

# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
ARG VIPS_VERSION=8.17.2
ARG VIPS_VERSION=8.17.3
# libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"]
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download

Expand Down
14 changes: 7 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ GEM
blurhash (0.1.8)
bootsnap (1.18.6)
msgpack (~> 1.2)
brakeman (7.0.2)
brakeman (7.1.1)
racc
browser (6.2.0)
builder (3.3.0)
Expand Down Expand Up @@ -224,7 +224,7 @@ GEM
mail (~> 2.7)
email_validator (2.2.4)
activemodel
erb (5.1.1)
erb (5.1.3)
erubi (1.13.1)
et-orbi (1.4.0)
tzinfo
Expand Down Expand Up @@ -337,7 +337,7 @@ GEM
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.8.1)
irb (1.15.2)
irb (1.15.3)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
Expand Down Expand Up @@ -621,7 +621,7 @@ GEM
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
rack (3.2.3)
rack (3.2.4)
rack-attack (6.8.0)
rack (>= 1.0, < 4)
rack-cors (3.0.0)
Expand Down Expand Up @@ -691,7 +691,7 @@ GEM
readline (~> 0.0)
rdf-normalize (0.7.0)
rdf (~> 3.3)
rdoc (6.15.0)
rdoc (6.15.1)
erb
psych (>= 4.0.0)
tsort
Expand Down Expand Up @@ -791,7 +791,7 @@ GEM
ruby-vips (2.2.5)
ffi (~> 1.12)
logger
rubyzip (3.2.1)
rubyzip (3.2.2)
rufus-scheduler (3.9.2)
fugit (~> 1.1, >= 1.11.1)
safety_net_attestation (0.5.0)
Expand All @@ -805,7 +805,7 @@ GEM
securerandom (0.4.1)
shoulda-matchers (6.5.0)
activesupport (>= 5.2.0)
sidekiq (8.0.8)
sidekiq (8.0.9)
connection_pool (>= 2.5.0)
json (>= 2.9.0)
logger (>= 1.6.2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ActivityPub::QuoteAuthorizationsController < ActivityPub::BaseController
before_action :set_quote_authorization

def show
expires_in 30.seconds, public: true if @quote.status.distributable? && public_fetch_mode?
expires_in 30.seconds, public: true if @quote.quoted_status.distributable? && public_fetch_mode?
render json: @quote, serializer: ActivityPub::QuoteAuthorizationSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
end

Expand All @@ -23,7 +23,7 @@ def set_quote_authorization
@quote = Quote.accepted.where(quoted_account: @account).find(params[:id])
return not_found unless @quote.status.present? && @quote.quoted_status.present?

authorize @quote.status, :show?
authorize @quote.quoted_status, :show?
rescue Mastodon::NotPermittedError
not_found
end
Expand Down
3 changes: 1 addition & 2 deletions app/controllers/api/v1/statuses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,10 @@ def destroy
@status = Status.where(account: current_account).find(params[:id])
authorize @status, :destroy?

json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true

@status.discard_with_reblogs
StatusPin.find_by(status: @status)&.destroy
@status.account.statuses_count = @status.account.statuses_count - 1
json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true

RemovalWorker.perform_async(@status.id, { 'redraft' => !truthy_param?(:delete_media) })

Expand Down
44 changes: 11 additions & 33 deletions app/javascript/mastodon/actions/compose.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { throttle } from 'lodash';

import api from 'mastodon/api';
import { browserHistory } from 'mastodon/components/router';
import { countableText } from 'mastodon/features/compose/util/counter';
import { search as emojiSearch } from 'mastodon/features/emoji/emoji_mart_search_light';
import { tagHistory } from 'mastodon/settings';

Expand Down Expand Up @@ -57,9 +58,6 @@ export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
export const COMPOSE_MARKDOWN_CHANGE = 'COMPOSE_MARKDOWN_CHANGE';
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
export const COMPOSE_SEARCHABILITY_CHANGE= 'COMPOSE_SEARCHABILITY_CHANGE';
export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE';
export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';

Expand All @@ -79,8 +77,6 @@ export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE';
export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE';
export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE';

export const COMPOSE_CIRCLE_CHANGE = 'COMPOSE_CIRCLE_CHANGE';

export const INIT_MEDIA_EDIT_MODAL = 'INIT_MEDIA_EDIT_MODAL';

export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = 'COMPOSE_CHANGE_MEDIA_DESCRIPTION';
Expand All @@ -97,6 +93,7 @@ const messages = defineMessages({
open: { id: 'compose.published.open', defaultMessage: 'Open' },
published: { id: 'compose.published.body', defaultMessage: 'Post published.' },
saved: { id: 'compose.saved.body', defaultMessage: 'Post saved.' },
blankPostError: { id: 'compose.error.blank_post', defaultMessage: 'Post can\'t be blank.' },
});

export const ensureComposeIsVisible = (getState) => {
Expand Down Expand Up @@ -208,7 +205,15 @@ export function submitCompose(successCallback) {
const hasQuote = !!getState().getIn(['compose', 'quoted_status_id']);
const spoiler_text = getState().getIn(['compose', 'spoiler']) ? getState().getIn(['compose', 'spoiler_text'], '') : '';

if (!(status?.length || media.size !== 0 || (hasQuote && spoiler_text?.length))) {
const fulltext = `${spoiler_text ?? ''}${countableText(status ?? '')}`;
const hasText = fulltext.trim().length > 0;

if (!(hasText || media.size !== 0 || (hasQuote && spoiler_text?.length))) {
dispatch(showAlert({
message: messages.blankPostError,
}));
dispatch(focusCompose());

return;
}

Expand Down Expand Up @@ -811,26 +816,6 @@ export function changeComposeSpoilerText(text) {
};
}

export function changeComposeMarkdown() {
return {
type: COMPOSE_MARKDOWN_CHANGE,
};
}

export function changeComposeVisibility(value) {
return {
type: COMPOSE_VISIBILITY_CHANGE,
value,
};
}

export function changeComposeSearchability(value) {
return {
type: COMPOSE_SEARCHABILITY_CHANGE,
value,
};
}

export function insertEmojiCompose(position, emoji, needsSpace) {
return {
type: COMPOSE_EMOJI_INSERT,
Expand Down Expand Up @@ -924,10 +909,3 @@ export const changeMediaOrder = (a, b) => ({
a,
b,
});

export function changeCircle(circleId) {
return {
type: COMPOSE_CIRCLE_CHANGE,
circleId,
};
}
Loading