Replaces Ember's deprecated `filterBy` with the native JavaScript method
`filter`. This aligns with modern JavaScript practices, improves code
clarity, and prepares for future deprecations.
Changes involve various components, controllers, and models across the
codebase.
Replaces usages of `mapBy` across the codebase with JavaScript's native
`.map`. This resolves deprecation warnings related to Ember's array
extensions and ensures compatibility with future Ember versions.
---------
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
Refactor all instances of `reject` and `rejectBy` across the codebase to
use the native `filter` method paired with appropriate logic. Updates
include changes in models, components, and services.
This ensures compatibility with modern JavaScript standards and reduces
reliance on deprecated array extension methods.
For historical reasons, Discourse has a customized Ember resolver. This
had a much more fuzzy implementation of 'normalize' and 'findTemplate'
functions. This leniency meant that our file naming hasn't always
matched Ember conventions.
Standardizing our naming will make things easier to understand for
developers, and will make adoption of newer ecosystem tooling easier
(e.g. route-based bundle splitting in Embroider/vite)
This commit adds deprecations to the resolver when this leniency is
used, and uses a fully bespoke codemod to rename all of the affected
routes/controllers/templates in the Discourse core repository.
Backwards-compatibility is maintained for anyone looking up the old
names in the resolver.
We've had the new floatkit-based autocomplete live in various parts of
Discourse for about a month now, and it's stable enough for us to remove
the site setting letting admins revert to the jquery-based autocomplete
library which is now deprecated.
Prior to this commit we would show the collapsible DMs section which has
a [+] on hover to start a DM but it was not very nice visually and also
had low affordance.
The new empty DMs state:
<img width="275" height="77" alt="Screenshot 2025-09-16 at 09 07 57"
src="https://github.com/user-attachments/assets/99976dfd-44ec-40f8-a6d1-c0d15f550524"
/>
Prior to this fix we would fetch thread data even if it was present in
the bus data, that's already unnecessary work in a normal situation but
that's even worse when a user is coming back to their computer as we
will have to catchup multiple new threads at once.
Also ensures we correctly await fetching data from server when
necessary.
No test as there are not behavior change.
Prior to this change we would have different context for quick reactions
and for channels this commit just move everything into one context which
is less surprising.
Uses the timestamp at the moment where the user hits send for the
created_at value of the chat message. This should ensure very consistent
ordering.
The implementation is simple:
- collects the timestamp and send it in the request (client_created_at)
- if client_created_at is present and valid, set it as created_at when
creating the message
I suspect that we could end up in a situation where a message is routed
to a slower worker and even if sent before an other message could end up
being persisted before the first message which would cause ordering issues.
When a user card is rendered, there are two phases: first, where a
placeholder is created, then after the user card data is retrieved, the
data is inserted into the user card structure.
This causes an issue where, if the placeholder is too close to the
bottom of the viewport, and there's a lot of data being inserted into
the user card, then the user card will be partially rendered outside of
the viewport, resulting in odd scrolling behaviour.
To address this issue, this change makes use of float-kit's ability to
auto-update the position of the user-card. There are three relevant UX
changes from this:
- When the avatar is close to the bottom of the viewport, the
placeholder renders below the avatar, and the final user card is much
bigger, the user card will jump from being below the avatar, to above
the avatar.
- The user card follows the avatar when the chat window scrolls.
- When the avatar scrolls out of view, the user card is hidden.
This commit introduces deprecation warnings for accessing Site.mobileView or
Site.desktopView during application initialization to prevent
layout-related errors and improve code reliability.
The changes include:
* Added deprecation warnings for Site.mobileView and Site.desktopView
access during the initialization phase.
* Updated multiple plugins and components to avoid these deprecated
calls during startup.
* Refactored initialization logic across discourse-ai, discourse-chat,
discourse-calendar, discourse-reactions, discourse-assign,
discourse-subscriptions, and discourse-user-notes plugins
* Improved error prevention by discouraging early access to
view-dependent properties before the application is fully initialized
* Enhanced code maintainability by establishing clearer boundaries
between initialization and runtime phases
This deprecation helps prevent subtle bugs that can occur when
components try to determine the view type before the application context
is properly established, leading to more robust plugin initialization
patterns.
This change concerns these header icons
<img width="220" height="116" alt="image"
src="https://github.com/user-attachments/assets/eb7883cf-4766-4499-8d1a-116a542a2cdd"
/>
Currently the chat icon in the header switches to chat "mode" when
possible, and remembers your last forum location. The AI header icon
does not remember your last forum location, and just redirects you to
the homepage when you toggle it off.
This PR adds the last forum URL memory for the AI header icon as well.
I've also updated the AI header icon to be a link when
`ai_bot_enable_dedicated_ux` is enabled, this way it can be opened in a
new tab and do all the typical link behavior (requested here:
https://meta.discourse.org/t/change-ai-bot-icon-to-link-element/377435).
It is still a button when `ai_bot_enable_dedicated_ux`, which is
appropriate for opening the composer.
This also updates the AI button title when the state changes (noted
here:
https://meta.discourse.org/t/ai-bot-header-button-title-doesnt-always-match-its-action/377402)
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
Early initializers (e.g. chat-setup) were checking mobile mode before
the lib was initialized. This moves the init into the root of the
module, so it's definitely ready before anything accesses it.
Also updates the chat-emoji-button `displayed` property to be a getter,
so that it updates dynamically in 'viewport based mobile mode'.
Followup to 5873ea104d
Also remove the `scrollTop()`, which is now handled by `services/route-scroll-manager`.
Co-authored-by: Martin Brennan <martin@discourse.org>
This PR introduces a modern floatkit-based autocomplete system for the
core composer (both rich text / markdown modes), intended to replace the
legacy jQuery-based implementation. This will be enabled via a site
setting for now. All tests that cover the legacy implementation are
duplicated with the site setting enabled to ensure they keep functional
parity.
### What's changed:
* The autocomplete menu remains open between searches while typing
within a search term, instead of closing and reopening (this looks like
the menu flickering, especially if the searches are quickly resolving).
* Flip behaviour now works (the autocomplete menu should never overlap
with the header, and will appear below the cursor if there's not enough
space to appear fully in the viewport)
* On any mouse-down event outside the menu, the menu will immediately
close (previously, it stayed open during the grippie drag up/down of the
composer drawer, and closes on mouse-up)
* Preserves exact CSS structure and selectors for existing
themes/plugins
* Better use of native browser APIs
*
[scrollIntoView](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView)
API is used for handling scroll within the hashtag autocomplete menu
instead of manual calculation
*
[requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame)
API is used to better time the opening of the autocomplete menu with
repaint during pasting of autocompletable terms
* `position: absolute` CSS was removed - this didn't seem to affect the
old autocomplete during testing, and keeping it broke positioning for
the Floatkit-based autocomplete
### What's the same:
* All templates specific to the different types of autocomplete (user &
group / hashtag / emoji) remain exactly the same
* we update the selected class that's used to highlight the item in the
autocomplete menu while navigating it via keyboard the same way we do in
the old autocomplete - it's fairly imperative, but allows us to avoid a
deeper refactor (including an entirely new set of templates)
JS assets defined under `admin/` in plugins are compiled into a separate
bundle that should be loaded for staff users only, but we currently load
it for all users including normal users and anons. This is wasteful and
unexpected since it could cause errors if an asset in the admin bundle
of a plugin imports a module from the admin bundle in core (which
doesn't get loaded for non-staff users).
Fixes an issue where a URL like this:
```
https://meta.discourse.org/admin/site_settings/category/all_results?filter=discourse connect
```
Would appear to be broken when inserting into the composer via the
hyperlink modal. All we have to do is escape it before inserting,
and unescape before editing it in the modal.
Also in this commit I am renaming the InsertHyperlink modal to
UpsertHyperlink,
since it is used for both inserting and editing links.
This fixes an issue where the YouTube thumbnail was huge in a chat
transcript, like in this scenario:
* Share a link to a youtube video in channel A
* See it onebox at a reasonable size
* Grab a link to your message
* Share the link to your message in channel B (e.g. a DM to yourself)
* ❌ See GIANT youtube image
This commit only fixes the issue visually though -- it does not apply
the LazyYoutube decorations that actually embed the video. We can do
this in a followup commit.
Followup fb7fa2902c,
prevent opening the chat channel selector with Ctrl/Meta+K
in any inputs except the chat composer, most of the time you
do not want this, but especially in the topic composer.
In that case, you want the link insert modal to open.
Fixes an issue where the admin search results was showing
breadcrumbs with a double up of the parent label. For example,
we would show "Plugins > Plugins > AI > Usage" or
"Advanced > Advanced > Backups > Logs".
Also adds a missing translation for the chat incoming webhooks
page.
Chat inline onebox links should open in a new tab with the help of chat
decorators by appending the `target="_blank"` attribute. I suspect this
may have been accidentally broken during a refactor in #31309
The issue was that the element that we pass into the decorator has
changed, meaning that the selector in the decorator would never find
inline links in cooked messages.
When category lazy loading was disabled, chat channel CSS classes were
not being inserted into the page markup. This meant that they would not
be styled correctly in the markdown editor preview.