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.
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.
- Update welcome topic copy
- Edit the welcome topic automatically when the title or description changes
- Remove “Create your Welcome Topic” banner/CTA
- Add "edit welcome topic" user tip
a373bf2 updated the behavior of replace-emoji so that the input is treated as unsafe-by-default. fancy_title is already escaped, so we need to mark it as html-safe to avoid it being double-escaped.
There is no need to html-safe the result of replace-emoji - it's already done as part of the helper.
### What is the problem?
It is possible to pass an arbitrary value to the limit parameter in `TagsController#search`, and have it flow through `DiscourseTagging.filter_allowed_tags` where it will raise an error deep in the database driver. MiniSql ensures there's no injection happening, but that ultimately results in an invalid query.
### How does this fix it?
This change checks more strictly that the parameter can be cleanly converted to an integer by replacing the loose `#to_i` conversion semantics with the stronger `Kernel#Integer` ones.
**Example:**
```ruby
"1; SELECT 1".to_i
#=> 1
Integer("1; SELECT 1")
#=> ArgumentError
```
As part of the change, I also went ahead to disallow a limit of "0", as that doesn't seem to be a useful option. Previously only negative limits were disallowed.
### Background
When SSRF detection fails, the exception bubbles all the way up, causing a log alert. This isn't actionable, and should instead be ignored. The existing `rescue` does already ignore network errors, but fails to account for SSRF exceptions coming from `FinalDestination`.
### What is this change?
This PR does two things.
---
Firstly, it introduces a common root exception class, `FinalDestination::SSRFError` for SSRF errors. This serves two functions: 1) it makes it easier to rescue both errors at once, which is generally what one wants to do and 2) prevents having to dig deep into the class hierarchy for the constant.
This change is fully backwards compatible thanks to how inheritance and exception handling works.
---
Secondly, it rescues this new exception in `UserAvatar.import_url_for_user`, which is causing sporadic errors to be logged in production. After this SSRF errors are handled the same as network errors.
This fixes a bug in the create invite API where if you passed in an
integer for the group_ids field it would fail to add the user to the
specified group.
The issues fixed:
1. Previously all static pages (e.g. login-required landing page, /tos, /privacy, forgot-password) were wrapped in the faq-read-tracking component
2. All these pages shared one controller with methods that were relevant to one route
3. There were two route-generating functions: `static-route-builder` and `build-static-route` 🤣
4. They were using the deprecated `renderTemplate()` API
5. A slight misuse of Ember API (`controllerFor()`)
6. Small mark-faq-read related bugs
added site toggle functionality through site settings
added tests to implemented feature
Introduced suggested correction
renamed find_new_topic method and deleted click_new_topic_button method
Currently the /new-category url can be accessed by moderators, regardless of whether the Site Setting for moderators_manage_categories_and_groups is true or false.
On top of this, non authorized users can also access this page but shows errors (no 404 loaded).
Since the 404 redirect happens within Ember, we need to allow the site setting value to be accessed within JS.
After this change all non admin users will see a 404 for this route, the exception being moderators if the moderators_manage_categories_and_groups setting has a value of true.
/t/73360
The problem
When selecting text and clicking the "Edit" button that pops up, this opens up the Fast Edit dialog.
The fast edit feature doesn't work well with non standard characters (non-ascii). If the user selects a string of text that contains non-ascii characters, sometimes they won't save. It is non-obvious to the user why this is happening. This issue occurs more frequently when editing content that is written in non-english languages, as fast-edit doesn't work well with non-ascii characters. We currently do a global replace on a couple of the more obvious quotation marks when the fast edit dialog attempts to save, but there are too many edge cases for foreign language content.
The solution
We can fix this issue by using a catch-all approach for non-ascii characters before the user clicks the edit button to bring up the fast edit dialog. Then we can fallback to the full composer to edit their text, which has much better support for non-ascii characters.
What does this regex do?
The regex used matches any character that is not within the ASCII range of 0x00 to 0x7F, which includes all control characters and non-ASCII characters.
This regex pattern can be used to match any character that is not a standard ASCII character, such as accented characters, non-Latin characters, and special symbols.
We were giving topics with repeated words extra weight in search index.
This meant that it was trivial to stuff words into title to dominate in search
given we search for exact title matches first.
The following tweak means that:
`invite invited invites`
and
`invite some stuff`
Both rank the same for title searching.
Titles are short and punchy, duplicating words should not give special
weight.
Requires a full reindex to take effect.
This commit fixes an issue where the Likes Received notification
count in the user digest email was not affected by the
since/last_seen date for the user, which meant that no matter
how long it had been since the user visited the count was
always constant.
Now instead for the Likes Received count, we only count the
unread notifications of that type since the user was last
seen.
This improves keyboard navigation in and out of select-kit components.
The improvements include:
- `Tab` will now dismiss the dropdown once the active element is outside
the select-kit element
- pressing `Escape` will not bubble, this is most noticeable in the
composer, pressing `Esc` there now when a dropdown is expanded will not
dismiss the composer
- `Shift+Tab` will also dismiss the dropdown once focus is outside it
The problem
The fast edit feature doesn't work well with non standard characters (non-ascii). If the user selects a string of text that contains non-ascii characters, then the edit won't save.
The solution
The best solution is to catch those non-ascii characters before the user clicks the edit button to bring up the fast edit dialog. Then we can fallback to the full composer to edit their text, which has much better support for non-ascii characters.
What does this regex do?
The regex used to catch this is [^\x00-\x7F], which matches any character that is not within the ASCII range of 0x00 to 0x7F, which includes all control characters and non-ASCII characters.
This regex pattern can be used to match any character that is not a standard ASCII character, such as accented characters, non-Latin characters, and special symbols.
The current limit (250 characters) is too low, as we have some
translations used for our badge descriptions that result in a
description length of 264 characters.
To be on the safe side, the limit is now set to 500 characters.
Ember's implicit injections feature is removed in Ember 4.x. We want to give ourselves more time to migrate to explicit injections, so this commit re-implements our implicit injections as extensions to the base framework classes.
Incremental migration to newer patterns can be achieved using the `@disableImplicitInjections` class decorator (available from `discourse/lib/implicit-injections').
This resolves and unsilences the `implicit-injections` deprecation.
A category's slug can be encoded when
`SiteSetting.slug_generation_method` has been set to "encoded". As a
result, we have to support non ASCII characters as well.
Change mechanism handling `more` button for sidebar.
Before it was using HTML details tag.
To make tests more reliable, we are switching to use ember runloop.
What is the problem?
The TopicTrackingState is a service on the client side that is used to store
state of topics which is new or has unread posts for a given user. The state
is updated via various means and the one in concern here is whenever we load
a new topic list from the server. When a topic list is loaded from the server,
we sync this new topic list with the states in TopicTrackingState. There is also
a hard limit on the number of states that is stored by TopicTrackingState for
performance reasons and the limit is currently set to 4000. It was noticed that
once this limit has been reached, syncing a topic list with TopicTrackingState can
result in the registered state change callbacks to be called unnecessarily. This
is because during `TopicTrackingState#sync` we call `TopicTrackingState#removeTopic`
if the topic in question is neither new or unread to a user. However, `TopicTrackingState#removeTopic`
would call `TopicTrackingState#_afterStateChange` even if nothing was removed.
What is the fix?
This commit fixes the problem by checking that `TopicTrackingState#_afterStateChange` is only
called in `TopicTrackingState#removeTopic` when a topic is actually removed.
This amends it so our cached counting reliant specs run in synchronize mode
When running async there are situations where data is left over in the table
after a transactional test. This means that repeat runs of the test suite
fail.
- Ensure changing timezones are reflected immediately in the date-time-input (the computed property was missing a dependent key)
- Ensure date-input doesn't lose timezone information (calling `toDate()` causes moment timestamps to lose timezone information)
This was created to resolve issues in the discourse-calendar plugin (https://github.com/discourse/discourse-calendar/pull/399)
In the expand table event handler, we currently rely on `event.target`
to select the table being expanded. Sometimes, the target is the svg icon
wrapped inside the button instead of the button itself. This throws
things off.
This change uses `currentTarget` which refers to the button
element even if the event originated from svg icon.
* DEV: move sidebar community section to database
Before, community section was hard-coded. In the future, we are planning to allow admins to edit it. Therefore, it has to be moved to database to `custom_sections` table.
Few steps and simplifications has to be made:
- custom section was hidden behind `enable_custom_sidebar_sections` feature flag. It has to be deleted so all forums, see community section;
- migration to add `section_type` column to sidebar section to show it is a special type;
- migration to add `segment` column to sidebar links to determine if link should be displayed in primary section or in more section;
- simplify more section to have one level only (secondary section links are merged);
- ensure that links like `everything` are correctly tracking state;
- make user an anonymous links position consistence. For example, from now on `faq` link for user and anonymous is visible in more tab;
- delete old community-section template.
This commit fixes a bug on subfolder setups where the user messages
inbox dropdown will always be blank. This is because we were comparing
URLs using values from `router.currentURL` and `router.urlFor` where
`router.currentURL` does not include `router.rootURL` while
`router.urlFor` does.
Ember's implicit injections feature is removed in Ember 4.x. We want to give ourselves more time to migrate to explicit injections, so this commit re-implements our implicit injections as extensions to the base framework classes.
Incremental migration to newer patterns can be achieved using the `@disableImplicitInjections` class decorator (available from `discourse/lib/implicit-injections').
This resolves and unsilences the `implicit-injections` deprecation.
When navigating with the keyboard, the select-kit would not close when
focus was moved to an element outside of the body. For example, when
navigating via Tab or Shift+Tab, once the end (or beginning) of the list
was reached, focus would move out of the SK element, but the SK itself
would stay visible.
Switching from a click event to a focusout event solves the issue and
covers both mouse and keyboard navigation.
Before this fix if the underlying model of a reviewable was changed, the filter wouldn't work anymore as it was expecting a 1:1 relation between filter type and model name.
This commit also relies on the `Reviewable.types` array to check against valid types instead of a regex not checking much.
Finally this commit adds a spec to ensure chat reviewables are listable from the review index page.
Ran into an issue with these hooks preventing click events on anchors from completing (because the triggered rerender cancels the click). See:
https://github.com/discourse/discourse-header-search/pull/24
This change should have no effect on existing usage of these hooks. Current usage is limited to:
- legacy navigation (should be a no-op)
- reactions plugin (should be a no-op)
- discourse-header-search (will fix the issue!)
* FIX: Empty video thumbnails
This fix ensures that topic video thumbnail generation is completed
before the composer is allowed to submit which should prevent some bugs
around missing thumbnails on video topics.
* move callback to on upload-success
This will automatically adjust when browser UI is shown/hidden (e.g. when scrolling up/down on mobile Safari).
Similar approach to c82094cd9d, which targeted the 'slide-in' version of menus.
Many blog posts use these to illustrate and images were previously omitted
Additionally strip superfluous HTML and BODY tags from embed HTML.
This was incorrectly returned from server.
Followup to c03f83bbea.
The `flair_group_id` parameter is now required to show the flair, and this serializer was missing that detail.
This also fixes a typo in the `include_flair_group_name?` method.
Group user event webhooks filtered by group fail silently
because the `group_ids` job arg wasn't being passed into the job.
This change add's `group_ids` to the `EmitWebHookEvent` jobs queued for
`user_added_to_group` and `user_removed_from_group` events.
User status updates come from the server in a map where keys are user IDs.
If user.trackStatus() is called for a user model without an ID, the model
cannot identify its status updates and silently misses them. It's quite hard to
notice that a user rendered in the UI doesn't receive live status updates.
Also, it's not immediately obvious what's the reason of the problem.
A warning will be very helpful here.
Named outlets are deprecated and will be removed in Ember 4.x.
Backwards-compatibility shims are introduced so that plugin overrides to `controller:composer` are ported to `service:composer`.
After removing `TextareaTextManipulation` from `ChatComposer` and using `TextareaInteractor` as a proxy, one function has been forgotten: `paste(event)` which is not available in glimmer components anymore, and even less avaiable now that the mixin is not tied to a component anymore but a real DOM node. As a solution we now add a manual paste event listener which will call `paste(event)`.
Adds a bit more information to the categories view for crawlers, for better indexing of deep content.
This only works when the "Subcategories with Featured Topics" is the selected layout.
We call the `/u/search/users` URL when autocompleting users. It returns
user's name, username and avatar template, but not user ID.
We need it to return user IDs in order to display user status in certain situations.
I could add ID to FoundUserWithStatusSerializer, so it will be added only if
user status is enabled in site settings. But I feel that it's good to always return it,
it's not a lot of data comparing to what we already return, and it should be useful
in other scenarios.
This pull request is a full overhaul of the chat-composer and contains various improvements to the thread panel. They have been grouped in the same PR as lots of improvements/fixes to the thread panel needed an improved composer. This is meant as a first step.
### New features included in this PR
- A resizable side panel
- A clear dropzone area for uploads
- A simplified design for image uploads, this is only a first step towards more redesign of this area in the future
### Notable fixes in this PR
- Correct placeholder in thread panel
- Allows to edit the last message of a thread with arrow up
- Correctly focus composer when replying to a message
- The reply indicator is added instantly in the channel when starting a thread
- Prevents a large variety of bug where the composer could bug and prevent sending message or would clear your input while it has content
### Technical notes
To achieve this PR, three important changes have been made:
- `<ChatComposer>` has been fully rewritten and is now a glimmer component
- The chat composer now takes a `ChatMessage` as input which can directly be used in other operations, it simplifies a lot of logic as we are always working a with a `ChatMessage`
- `TextareaInteractor` has been created to wrap the existing `TextareaTextManipulation` mixin, it will make future migrations easier and allow us to have a less polluted `<ChatComposer>`
Note ".chat-live-pane" has been renamed ".chat-channel"
Design for upload dropzone is from @chapoi
Due to the order we were parsing markdown, bbcode [url] elements were not
handled properly.
`[url]https://example.com/path[/url]` was not currectly parsing cause
linkify was detecting the url as: `https://example.com/path[/url]` which is
legit.
To resolve this I swapped url to use a replace rule, and instead re-parsed
the internal payload and injected the tokens in.
This fix is complex cause we support stuff like
`[url][b]test.com[/b][/url]`
So we need to parse the content inside url `[b]test.com[/b]`
Currently, only user badge grants emit webhook events. This change
extends the `user_badge` webhook to emit user badge revocation events.
A new `user_badge_revoked` event has been introduced instead of relying
on the existing `user_badge_removed` event. `user_badge_removed` emitted
just the `badge_id` and `user_id` which aren't helpful for generating a
meaningful webhook payload for revoked(deleted) user badges.
The new event emits the user badge object.
* FIX: Blank video thumbnails
On some mobile and possibly other browsers, the automatic video
thumbnail generation would create blank or all white images.
This commit addresses several different issues that was preventing image
generation from working correctly on mobile.
* fix typo
On the client-side, message-bus subscriptions and reviewable count UI is based on the 'redesigned_user_menu_enabled' boolean. We need to use the same logic on the server-side to ensure things work correctly when legacy navigation is used alongside the new user menu.
The value field of ThemeField is only used when viewing a diff in the staff action logs and local theme editing. value is being serialized into the theme index as well, which is not used. It's a huge amount of JSON that we can cut by removing it.
This also breaks up the various theme serializers into separate classes so they autoload properly (or at least restart the server on edit)
When revising a post, if the topic that post belonged to did not have a category attached it would error with
> NoMethodError (undefined method `read_restricted' for nil:NilClass)
The updated user menu is the default for new sites, and will soon be enabled on older sites. This commit removes the 'EXPERIMENTAL' warning from the new `registerUserMenuTab` API, and adds a note to the `addUserMenuGlyph` documentation.
* FIX: Do not overwrite existing thumbnails
When auto generating video thumbnails they should not overwrite any
existing topic thumbnails.
This also addresses an issue with capitalized file extensions like .MOV
that were being excluded.
* Update app/models/post.rb
Remove comment
Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
---------
Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
Followup to 17ba00c395.
Fix for https://meta.discourse.org/t/-/261917
This fixes a usability issue where the user couldn't switch to the user
menu when the search menu was visible and the text in the input was
selected.
Explanation: The `click` event is triggered both when clicking and when
selecting some text and clicking. This means that when selecting text in
the search input, at the end of the selection event, a click event was
triggered. And if that click event happened to be outside of the search
menu, then the menu would be dismissed.
Previously, we fixed this by checked if a current text selection was
present. But that results in a small side-effect of not switching to
other menus. This PR switches to setting a flag during `mouseDown` and
then using that flag when evaluating whether to trigger clickOutside or
not.
We are seeing issues with the composer not being able to close due to the addition of a error message when rescuing from `Draft::OutOfSequence`. This PR will revert to the original solution implemented prior to https://github.com/discourse/discourse/pull/21148 that just silently rescues from `Draft::OutOfSequence`
This PR adds the ability to destroy reviewables for a passed user via the API. This was not possible before as this action was reserved for reviewables for you created only.
If a user is an admin and calls the `#destroy` action from the API they are able to destroy a reviewable for a passed user. A user can be targeted by passed either their:
- username
- external_id (for SSO)
to the request.
In the case you attempt to destroy a non-personal reviewable and
- You are not an admin
- You do not access the `#destroy` action via the API
you will raise a `Discourse::InvalidAccess` (403) and will not succeed in destroying the reviewable.
Responding to negative behaviour tends to solicit more of the same. Common wisdom states: "don't feed the trolls".
This change codifies that advice by introducing a new nudge when hitting the reply button on a flagged post. It will be shown if either the current user, or two other users (configurable via a site setting) have flagged the post.
This commit fixes the following scenario:
1. The user is searching for hashtags in chat, where the subcategory
type is not highest-ranked in priority order.
2. There can, but doesn't have to be, a higher-ranked matching chat
channel that has the same slug as the subcategory.
3. Since it is not the highest-ranked type, the subcategory, which
normally has a ref of parent:child, has its ref changed to
child::category, which does not work
This was happening because whenever a hashtag type was not highest
ranked, if _any_ other hashtag results conflicted slugs, we would
append the ::type suffix. Now, we only append this suffix if a
higher-ranked type conflicts with the hashtag, and we use the current ref
to build the new typed ref to preserve this parent:child format as well,
it's more accurate.