We believe the rich editor is a great experience for the
vast majority of sites and users, so we are enabling it
for all sites and all users by default.
This commit does the following:
* Hides the rich_editor site setting and sets it to true by default.
It can still be overridden by sites that want to disable it
completely.
* Sets `rich_editor` to true for all sites to enable the rich editor
everywhere.
* Adds a new `default_composition_mode` site setting and corresponding
user option that defaults to Rich for all users. The other option is
Markdown.
* Changes the rich editor toggle in the composer to use the new
database-backed user option (`composition_mode`) instead of a local
storage key/value store. This makes the preference persistent
across devices.
Existing key/value store settings for the markdown toggle are
kept, the preference will be saved to the user option automatically.
When enabled this will convert uploaded videos to a standard format that should
be playable on all devices and browsers.
The goal of this feature is to prevent codec playback issues that
sometimes can occur with video uploads.
It uses an adapter pattern, so that other services for video conversion
could be easily added in the future.
Previously, all script tags in a theme field would be combined into a
single `.js` bundle along with the `text/discourse-plugin` modules. This
led to some unexpected run order, and also makes it hard to implement
the `type=module` change being developed in #33103.
This commit refactors things so that each raw script gets extracted into
its own `.js` bundle, which is then placed in exactly the same place in
the HTML.
This commit introduces the concept of themeable site settings,
which is a new tool for theme authors that lives alongside theme
modifiers and theme settings. Here is a quick summary:
* Theme settings - These are custom settings used to control UI and functionality within your theme or component and provide configuration options. These cannot change core Discourse functionality.
* Theme modifiers - Allows a theme or a component to modify selected server-side functionality of core Discourse as an alternative to building a plugin.
* Themeable site settings (new) - Allows a theme (not components) to override a small subset of core site settings, which generally control parts of the UI and other minor functionality. This allows themes to have a greater control over the full site experience.
Themeable site settings will be shown for all themes, whether the theme
changes
the value or not, and have a similar UI to custom theme settings.
We are also introducing a new page at
`/admin/config/theme-site-settings` that
allows admins to see all possible themeable site settings, and which
themes
are changing the value from the default.
### Configuration
Theme authors can configure initial values themeable site settings using
a section in the `about.json` file like so:
```json
"theme_site_settings": {
"search_experience": "search_field"
}
```
These values will not change when the theme updates, because we cannot
know if admins have manually changed them.
### Limitations
Themeable site settings are only really intended to control elements of
the UI, and when retrieving their value we require a theme ID, so these
limitations apply:
- Themeable site settings cannot be used in Sidekiq jobs
- Themeable site settings cannot be used in markdown rules
- Themeable site settings will be cached separately to client site
settings using theme ID as a key
- Themeable site settings will override keys on the `siteSettings`
service on the client using the application preloader
- `SiteSetting.client_settings_json` will not include themeable site
settings, instead you can call `SiteSetting.theme_site_settings_json`
with a theme ID
### Initial settings
There are only two site settings that will be themeable to begin with:
* `enable_welcome_banner`
* `search_experience`
And our new Horizon theme will take advantage of both. Over time, more
settings that control elements of the UI will be exposed this way.
- Add indexes in some places where we were seeing bottlenecks
- Remove redundant ILIKE query
---------
Co-authored-by: Gerhard Schlager <gerhard.schlager@discourse.org>
We want to add the ability to enable/disable users selecting Gravatar for their avatar.
This change adds a site setting to enable/disable the option (default to enabled.) This will prevent users from configuring Gravatars from that point on. It does not affect already configured avatars.
We're also taking this chance to hide some of the advanced settings from the UI.
* Fixes capitalisation for *My messages*, *My posts*, and *My drafts*
sidebar links.
* Hides *My messages* link for anonymous users.
* Hides *My messages* link for users who can’t access messages.
* Adds active state for *My messages* link (applies to all child routes:
personal, group, and tags).
Post edits need to inform the backend if the locale is changed and is
sometimes set as `""`. This PR prevents the locale from being set to
`""` in the database, and includes a migration to purge the empty
strings.
We want to deprecate the enabled/disabled toggle for this setting and rely entirely on the presence of a URL.
This change:
- Deprecates and hides the enabled/disabled setting.
- Updates all code paths and tests that rely on the old setting.
- Adds a migration that clears the URL if the enabled/disabled setting is set to false.
`SiteSerializer#post_action_types` and `SiteSerializer#topic_flag_types`
both call the `Flag.used_flag_ids` method which executes queries that
becomes very slow on sites with alot of records in either the
`post_actions` or `reviewable_scores` table.
On the `post_actions` table, we execute `SELECT DISTINCT
post_action_type_id FROM post_actions`. On the `reviewable_scores`
table, we execute `SELECT DISTINCT reviewable_scope_type FROM
reviewable_scopes`. The problem with both queries is that it requires
the PG planner to scan through every single row in those tables.
For our use case, all we actually need is to check if a flag is being
referenced by a record in either the `post_actions` or
`reviewable_scores` tables. This commit updates the `Flag.used_flag_ids`
to accept a `flag_ids`
argument and use the argument to check whether the flag ids are
referenced in the `post_action_type_id` or `reviewable_scope_type`
foreign keys.
This PR takes the localization features out of "experimental" to prep
for the announcement
- rename settings and gives them its own area
- `experimental_content_localization` to `content_localization_enabled`
- `experimental_content_localization_allowed_groups` to
`content_localization_allowed_groups`
- `experimental_content_localization_supported_locales` to
`content_localization_supported_locales`
- `experimental_anon_language_switcher` to
`content_localization_anon_language_switcher`
- migration
- related to https://github.com/discourse/discourse-ai/pull/1439
| screenshot 📸 |
|---|
| <img width="964" alt="Screenshot 2025-06-17 at 5 06 32 PM"
src="https://github.com/user-attachments/assets/9a8b2c38-c846-4fc9-8ddd-815c45cc3d0e"
/> |
Introduction of system themes. System themes are local themes which:
- Cannot be deleted;
- Cannot have “custom code” added, components only;
- Cannot have uploads;
- Cannot edit color palettes;
- Are updated on deploy, like core plugins.
This PR added the Foundation system theme, which is an empty theme like
Default. The Foundation theme will be added in the next PR.
In a development environment, when system theme files are
changed/added/deleted, the theme is reuploaded and the page is reloaded
to make it a good experience for the engineer working on improvements.
System themes are not visible until
`SiteSetting.experimental_system_theme` is enabled.
In #33012 we phased out the site settings for:
- disable_avatar_education_message
- sequential_replies_threshold
- warn_reviving_old_topic_age
This change is a follow up migration to delete the site settings from
the database.
We phased out the site setting for `max_similar_results` in #32934 -
this change is a follow up migration to delete the site setting from the
database.
As part of the review queue refresh, we'll be adding the ability for moderators to make notes on individual reviewable items. As a first step, this change adds the new model and associated backend code.
Application code should not be used in migrations since we want
migrations to be idempotent. Since these migrations were added 4 years
ago, the application code is safe to be removed.
This will allow me to make changes to the
`FileStore::S3Store#update_upload_ACL` without having to worry about
these migrations.
Previously we had omitted determining the locale of categories, as
unlike posts, categories are usually single words and are usually only
translated once.
Since there is no locale, a category called "Staff" would also have an
English translation. With LLMs that perform poorly, we see that
translating "Staff" to English may result in something entirely
different (like "Personnelle" or "Personal").
Thus adding locale support to categories can mitigate this issue due to
the uncertainty.
We're moving the add-groups-to-about theme component into core. We have already added the logic and switchover in #32659.
This PR adds a data migration that maps the theme settings to the relevant site settings, then enables the core implementation.
Currently, topic excerpts are not localized.
This commit adds the excerpt column into topic_localization and displays the
localized excerpt if present.
**Description**
As part of a customer request, we have added the option to search groups
by ID when doing API calls. However, in doing so we have decided to
correct the confusion around the group's routes. Previously the route
would look like `g/:id` while taking the `name` of the group as the
param. For example, when getting a group the route would be like this:
```
GET /g/admins
```
This would make the code in the controller seem as if it was handling
the group IDs instead of names. With these changes, this should be
addressed.
Similar to https://github.com/discourse/discourse/pull/32526.
Reviewer note: There had been some deliberation if we should just take
the `topic.first_post.locale` instead of having a `topic.locale`.
Ultimately, titles may be of a different language of the post itself,
and secondarily in some cases it could be faster without having to load
the first_post at all.
Previous to this change when we used to specify format it could get an
image
in the incorrect format.
Also... allows image magick to decode svg
---
There remains a bug where the crop / resize information is not stored in
optimized images
this means that sometimes when asking for a cropped image you may get a
resized one.
We are making this the only option for our login/signup
pages on April 29th, 2025, per
https://meta.discourse.org/t/introducing-our-new-fullscreen-signup-and-login-pages/340401.
This commit removes the `full_page_login` setting and any logic
around it, as well as deleting the old login and signup modals,
and removing leftover problem checks and settings from the database.
This commit adds
- `topic_localization` containing its topic, a locale, title, and
fancy_title
- `post_localization` containing its post, a locale, raw, cooked, the
associated post's version
- and also APIs to add them
Reviewer note: We may ask ourselves "why create separate models instead
of one that is generic?" but the different localizable models may be
vastly different. For example in posts we only have raw that we need to
translate, and topics we have only title, but for categories we have
name and description. Then, we may ask ourselves "why not create a
polymorphic one that takes in model and column name?" and then we end up
with the same thing as what we have currently which is custom fields
(which is a mess in itself). Also, when replacing the untranslated
content to the translated one, we may find it easier to just `join` +
`coalesce` on the dedicated table - it would be a much simpler query
than polymorphism.
When a reviewable is auto-claimed, this actually claims all reviewables in a given topic, rather than just the specific post that the reviewable is about. Particularly for sites that require all posts to be reviewed, this can quickly result in many reviewables being unintentionally claimed by the first moderator to review a post in a given topic.
Unfortunately, due to `ReviewableClaimedTopic` being originally built to claim by topic, we can't fully fix this without significant re-architecture. In the mean time, however, we can ensure that reviewables are unclaimed once they've been handled, so that the next reviewable from a topic won't be automatically claimed.
When multiple admins are working in the review queue, it's quite easy for two people to try and handle the same reviewable at the same time. This change addresses the two major situations where this can occur.
The `ReviewableClaimedTopic` model has been extended to allow the system to mark a reviewable as claimed as soon as the first moderator starts handling the reviewable, even when the `reviewable_claiming` setting is disabled. This ensures that reviewable actions with client-site activity (for example, `agree_and_suspend`) will lock the reviewable before another moderator starts working on it.
When someone handles handles a reviewable, we now use `MessageBus` to inform other moderators that it's changed. If any of the other moderator have that reviewable open (either individually, or on the list screen), it will automatically refresh that data.
This PR renames a couple of settings related to anonymous mode:
1. `allow_anonymous_posting` → `allow_anonymous_mode`. This setting is
used as a switch for the entire anonymous mode feature, so it makes
sense to give it a generic name that better reflects what the setting
does.
2. `allow_anonymous_likes` → `allow_likes_in_anonymous_mode`. The new
name is clearer and will match a new setting that we'll add to allow
anonymous users to post in chat.
Internal topic: t/148088.
This is a stripped-back version of the Search Banner
component https://meta.discourse.org/t/search-banner/122939,
which will be renamed to Advanced Search Banner,
see https://github.com/discourse/discourse-search-banner/pull/84.
This welcome banner interacts with the header search.
When `search_experience` is set to `search_field`, we only
show the header search after the welcome banner scrolls
out of view, and vice-versa.
Only new sites will get this feature turned on by default,
existing sites have a migration to disable it.
---------
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Co-authored-by: Jordan Vidrine <jordan@jordanvidrine.com>