Note, if this does now work we may have to simply skip in CI
Concurrent tests depend on timing of background threads and if scheduler
is overwhelmed stuff can take inconsistent amounts of time.
This allows gists to appear in PM inboxes as well, and adds a spec for
gists (didn't have one previously).
The PM and public topic list gist preferences are stored separately, as
there may be cases where you'd want one and not the other.
<img width="2222" height="916" alt="image"
src="https://github.com/user-attachments/assets/f9792e30-ab65-452b-b8e1-7407d9d181e2"
/>
This commit refactors how user status is tracked in the `poster-name`
component. The previous implementation used lifecycle hooks and a custom
refresh method to start and stop tracking the user's status. The new
approach leverages the `helperFn` pattern to directly manage tracking
based on the component's lifecycle and its user argument. This change
improves reliability and code clarity, ensuring user status is tracked
and cleaned up appropriately without manual refresh logic.
# Hide IP Addresses from Moderators When `moderators_view_ips` is
Disabled
## Summary
Feature Request Link -
https://meta.discourse.org/t/option-to-hide-ip-addresses-from-moderators/207715/51
This PR implements a feature to **hide IP addresses from moderators**
when the `moderators_view_ips` site setting is disabled. Previously,
moderators could view IPs in multiple locations across the admin UI.
This update ensures that IP addresses are visible to moderators when the
setting allows it.
## Changes Implemented
### Backend Updates
- **Added `moderators_view_ips` site setting** in `site_settings.yml`
- **Updated `CurrentUserSerializer`** to include `can_see_ip` field
based on the user’s role and site setting.
- **Modified `AdminUserSerializer`** to restrict IP address visibility.
- **Updated `UsersController`** to prevent IP addresses from being
included in API responses.
- **Restricted IPs in `ScreenedIpAddressesController`** by throwing
`Discourse::InvalidAccess` if the user lacks permission.
### Frontend Updates
- **Hid "Screened IPs" tab** in `/admin/logs` when `moderators_view_ips`
is disabled.
- **Blocked direct access to `/admin/logs/screened_ip_addresses`** for
unauthorized users.
- **Updated `user-index.hbs` and `logs.hbs`** to conditionally hide IP
fields.
### UI Screenshots
New option for Admins in the Admin Security settings dashboard:

Moderator's view before:

Moderator's view after:

Moderator's view before:

Moderator's view after:

---------
Co-authored-by: Bennett Dungan <bennettdungan@gmail.com>
Concerns this button feedback
<img width="190" height="152" alt="image"
src="https://github.com/user-attachments/assets/805a9258-2130-4e2e-99d4-50d9638c825b"
/>
This change is pretty straightforward, the desktop css includes all
styling for the `.post-action-feedback-alert`, so that can be simply
moved to common. The mobile alert was removed by
https://github.com/discourse/discourse/pull/31375 (because we open a
link modal instead)... so the mobile styles aren't actually applied
anywhere (no plugins either).
Since we don't have native floatkit/dmenu functionality (yet) to
make the menu stick to the width of the element, this is a
stopgap solution to make sure the menu stays the same width
as the filter input whether resizing the window or hiding/showing
the menu.
Localizes topic titles in these areas
- user notification
- bookmarks
This commit also updates the user notification bookmark list to use fancy
title instead of title, similar to the other user notification tabs.
This PR ports the floatkit-based autocomplete system to chat composer
under a site setting, providing consistent UX across both regular and
chat composers.
### Key Changes
* Adds floatkit_autocomplete_chat_composer setting (defaults to true)
* Adds `fixedTextareaPosition` option and
`createVirtualElementAtTextarea` to DAutocompleteModifier to allow for
positioning of the autocomplete menu relative to the whole textarea
bounds instead of following the cursor - this is better for chat UI &
aligns with current behaviour
* Use DMenu for the filter tips UI
* Move the input, filtering, and DMenu into the same
`FilterNavigationMenu` component to avoid input event listener
shenanigans
* General renaming, refactors, adding comments
* Move searching/suggestion logic for specific types of filter out into
`FilterSuggestions` lib to avoid cluttering the component
This change adds a new `from_described_class` helper to `RSpec::Mocks`, allowing stubs to only be used when called from the described class in a given spec.
The practical application of this helper is to handle flaky specs, where other code can call the mocks before the test target can.
Consolidated all decorator logic into a single `decorate` method,
eliminating the complexity of separate `beforeAdopt` and `afterAdopt`
options. Streamlined related API and component logic for consistency and
maintainability.
This commit ensures that polls including @mentions of users with active user
statuses are rendered correctly without errors. It introduces a document
validation check before rendering components, adds fixtures for polls
with mentions, and provides acceptance tests to verify proper rendering
of polls containing @mentions.
Introduced the `post-meta-data-edits-indicator-label` transformer to
enable customization of post edits indicator labels. Added integration
tests to validate customization and default behavior.
- Add `prevPost` and `nextPost` to post outlet params
- Add `prevPost` to `post-article-class` transformer
- Introduce `in-post-article` plugin outlet for adding extension points
to the post within the `article` itself
- Introduce `post-links` plugin outlet that wraps `PostLinks` component
(I chose to wrap here vs within the component to ensure that we render
the outlet even if there is not post links)
In the glimmer post stream, mutating `post.cooked` will cause ember to
re-render the HTML. That conflicts with d-ai's own morphlex-based diff
streaming.
To avoid this, we can wait until all streaming has finished before
setting the cooked property of the model.
Co-authored-by: Sérgio Saquetim <saquetim@discourse.org>
When on a tag intersection like this: `/tags/intersection/foo/bar`
We have our tag selector:
<img width="946" height="136" alt="image"
src="https://github.com/user-attachments/assets/6f64cec6-c8f0-456e-a139-769ae66584d1"
/>
When you remove all but one tag, we redirect to /tags, which isn't the
best experience. This change will direct users to the single tag page
`/tag/foo` instead.