Previously all locale bundles would be built & compressed during
assets:precompile. For most sites, only one of these languages was
actually used, so this is fairly wasteful.
This commit moves the main locale bundle into the
ExtraLocalesController, which has recently undergone many improvements
to make it more efficient. This allows locale files to be bundled "just
in time" when they're first accessed.
Now that brotli level=6 is enabled for these assets in our nginx config,
this change should have no impact on the locale bundle size.
This change does a couple of things.
Change in behaviour:
- Matches on the site setting name and keywords now get a higher ranking in search results.
- When counting gaps for ranking fuzzy matches, we no consider the smallest number of gaps.
Code organization:
- Extract a separate SiteSettingMatcher object for the matching logic.
- Flatten some conditionals to make control flow clearer.
- Higher weight now means higher in search results.
This is mainly used for the test environment where
`Discourse.current_hostname` and `GlobalSetting.relative_url_root` can
be stubbed.
### Reviewer notes
We don't really need a test here since this doesn't really affect the
production environment.
When ordering categories,
af8e48c1e0/app/models/category_list.rb (L61-L68)
Only one of the flows do `.group("categories.id")`.
This was causing sites with `SiteSetting.fixed_category_positions=true`
to 500 when another site setting
`SiteSetting.experimental_content_localization` was enabled. (Related:
https://github.com/discourse/discourse/pull/32464).
This commit fixes the issue by also grouping on the other case.
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.
This is a bug introduced by me by thinking the lonely operator is redundant here. It is not. Sometimes the param keys are not sent, and when they aren't we should preserve the existing attribute value, not null it out.
This PR fixes that and also adds a regression test explaining why it's needed.
A rework of https://github.com/discourse/discourse/pull/32460.
In the earlier PR that had to be reverted, we were directly deleting
cache (redis) and it was causing our image build to fail (see dev chat).
In this commit, we will rely on the existing method of invalid the keys
(which essentially will cause the next request to get the new site json
since the seq is not the same).
This PR makes the following key changes to the load-more component:
* Updating to a Glimmer component
* Changing from an eyeline/scrolling-based mechanism to an
IntersectionObserver to determine when to load
* Keeping track of a single invisible sentinel element to help trigger
the loadMore action instead of having to find and track the last item of
the collection upon every load
* The component can now be used without wrapping around some content to
be yielded - the intent is to use this for cases like
[DiscoveryTopicsList](f0057c7353/app/assets/javascripts/discourse/app/components/discovery/topics.gjs (L222))
where we might want more precise placement of the sentinel element.
* Added utility toggle functions to control observer behaviour in this
class for testing
We will replace the load-more mixin in DiscoveryTopicsList in another
PR.
https://github.com/user-attachments/assets/50d9763f-b5f8-40f6-8630-41bdf107baf7
### Technical Considerations
1. Keeping track of a single sentinel element simplifies the logic
greatly and is also more robust to changes in the collection that's
being loaded. (ref: a [previous
commit](2279519081)
that was following the previous approach of tracking specifically the
last item of the loaded collection); this also sidesteps odd edge cases
like if the tracked element is larger than the entire viewport.
2. Using
[isIntersecting](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry/isIntersecting)
instead of calculating manually whether the element is in the viewport
is also less flaky - I ran into issues with the boundingClientRect
inconsistently being calculated as outside the viewport on different
sized screens.
3. We need to properly bind `loadMore` functions with the action
decorator, otherwise the way we pass the loadMore callbacks through to
the observe-intersection modifier results in attempting to call it on
the loadMore component context instead. I've done this for all such
functions except for the one in
[`category-list`](0ed4b09527/app/assets/javascripts/discourse/app/models/category-list.js (L117))
which uses `@bind` that should be equivalent in terms of binding to the
correct `this`.
- Load moment and moment-timezone-with-data via webpack import instead
of including copies in every locale file
- Fetch static files from node_modules instead of `vendor/`
This cuts the size of locale-specific JS files in half, since they no
longer include moment itself.
After adjusting an overflow on the rich editor placeholder, it started
being cut on mobile, as the parent paragraph can be smaller than the
area the placeholder takes.
This fixes it by returning the `position: relative` to the
`.ProseMirror` editor, which also fixes some weird positioning errors
for "fake" cursors (gap cursor, codemark cursor, drop cursor) and
absolute-positioned elements that relied upon the editor being
`position: relative`.
This span renders even when the plugin outlet isn't being used, so it
can get in the way. I did a quick search and don't see it targeted
anywhere obvious (it would be difficult to do without a unique class
anyway)
This will show the experimental rich_editor setting and admins
can turn it on for their site. It is still marked experimental
because there are some features missing, but it works well for
95% of cases.
---------
Co-authored-by: Renato Atilio <renato@discourse.org>
Merging the core annotation check into the core backend job reduces the
number of runners required per workflow from 15 to 14. Before this
change, the core annotations job occupies a runner for about 1 min
30 secs in order to spend 9 seconds running the core annotations check.
While the step to run plugin system tests has been set with a timeout of
30 minutes, the overall job timeout was only set to 20 minutes. As a
result, we are starting to see the plugin system tests job fail due to
the job exceeding the 20 minutes timeout.
### Reviewer notes
Example of plugin system tests exceeding 20 minutes timeout:
https://github.com/discourse/discourse/actions/runs/14665943355/job/41160611627
Allows themes and components to opt out of category title badge styling
when using the `CategoryTitleLink`.
Using `@unstyled` allows the previous text only category name that we
had prior to #32109:
```
<CategoryTitleLink @category={{c}} @unstyled={{true}} />
```
Instead of having each test go incur the overhead of having to go
through the actual user flow to register a security key, we can generate
the WebAuthn credentials on the server side and adds it to the virtual
authenticator.
This was missed when adding category badges in #32109. Category title
badges are now added when the site setting for `Desktop category page
style` or `Mobile category page style` is set to either:
- Boxes with Subcategories
- Boxes with Featured Topics