The list of categories is loaded async when lazy_load_categories is
enabled, but there is no visual indication that the list of categories
is being loaded.
Parsing html, modifying it, and then serializing had some negative side-effects (namely, it was losing html entity escaping in some cases)
Drops jsdom dependency
Merges the design experiment at
https://meta.discourse.org/t/post-quote-copy-to-clipboard-button-feedback/285376
into core.
This adds a new button by default to the menu that pops up when text is
selected in a post.
The normal Quote button that is shown when selecting text within a post
will open the composer with the quote markdown prefilled.
This new "Copy Quote" button copies the quote markdown directly to the
user’s clipboard. This is useful for when you want to copy the quote
elsewhere – to another topic or a chat message for instance – without
having to manually copy from the opened composer, which then has to be
dismissed afterwards. An example of quote markdown:
```
[quote="someuser, post:7, topic:285376"]
In this moment, I am euphoric.
[/quote]
```
In this PR we introduced the enabled/disabled components filter.
https://github.com/discourse/discourse/pull/25105
However, components are slightly more complicated and can be used/unused/enabled/disabled.
- Convert group based `experimental_search_menu_groups_enabled` site setting to be a _hidden_ boolean `experimental_search_menu` setting.
- Make default `true`
- Remove widget search menu tests
Discourse Encrypt Test Failure Fix - https://github.com/discourse/discourse-encrypt/pull/301
Ported from d95706b25a
This is enabled by default, but can be disabled via the `warn_critical_js_deprecations` hidden site setting.
The `warn_critical_js_deprecations_message` site setting can be used by hosting providers to add a sentence to the warning message (e.g. a date when they will be deploying the Ember 5 upgrade).
Currently, when bulk uploading and multiple uploads fail, we show a number of dialogs in quick succession. This is of course a terrible user experience.
With this change, we buffer the error messages until there are no more pending uploads. Then we combine the buffered errors and display a single dialog with a list of failed files.
* add cc addresses and post_id to sent email logs
* sort cc addresses by email address filter value and collapse additional addreses into tooltip
* add slice helper for use in ember tempaltes
* FIX: never skip push notifications
According to Apple, silent push notifications are automatically punished per:
https://developer.apple.com/videos/play/wwdc2022/10098/?time=814
> As mentioned when I showed you the code on how to request a push
> subscription, you must promise that pushes will be user visible.
> Handling a push event is not an invitation for your JavaScript to
> get silent background runtime. Doing so would violate both a user’s
> trust and a user’s battery life. When handling a push event, you are
> in fact required to post a notification to Notification Center.
> Other browsers all have countermeasures against violating the promise
> to make pushes user visible, and so does Safari.
> In the beta build of macOS Ventura, after three push events where you
> fail to post a notification in a timely manner, your site’s push
> subscription will be revoked. You will need to go through the permission
> workflow again.
The isIdle check was causing certain push notifications to be silent
Additionally, the auto dismissal logic was causing delays which may cause
the device to think the push was a silent one.
By removing this we hope to ensure push notification delivery is more robust
and consistent on iOS.
Having separate mobile/desktop templates is something we're moving away from. This commit moves the mobile-specific logic into a conditional in the main colocated template.
Previously it was relying on the `templates/mobile` logic to make this a simple div wrapper on mobile, and a more complex implementation on mobile. This commit colocates the template so it's active on mobile and desktop, but adds an `{{#if` block to explicitly change the behavior.
In Ember, these deprecations are wrapped in an `if(DEBUG)` check, so they are optimized out of the production build. We prefer to keep deprecations in production so that we can collect telemetry and warn theme authors who do not use local development environments.
This commit restores the deprecations as part of our ember-production-deprecations addon.
Why this change?
A system test which was testing our ability to add a form template to a
category was flaky. This turned out to be a client side bug where the
`FormTemplateChooser` dropdown may not display any dropdown options if
the ajax request to fetch the categories form template has not been
completed when the dropdown is opened.
What does this change do?
Make use of select-kit's `triggerSearch` function to fetch the records
which will properly rerender the dropdown options.
post action feedback is the mechanism in which we provide visual feedback
to the user when a post action is clicked, in cases where the action is a
background (hidden to user) for example: copying text to the clipboard
Core uses this to share post links, but other plugins (for example: AI) use
this to share post transcripts via the clipboard.
This adds a proper plugin API to consume this functionality
`addPostMenuButton` can provide a builder that specified a function as the action.
This function will be called with an object that has both the current post and a method for showing feedback.
`window.deprecationWorkflow` does not exist in the server-side pretty-text environment. This commit fixes the check and adds a general spec for deprecations triggered inside pretty-text
- Add plugin outlet to `AdminUserFieldItem`
- Add ability to include custom fields when saving `AdminUserFieldItem`
- Update plugin API with `includeUserFieldPropertiesOnSave` per ☝️
- Add `DiscoursePluginRegistry` to `UserFieldsController` to add custom columns
Categories will no longer be preloaded when `lazy_load_categories` is
enabled through PreloadStore.
Instead, the list of site categories will continue to be populated
by `Site.updateCategory` as more and more categories are being loaded
from different sources (topic lists, category selectors, etc).
In non secure contexts (HTTP vs HTTPS) which many run in development the
`clipboardCopy` method falls back to and an exec hack.
However, callers expect a promise from this method and the fallback just
returns a boolean.
This change passes down all params to the home logo widget (rather than explicitly setting minimized). This will allow for flexible logo sizing in the Discourse full width theme component.
This change simplifies the layout of our header when chat is open on mobile. The search icon and hamburger menu icons are also hidden and the Discourse logo is replaced by a ← Forum link to make it easier to continue where you left off within the forum (prior to this update the user could only go back to the forum index page).
With certain conditions, this issue does not show up. The easiest way to reproduce this is probably to do either of this
- Use a 3G slow connection or;
- Add a breakpoint to scrolling-post-stream.topRefresh (anon)
- (and optionally lock-on.lock)
This issue is happening because there are multiple areas that set scroll location in the post stream when loading a topic. In our case, sometimes lock-on is triggering and scrolling to post_1, before ?page=2's post_21 is being scrolled to, due to posts above post_21 can finishing loading at different times. This causes some calculations to not add up, as being in the middle of a post stream has different calculations than being at the top of the post stream.
The problem:
Removing the options to addEventListener results in events that are properly cleaned up when the search menu is removed. Previously every time you opened the search menu, the listeners would be attached again, and clicking outside even after it was closed would fire the function again and again (N times as you opened the search menu!)
This was made far far worse in this commit c91d053, where I called close() to remove focus from the search input in the event that the search menu is rendered outside the header.
The problem with this was 2-fold. The close function tried to focus the search header button in core here. When the events aren't cleanup up and that happens... you can't do anything in the app.
The solution:
We don't need the event listeners to close the search menu when it's rendered from the header. The widget header handles clicks outside of the header. Sooo
1. Only register them for standalone search menus
2. Remove the passive options to the listeners so that they are properly removed on close
3. Call close() to unfocus input rather than just closing panel
4. Rename passed in are closeSearchMenu -> onClose because it's more accurate. It's really a callback.
Why this change?
The `Editing sidebar tags navigation allows a user to filter the tag in the modal by selection` system test was flaky
when we were doing `modal.filter("").filter_by_unselected`. The
hypothesis here is that the filtering is debounced before issue a
request to load the new tags and the dropdown is only disabled in the
debounced function. Thereforethere is a chance that when
`modal.filter_by_unselected` runs, it is selecting a row against a
disabled dropdown which results in a noop.
What does this change do?
When filtering using the input in the modal, we will now disabled the
dropdown until the filtering completes which will then re-enable the
dropdown.
The `style` variable is always set because every category has a color
defined, so the surrounding if statement is unnecessary.
"+ X categories" option has also been removed in the past and the code
related to it is now dead code.
This changes the Plugins link in the admin sidebar to
be a section instead, which then shows all enabled plugin
admin routes (which are custom routes some plugins e.g.
chat define).
This is done via adding some special preloaded data for
all controllers based on AdminController, and also specifically
on Admin::PluginsController, to have the routes loaded without
additional requests on page load.
We just use a cog for all the route icons for now...we don't
have anything better.
We had our own implementation of number fields in Ember, extended from text fields. Number inputs are now widely supported in browsers, and we can fall back on the native implementation which will be a better experience in almost all cases.
One thing traded off here is number fields can't have a placeholder, but that is intentional. We aren't using that ability anywhere, and we probably only kept it because we're extending text fields.
With this change we can get rid of the entire .js file, since there's no custom behaviour, and just make NumberField a template.
(extracted from #23678)
* Move Wizard back into main app, remove Wizard addon
* Remove Wizard-related resolver or build hacks
* Install and enable `@embroider/router`
* Add "wizard" to `splitAtRoutes`
In a fully optimized Embroider app, route-based code splitting more
or less Just Work™ – install `@embroider/router`, subclass from it,
configure which routes you want to split and that's about it.
However, our app is not "fully optimized", by which I mean we are
not able to turn on all the `static*` flags.
In Embroider, "static" means "statically analyzable". Specifically
it means that all inter-dependencies between modules (files) are
explicitly expressed as `import`s, as opposed to `{{i18n ...}}`
magically means "look for the default export in app/helpers/i18n.js"
or something even more dynamic with the resolver.
Without turning on those flags, Embroider behaves conservatively,
slurps up all `app` files eagerly into the primary bundle/chunks.
So, while you _could_ turn on route-based code splitting, there
won't be much to split.
The commits leading up to this involves a bunch of refactors and
cleanups that 1) works perfectly fine in the classic build, 2) are
good and useful in their own right, but also 3) re-arranged things
such that most dependencies are now explicit.
With those in place, I was able to move all the wizard code into
the "app/static" folder. Embroider does not eagerly pull things from
this folder into any bundle, unless something explicitly "asks" for
them via `imports`. Conversely, things from this folder are not
registered with the resolver and are not added to the `loader.js`
registry.
In conjunction with route-based code splitting, we now have the
ability to split out islands of on-demand functionalities from the
main app bundle.
When you split a route in Embroider, it automatically creates a
bundle/entrypoint with the relevant routes/templates/controllers
matching that route prefix. Anything they import will be added to
the bundle as well, assuming they are not already in the main app
bundle, which is where the "app/static" folder comes into play.
The "app/static" folder name is not special. It is configured in
ember-cli-build.js. Alternatively, we could have left everything
in their normal locations, and add more fine-grained paths to the
`staticAppPaths` array. I just thought it would be easy to manage
and scale, and less error-prone to do it this way.
Note that putting things in `app/static` does not guarantee that
it would not be part of the main app bundle. For example, if we
were to add an `import ... from "app/static/wizard/...";` in a
main bundle file (say, `app.js`), then that chunk of the module
graph would be pulled in. (Consider using `await import(...)`?)
Overtime, we can build better tooling (e.g. lint rules and babel
macros to make things less repetitive) as we expand the use of
this pattern, but this is a start.
Co-authored-by: Godfrey Chan <godfreykfc@gmail.com>
The regen_ember_5_lockfile script was actually just duplicating the ember3 lockfile without changes 🤦♂️. This commit fixes that, and updates the ember-version-enforcement workflow to detect lockfile issues in future.
Consumers should use the default export. This function doesn't work directly (unless you manually construct its arguments) - the default export helper handles all that automatically.
This makes it much easier to see what a production site will look like before launch. The notices return on the next pageload, so there is minimal risk of this affecting visibility of an email configuration problem.
This new navbar component is used for every navbar in chat, full page or drawer, and any screen.
This commit also uses this opportunity to correctly decouple drawer-routes from full page routes. This will avoid having this kind of properties in components: `@includeHeader={{false}}`. The header is now defined in the parent template using a navbar. Each route has now its own template wrapped in a div of the name of the route, eg: `<div class="c-routes-threads">..</div>`.
The navbar API:
```gjs
<Navbar as |navbar|>
<navbar.BackButton />
<navbar.Title @title="Foo" />
<navbar.ChannelTitle @channel={{@channel}} />
<navbar.Actions as |action|>
<action.CloseThreadButton />
</navbar.Actions>
</navbar>
```
The full list of components is listed in `plugins/chat/assets/javascripts/discourse/components/navbar/index.gjs` and `plugins/chat/assets/javascripts/discourse/components/navbar/actions.gjs`.
Visually the header is not changing much, only in drawer mode the background has been removed.
This commit also introduces a `<List />` component to facilitate rendering lists in chat plugin.
This commit refactor CategoryList to remove usage of EmberObject,
hopefully make the code more readable and fixes various edge cases with
lazy loaded categories (third level subcategories not being visible,
subcategories not being visible on category page, requesting for more
pages even if the last one did not return any results, etc).
The problems have always been here, but were not visible because a lot
of the processing was handled by the server and then the result was
serialized. With more of these being moved to the client side for the
lazy category loading, the problems became more obvious.
Previously, `addGlobalNotice` would have to be called before the GlobalNotice component was rendered. By using a TrackedArray, we can improve that so that plugins can call the function at any time and the notice will be rendered immediately
We're changing the implementation of trust levels to use groups. Part of this is to have site settings that reference trust levels use groups instead. It converts the min_trust_level_to_allow_ignore site setting to ignore_allowed_groups.
This PR maintains backwards compatibility until we can update plugins and themes using this.
This is v0 of admin sidebar navigation, which moves
all of the top-level admin nav from the top of the page
into a sidebar. This is hidden behind a enable_admin_sidebar_navigation
site setting, and is opt-in for now.
This sidebar is dynamically shown whenever the user enters an
admin route in the UI, and is hidden and replaced with either
the:
* Main forum sidebar
* Chat sidebar
Depending on where they navigate to. For now, custom sections
are not supported in the admin sidebar.
This commit removes the experimental admin sidebar generation rake
task but keeps the experimental sidebar UI for now for further
testing; it just uses the real nav as the default now.
This bug appears to only be on Chrome due to the service worker fetching
the video content on page load instead of on play. For some reason
though the service worker would fetch around 4x more than the size of
the video resulting in excessive data being downloaded especially for
larger videos.
meta https://meta.discourse.org/t/287817
internal /t/111387/52
Float-kit elements (menus/tooltips) are positioned where they should be by setting an inline `left` property in JavaScript when they're rendered. For some reasons, we also set `left: 0` on float-kit elements here:
25d9927785/app/assets/stylesheets/common/float-kit/d-menu.scss (L11-L15)
This property is overridden by the inline property that the library sets in JavaScript. However, in RTL mode, all of our scss files are flipped where everything left becomes right and vice versa. In this case, the `left: 0` property in the scss file above becomes `right: 0`.
This results in a conflict specific to RTL mode where both the `left` and `right` properties are defined on the same absolute-positioned element; the `right` property will always be set to 0 because it comes from the (flipped) scss file above, and the inline `left` property will be set to some px amount determined in JavaScript.
The `right` property will take precedence over the inline `left` property due to the page being right-to-left (source: https://developer.mozilla.org/en-US/docs/Web/CSS/right#description) and this causes float-kit elements to incorrectly always stick to the right.
This commit removes the `left: 0` property altogether for float-kit elements from our scss files. It's not clear from git history why the property was added, and removing it doesn't seem to cause any issues.
Meta topic: https://meta.discourse.org/t/positioning-issues-with-rtl-locales-after-recent-updates/280220?u=osama
We're changing the implementation of trust levels to use groups. Part of this is to have site settings that reference trust levels use groups instead. It converts the tl4_delete_posts_and_topics site setting to delete_all_posts_and_topics_allowed_groups.
This one is a bit different from previous ones, as it's a boolean flag, and the default should be no group. Pay special attention to the migration during review.
This commit adds an additional toggle to our safe-mode system. When enabled, it will cause all deprecation messages to become exceptions. This gives admins a way to test their themes/plugins against upcoming Discourse changes without needing to use the browser developer tools.
This change converts the allow_uploaded_avatars site setting to uploaded_avatars_allowed_groups.
See: https://meta.discourse.org/t/283408
Hides the old setting
Adds the new site setting
Adds a deprecation warning
Updates to use the new setting
Adds a migration to fill in the new setting if the old setting was changed
Adds an entry to the site_setting.keywords section
Updates tests to account for the new change
After a couple of months, we will remove the allow_uploaded_avatars setting entirely.
Internal ref: /t/117248
Now that we're using native `import()`, our main JS bundles might not even be parse-able by older browsers. In that case, `I18n` will never be defined, and so we need to account for that situation in the browser-update code.
In modern hljs, languages should be targetted with `lang-` prefixes. These selectors haven't worked in Discourse for a long time, so let's drop them to reduce confusion
We no longer offer the option to use the legacy hamburger menu since October 9th 2023, see 832b3b9e60. However, the code for the legacy hamburger menu is still around and needs to be removed. All plugins and themes that we know of that customize the legacy hamburger menu have been updated to either remove the customizations or migrate the customizations to the new sidebar, so now we can safely remove the legacy hamburger menu code from core.
Internal topic: t/113137.
When `lazy_load_categories` is enabled, the categories are no longer
preloaded in the `Site` object, but instead they are being requested
on a need basis.
The categories page still loaded all categories at once, which was not
ideal for sites with many categories because ti would take a lot of
time to build and parse the response.
This commit adds pagination to the categories page using the LoadMore
helper. As the user scrolls through the categories page, more categories
are requested from the server and appended to the page.
<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
When 2FA is enforced and the user has no key or TOTP on their account, we
block navigating away from the page until they have added one. However,
we don't reload the page after they have added one, so the user is left
with a page that still says they need to add 2FA.
It's possible for browser extensions to trigger JS errors and deprecation warnings. That can lead to significant confusion and noise in our logs/metrics. One recent example we've identified is the 'Wappalyzer' extension triggering the `ember-global` deprecation.
This commit will clearly identify these errors/deprecations with a `[BROWSER EXTENSION]` prefix in the console.