This moves chat tracking state calculation for channels
and threads into a central Chat::TrackingStateManager service, that
serves a similar purpose to the TopicTrackingState model
in core.
This service calls down to these query classes:
* ThreadUnreadsQuery
* ChannelUnreadsQuery
To get the unread_count and mention_count for the appropriate
channels and threads.
As well as this, this commit refactors the client-side chat
tracking state.
Now, there is a central ChatTrackingStateManager Ember Service
so all tracking is accessible and can be counted from one place,
which can also initialize tracking from an initial payload.
The actual tracking counts are now maintained in a ChatTrackingState
class that is initialized on the `.tracking` property of both channel and
thread objects.
This removes the attributes on UserChatChannelMembership and decoration
of said membership from ChannelFetcher, preferring instead to have an additional
object for tracking in the JSON.
* DEV: add new thread icon
* FIX: Use new thread icon, fix typo in SVG
UX: move the thread list icon to the right of
the collapse button
---------
Co-authored-by: Martin Brennan <martin@discourse.org>
We have been struggling lately finding site settings due to 30 setting limit
This was introduced for performance reasons a while back but is no longer as
needed given that ember is faster.
Additionally searching is hard, so allow people to use fuzzy search against
setting name.
What is the problem?
Previously the `sections` getter was initializing duplicate `lib/sidebar/(community-)section` instances every time it was evaluated. This change in identity was causing Ember's `{{#each` helper to totally rerender every section whenever the getter was evaluated.
What is the fix?
This commit refactors things to lean on Ember's components for state/lifecycle management. The `{{#each` loop is done over the source data, which is guaranteed to only change identity when there is a real config change. Individual section components are initialized for each section, and are responsible for constructing and tearing down their own `lib/sidebar/(community-)section` instances.
This commit also updates `lib/sidebar/(community-)section` to support service injection rather than passing service references around.
Co-authored-by: David Taylor <david@taylorhq.com>
We use the `:empty` css selector on `#modal-alert`, so we need to strip any whitespace from the contents to ensure the selector functions correctly. Followup to ad431ab03a
* FIX: Displaying the wrong number of minimum tags in the composer
When the minimum number of tags set for the category is larger than the minimum number of tags
set in the category tag-groups, the composer was displaying the wrong value.
This commit fixes the value displayed in the composer to show the max value between the required
for the category and the tag-groups set for the category.
This bug was reported on Meta in https://meta.discourse.org/t/tags-from-multiple-tag-groups-required-only-suggest-select-at-least-one-tag/263817
* FIX: Limiting tags in categories not working as expected
When a category was restricted to a tag group A, which was set to only allow
one tag from the group per topic, selecting a tag belonging only to A returned
other tags from A that also belonged to other group/s (if any).
Example:
Tag group A: alpha, beta, gamma, epsilon, delta
Tag group B: alpha, beta, gamma
Both tag groups set to only allow one tag from the group per topic.
If Category 1 was set to only allow tags from the tag group A, and the first tag
selected was epsilon, then, because they also belonged to tag group B, the tags
alpha, beta, and gamma were still returned as valid options when they should not be.
This commit ensures that once a tag from a tag group that restricts its tags to
one per topic is selected, no other tag from this group is returned.
This bug was reported on Meta in https://meta.discourse.org/t/limiting-tags-to-categories-not-working-as-expected/263143.
* FIX: Moving topics does not prompt to add required tag for new category
When a topic moved from a category to another, the tag requirements
of the new category were not being checked.
This allowed a topic to be created and moved to a category:
- that limited the tags to a tag group, with the topic containing tags
not allowed.
- that required N tags from a tag group, with the topic not containing
the required tags.
This bug was reported on Meta in https://meta.discourse.org/t/moving-tagged-topics-does-not-prompt-to-add-required-tag-for-new-category/264138.
* FIX: Editing topics with tag groups from parents allows incorrect tagging
When there was a combination between parent tags defined in a tag group
set to allow only one tag from the group per topic, and other tag groups
relying on this restriction to combine the children tag types with the
parent tag, editing a topic could allow the user to insert an invalid
combination of these tags.
Example:
Automakers tag group: landhover, toyota
- group set to limit one tag from the group per topic
Toyota models group: land-cruiser, hilux, corolla
Landhover models group: evoque, defender, discovery
If a topic was initially set up with the tags toyota, land-cruiser it was
possible to edit it by removing the tag toyota and adding the tag landhover
and other landhover model tags like evoque for example.
In this case, the topic would end up with the tags toyota, land-cruiser,
landhover, evoque because Discourse will automatically insert the
missing parent tag toyota when it detects the tag land-cruiser.
This combination of tags would violate the restriction specified in
the Automakers tag group resulting in an invalid combination of tags.
This commit enforces that the "one tag from the group per topic"
restriction is verified before updating the topic tags and also
make sure the verification checks the compatibility of parent tags that
would be automatically inserted.
After the changes, the user will receive an error similar to:
The tags land-cruiser, landhover cannot be used simultaneously.
Please include only one of them.
Moving all control of 'hidden' into Ember will resolve issues we're seeing with Ember fighting against manual DOM manipulation (both vanilla JS and JQuery).
Looking up `controller:modal` from components is not ideal. However, the next step in the refactoring is to create a modal 'service' which will be able to injected into components cleanly.
This commit also removes safe-area-inset-bottom when keyboard is displayed to avoid having a taller than needed space between composer and replying indicator.
Having these things configured at the invocation of showModal is a strange API, and means that any changes to the modal require updating the call sites. It makes much more sense for these to be defined as part of the modal's own template. This was already supported for many of the properties. This commit adds support for the `modalClass` and `titleAriaElementId` config to be passed to DModalBody.
For now there is no deprecation message. Support for passing these things to `showModal` will be dropped as part of an upcoming conversion of modals from controllers to components.
Before this commit chat was applying a fixed height on everything under the `/chat` route. It's only really needed on the channel page with the composer at the bottom of the page.
This commits makes the following changes:
- moves height limitation from `#main-outlet-wrapper` to `.chat-channel`
- makes browse channel page and members list page full height and rely on main document scrollbar
- adds height computation for draft header and direct message creator block to ensure the height is correct when creating a draft channel
- makes chat index full height to rely on the browser scrollbar. As a result the <kbd> + </kbd> button used on mobile to create a direct message as been moved out of `<ChannelsList>` into the chat index template
- sidebar height was relying on chat setting a max height, as a result the height computation of sidebar has been changed to work correctly, especially with an opened keyboard on mobile or ipad
Watched words were converted to regular expressions containing \W, which
handled only ASCII characters. Using [^[:word]] instead ensures that
UTF-8 characters are also handled correctly.
What is the problem?
The main problem here is that we were incorrectly registering the same `onStateChange` callback with `TopicTrackingState`
each time a user reads a post. When a user reads a post, the state in `TopicTrackingState` is updated and it triggers all
the `onStateChange` callbacks which have been registered. In the `CommunitySection` class, we register a callback which
would then call the `onTopicTrackingStateChange` method for each link in the class. For the `EverythingSectionLink` class,
this would lookup the state in `TopicTrackingState` to get a new count of unread/new topics and update the `totalUnread` and
`totalNew` properties which are tracked. For some reason that I have yet to figure out, updating the either of the tracked properties
would result in Ember rerendering the entire `{{#each this.sections as |section|}}` in `component/sidebar/user/custom-sections.hbs`
template. Note that `this.sections` refers to a `@cached` getter in the `SidebarUserCustomSections` class. The problem is that
the `sections` getter is initializing a new bunch of sidebar sections related classes without calling the teardown function.
As a result, we end up registering new `onStateChange` callbacks in `TopicTrackingState` in `CommunitySection` without
removing the old ones. Over time, the number of callbacks build up and we end up slowing down the application. While we do
not know the reason why defining a getter for the `sections` is causing the entire block to re-render, I realized that
it is dangerous to use a getter for `sections` here since we have very little control on when the cached is broken.
Instead, I moved the `sections` getter to a tracked property instead where the property is updated via `appEvents`. With
this change, updating the tracked properties in `EverythingSectionLink` is no longer triggering a complete re-render of the
said block above. We also now call `teardown` on the section objects that has been initialised before updating the `sections`
property.
Hard to write a test for this behavior, this is a micro optimisation which doesn’t change the behavior but only makes it smoother by happening right before async request.
The failure screenshot shows the message is on screen while the error is:
```
Failure/Error: example.run
expected to find text "My favorite message" in "Community\nEverything\nMy Posts\nMore\nMessages\nInbox\nChannels\nPolitics 1\nPersonal chat\nPolitics 1". (However, it was found 1 time including non-visible text.)
```
I expect the arrow element might e slightly hiding the link, but not 100% sure of this.
An extensibility point we support server side is setting meta_data
(topic / post custom fields) with the composer payload.
Previous to this change even though we had a lot of setup code we never
actually sent the payload.
This ensures that on create we send meta_data.
TopicsFilter is meant to generate a query scope from a given string so
we don't really need to ensure any ordering outside of the supported
order filters.