This is extracted from #22390.
This patch introduces a scope to avoid duplication and a new method,
`Chat::Channel.find_by_id_or_slug` to allow finding a channel either by
its id or by its slug (or its category slug).
`Jobs::AutoJoinChannelBatch` was holding a lot of logic which should be in a service. Moreover, this refactoring is the opportunity to address a bug which could cause a duplicate key error.
From now when trying to insert a new membership it won't fail if a membership is already present.
Example error:
```
Job exception: ERROR: duplicate key value violates unique constraint "user_chat_channel_unique_memberships"
DETAIL: Key (user_id, chat_channel_id)=(1, 2) already exists.
Backtrace
rack-mini-profiler-3.1.0/lib/patches/db/pg.rb:110:in `exec'
rack-mini-profiler-3.1.0/lib/patches/db/pg.rb:110:in `async_exec'
(eval):29:in `async_exec'
mini_sql-1.4.0/lib/mini_sql/postgres/connection.rb:209:in `run'
mini_sql-1.4.0/lib/mini_sql/active_record_postgres/connection.rb:38:in `block in run'
mini_sql-1.4.0/lib/mini_sql/active_record_postgres/connection.rb:34:in `block in with_lock'
activesupport-7.0.5.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
activesupport-7.0.5.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
activesupport-7.0.5.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
activesupport-7.0.5.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
mini_sql-1.4.0/lib/mini_sql/active_record_postgres/connection.rb:34:in `with_lock'
mini_sql-1.4.0/lib/mini_sql/active_record_postgres/connection.rb:38:in `run'
mini_sql-1.4.0/lib/mini_sql/postgres/connection.rb:64:in `query_single'
/var/www/discourse/plugins/chat/app/jobs/regular/chat/auto_join_channel_batch.rb:38:in `execute'
```
Note this commit is also using main branch of `shoulda-matchers` as the gem has not been released yet.
Co-authored-by: Loïc Guitaut <5648+Flink@users.noreply.github.com>
Prior to this commit we were loading a large number of thread messages without any pagination. This commit attempts to fix this and also improves the following points:
- code sharing between channels and threads:
Attempts to reuse/share the code use in channels for threads. To make it possible part of this code has been extracted in dedicated helpers or has been improved to reduce the duplication needed.
Examples of extracted helpers:
- `stackingContextFix`: the ios hack for rendering bug when momentum scrolling is interrupted
- `scrollListToMessage`, `scrollListToTop`, `scrollListToBottom`: a series of helper to correctly scroll to a specific position in the list of messages
- better general performance of listing messages:
One of the main changes which has been made is to remove the computation of visible message during scroll, it will only happen when needed (update last read for example). This constant recomputation of `message.visible` on intersection observer event while scrolling was consuming a lot of CPU time.
Why this change?
In `PostDestroyer#make_previous_post_the_last_one` and
`Topic.reset_highest`, we have a query that looks something like this:
```
SELECT user_id FROM posts
WHERE topic_id = :topic_id AND
deleted_at IS NULL AND
post_type <> 4
#{post_type}
ORDER BY created_at desc
LIMIT 1
```
However, we currently don't have an index that caters directly to this
query. As a result, we have seen this query performing poorly on large
sites if the PG planner ends up using an index that is suboptimal for
the query.
This commit adds an index to the `posts` table on `topic_id` and then
`created_at`. For the query above, PG will be able to do a backwards
index scan efficiently.
Context of this change:
There are two site settings which an admin can configured to set the
default categories and tags that are shown for a new user. `default_navigation_menu_categories`
is used to determine the default categories while
`default_navigation_menu_tags` is used to determine the default tags.
Prior to this change when seeding the defaults, we will filter out the
categories/tags that the user do not have permission to see. However,
this means that when the user does eventually gain permission down the
line, the default categories and tags do not appear.
What does this change do?
With this commit, we have changed it such that all the categories and tags
configured in the `default_navigation_menu_categories` and
`default_navigation_menu_tags` site settings are seeded regardless of
whether the user's visibility of the categories or tags. During
serialization, we will then filter out the categories and tags which the
user does not have visibility of.
## Problem
History modal is flashing when changing revision versions
## Context
This was introduced in https://github.com/discourse/discourse/pull/22666
We need to have a conditional loading spinner for the initial paint of the history modal as we don't have the revision yet loaded, so this can cause some odd rendering issues. At the same time we don't want to display the loading spinner each time we toggle between the revision versions, because the loading spinner replaces the revision body causing the modal sizes to be drastically different resulting in _jumping_ or _flashing_.
## Fix
Render the loading spinner only on the first paint of the modal.
https://github.com/discourse/discourse/assets/50783505/8d19275e-86a5-4132-8a1f-af4b4f5301a6
Followup to f5e8e73.
This switches the placeholder label to the existing string "optional
tags" and only shows it if there are no items picked.
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
For the Discourse 3.2 beta series, we intend to use a `-dev` suffix while beta versions are being developed in `main`/`tests-passed`. When a beta version is ready, it will be 'released' without the `-dev` suffix.
This commit adds support for the `-dev` suffix, and also refactors `Discourse::VERSION` so that the canonical representation is a simple human-readable string. Constants for each segment are derived from that, so the interface remains unchanged.
I was only able to get one failure out of 100 tries, this failure didn't get me more info. My best guess ATM is that sometimes, the first session was still loading while receiving the reaction and created some unexpected situation.
The commit attempts to start the "check" session before the session making the reaction hoping that will be enough to prevent this case, if this is the issue.
Change to drag move event handling. When position of mouse changed, we can assume it is not drag and drop, and we should keep default behaviour.
Otherwise, we stop propagation of the event to handle drag and drop correctly. s
Embed Motoko service's primary URL is transiting from embed.smartcontracts.org to embed.motoko.org, this PR updates the Onebox logic to work for either domain.
New API to change sidebar mode. We defined two:
Separated - only sections belonging to specific panel are displayed, and buttons to switch the panel are available as well.
Combined - all sections are displayed together and switch panel buttons are not visible.
In addition, as a part of refactoring, a new service called SidebarState was introduced.
The `/u` route was broken when there were no directory columns because
its order parameter relied on the first column's name. This commit adds
a `likes_received` as the default order when there are no columns, which
results in a list of users being output without any additional columns.
For this very edge case, that's better than a JS error.
This adds support for the `<=` and `<` version operators in `.discourse-compatibility` files. This allows for more flexibility (e.g. targeting the entire 3.1.x stable release via `< 3.2.0.beta1`), and should also make compatibility files to be more readable.
If an operator is not specified we default to `<=`, which matches the old behavior.
Sharing a link in chat will create a onebox embed with a source that includes a site icon and title.
This change prevents loading the site icon into lightbox.
Fixes issue with scrolling background when lightbox is opened on mobile.
Since we rely on swiping for navigating lightbox galleries on mobile, we want to disable document scrolling.
We recently added a "don't feed the trolls" feature which warns you about interacting with posts that have been flagged and are pending review. The problem is the warning persists even if an admin reviews the post and rejects the flag.
After this change we only consider active flags when deciding whether to show the warning or not.
We're seeing unhandled errors in production when web push notifications are failing with an SSL error. This is happening for a few users, but generating a large amount of log noise due to the sheer number of notifications.
This adds handling of SSL errors in two places:
1. In FinalDestination::HTTP, this is handled the same as a timeout error, and gives a chance to recover.
2. In PushNotificationPusher. This will cause the notification to retry a number of times, and if it keeps failing, disable push notifications for the user. (Existing behaviour.)
I wanted to wrap the SSL error in e.g. WebPush::RequestError, but the gem doesn't have request error handling, so didn't want to have the freedom patch diverge from the gem as well. Instead just propagating the raw SSL error.
Why this change?
We were verifying that a url for a section link in a custom sidebar
section is valid by passing the url string to `Router#recognize`.
If a `rootURL` has been set on the router, the url string that is passed
to `Router#recognize` has to start with the `rootURL`.
This commit fixes the problem by ensuring that `RouteInfoHelper` adds
the application subfolder path before calling `Router#recognize` on the
url string.