Commit Graph

107 Commits

Author SHA1 Message Date
Loïc Guitaut
2a28cda15c DEV: Update to lastest rubocop-discourse 2024-05-27 18:06:14 +02:00
Jan Cernik
9889547475
FEATURE: Allow to bulk delete chat messages (#26586) 2024-05-22 08:57:00 -03:00
Joffrey JAFFEUX
26c8eab1f3
FIX: allows bots to create/update/stream messages (#26900)
Prior to this commit, only system users had this pass.

Another significant change of the PR, is to make membership of a channel the angular stone of the permission check to create/update/stop streaming a message. The idea being, if you are a member of a channel already we don't need to check if you can join it AGAIN.

We also have `Chat::AutoRemove::HandleCategoryUpdated` which will deal with permissions change so it's simpler and less prone to error to consider the membership as the only source of truth.
2024-05-07 15:17:42 +02:00
David Battersby
0c8f531909
FEATURE: encourage users to set chat thread titles (#26617)
This change encourages users to title their threads to make it easier for other users to join in on conversations that matter to them.

The creator of the chat thread will receive a toast notification prompting them to add a thread title when on mobile and the thread has at least 5 sent replies.
2024-04-29 17:20:01 +08:00
Joffrey JAFFEUX
52e8d57293
FEATURE: implements last read message for threads (#26702)
This commit will now allow us to track read position in a thread and returns to this position when you open the thread.

Note this commit is also extracting the following components to make it possible:
- `<ChatMessagesScroller />`
- `<ChatMessagesContainer />`

The `UpdateUserThreadLastRead` has been updated to allow this.

Various refactorings have also been done to the code and specs to improve the support of last read.
2024-04-25 10:47:54 +02:00
Jan Cernik
cab178a405
DEV: Move chat service objects into core (#26506) 2024-04-04 10:57:41 -03:00
Joffrey JAFFEUX
bbb8595107
PERF: defer loading channels (#26155)
Prior to this change we would pre-load all the user channels which making initial page load slower. This change will make them be loaded right after initial load. In the past this was not possible as the channels would have to be loaded on each page transition. However since about a year, we made the channels to be cached on the frontend and no other request will be needed.

I have decided for now to not show a loading state in the sidebar as I think it would be noise, but we can reconsider this later.

Note given we don't have the channels loaded at first certain things where harder to accomplish. The biggest UX change of this commit is that we removed all the complex logic of computing the best channel to display when you load /chat. We will now store the id of the last channel you visited and will use this id to decide which channel to show.
2024-03-18 08:35:07 +01:00
Joffrey JAFFEUX
821402d024
DEV: removes default service actions (#26078)
Previously services would let you define a high level default `def default_actions_for_service; end` which would define various handlers like `on_success`, after months of usage we consider the cons are superior to the pros here.

Two mains cons:
- people would often not understand where the handling was coming from
- it's easy to miss a case when you write your specs
2024-03-07 12:10:43 +01:00
Joffrey JAFFEUX
76953cc356
FEATURE: allows to force a thread (#25987)
Forcing a thread will work even in channel which don't have `threading_enabled` or in direct message channels.

For now this feature is only available through the `ChatSDK`:

```ruby
ChatSDK::Message.create(in_reply_to_id: 1, guardian: guardian, raw: "foo bar baz", channel_id: 2, force_thread: true)
```
2024-03-06 12:03:42 +01:00
Loïc Guitaut
f7d7092a7a DEV: Update rubocop-discourse to latest version
The lastest version of rubocop-discourse enables rules regarding
plugins.
2024-03-04 15:08:35 +01:00
Joffrey JAFFEUX
bb079f54cb
FIX: better handling of error on create DM (#25908)
Prior to this fix we were correctly failing but just returning a generic error.
2024-02-27 10:21:36 +01:00
Joffrey JAFFEUX
d8d756cd2f
DEV: chat streaming (#25736)
This commit introduces the possibility to stream messages. To allow plugins to use streaming this commit also ships a `ChatSDK` library to allow to interact with few parts of discourse chat.

```ruby
ChatSDK::Message.create_with_stream(raw: "test") do |helper|
  5.times do |i|
    is_streaming = helper.stream(raw: "more #{i}")
    next if !is_streaming
    sleep 2
  end
end
```

This commit also introduces all the frontend parts:
- messages can now be marked as streaming
- when streaming their content will be updated when a new content is appended
- a special UI will be showing (a blinking indicator)
- a cancel button allows the user to stop the streaming, when cancelled `helper.stream(...)` will return `false`, and the plugin can decide exit early
2024-02-20 09:49:19 +01:00
David Battersby
04d2ec45b4
DEV: remove user thread count route (#25385)
Removes a now redundant route for the user thread count.
2024-01-24 10:32:34 +08:00
David Battersby
4512e5652f
FEATURE: Mobile Chat Footer Redesign (#25161)
This update adds three tabs to the bottom of the chat overlay to make it easier for users to navigate chat on mobile.

As a result of this change:

- Direct Messages are now shown separately from public channels on mobile
- My Threads has now moved from the channel list to it's own tab on mobile
- My Threads can still be accessed on desktop via the sidebar and within the drawer channel list
- Chat back button has been updated to navigate to the correct tab (for both channels and threads)

Some special cases:

- If DMs are not used then the tab is not rendered
- If the user has no threads then the tab is not rendered
- If both the tabs for DMs and Threads aren't available then the whole footer will not be rendered
- Chat footer is only shown on the listing pages (DMs, Channels, My Threads)

---------

Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2024-01-16 14:29:33 +08:00
Joffrey JAFFEUX
09277bc543
FEATURE: my threads page (#24771)
This commit adds a new "My threads" link in sidebar and drawer. This link will open the "/chat/threads" page which contains all threads where the current user is a member. It's ordered by activity (unread and then last message created).

Moreover, the threads list of a channel page is now showing every threads of a channel, and not just the ones where you are a member.
2023-12-11 07:38:07 +01:00
Joffrey JAFFEUX
a1690e0401
DEV: removes dead code (message_link) (#24648)
Linking to a message ID is now handled by the frontend router: `chat.channel.near-message`
2023-11-30 11:13:37 +01:00
Joffrey JAFFEUX
384a8b17a1
FIX: leaving a group channel should destroy membership (#24631)
In other kind of channels we will only unfollow but for group channels we don't want people to keep appearing in members list.

This commit also creates appropriate services:
- `Chat::LeaveChannel`
- `Chat::UnfollowChannel`

And dedicated endpoint for unfollow: `DELETE /chat/api/channels/:id/memberships/me/follows`
2023-11-29 17:48:14 +01:00
Joffrey JAFFEUX
ee5bdb3436
DEV: refactor flag message (#24604)
- Uses a chat service: `Chat::FlatMessage`
- Moves logic inside chat api controllers
- Create a javascript chat api helper: `chatApi.flagMessage(...)`
2023-11-28 18:24:09 +01:00
Joffrey JAFFEUX
906caa63d7
FEATURE: implements drafts for threads (#24483)
This commit implements drafts for threads by adding a new `thread_id` column to `chat_drafts` table. This column is used to create draft keys on the frontend which are a compound key of the channel and the thread. If the draft is only for the channel, the key will be `c-${channelId}`, if for a thread: `c-${channelId}:t-${threadId}`.

This commit also moves the draft holder from the service to the channel or thread model. The current draft can now always be accessed by doing: `channel.draft` or `thread.draft`.

Other notable changes of this commit:
- moves ChatChannel to gjs
- moves ChatThread to gjs
2023-11-22 11:54:23 +01:00
Roman Rizzi
75e2c6b506
DEV: Pass the user who requested the summary to the strategy. (#24489)
This change allows the `discourse-ai` plugin to log the user who requested the summary in the `AiApiAuditLog`.
2023-11-21 13:27:27 -03:00
Joffrey JAFFEUX
7f3f682f67
DEV: removes dead code (#24345) 2023-11-13 15:18:15 +01:00
Joffrey JAFFEUX
ab832cc865
FEATURE: introduces group channels (#24288)
Group channels will allow users to create channels with a name and invite people. It's possible to add people even after creation of the channel. Removing users is not yet possible but will be added in the near future.

Technically a group channel is `direct_message_channel` with a group attribute set to true on its direct message (chatable). This model might evolve in the future but offers much flexibility for now without having to rely on a complex migration.

The commit essentially consists of:
- a migration to set existing direct message channels with more than 2 users to a group
- a new message creator which allows to search, add members, and create groups
- a new `AddUsersToChannel` service
- a modified `SearchChatable` service
2023-11-10 11:29:28 +01:00
Joffrey JAFFEUX
90efdd7f9d
PERF: cook message in background (#24227)
This commit starts from a simple observation: cooking messages on the hot path can be slow. Especially with a lot of mentions.

To move cooking from the hot path, this commit has made the following changes:

- updating cooked, inserting mentions and notifying user of new mentions has been moved inside the `process_message` job. It happens right after the `Chat::MessageProcessor` run, which is where the cooking happens.
- the similar existing code in `rebake!` has also been moved to rely on the `process_message`job only
- refactored `create_mentions` and `update_mentions` into one single `upsert_mentions` which can be called invariably
- allows services to decide if their job is ran inline or later. It avoids to need to know you have to use `Jobs.run_immediately!` in this case, in tests it will be inline per default
- made various frontend changes to make the chat-channel component lifecycle clearer. we had to handle `did-update @channel` which was super awkward and creating bugs with listeners which the changes of the PR made clear in failing specs
- adds a new `-processed` (and `-not-processed`) class on the chat message, this is made to have a good lifecyle hook in system specs
2023-11-06 15:45:30 +01:00
Joffrey JAFFEUX
5fec841c19
FIX: ensures users can open channel invites (#24067)
We were incorrectly generating URLs with message id even when it was not provided, resulting in a route ending with "undefined", which was causing an error.

This commit also uses this opportunity to:
- move `invite_users` into a proper controller inside the API namespace
- refactors the code into a service: `Chat::InviteUsersToChannel`
2023-10-24 18:51:33 +02:00
David Battersby
f1e22dfebd
FEATURE: add grace period for chat edits (#23800)
This change allows users to edit their chat messages based on the criteria added to Site Settings.

If the grace period conditions are met then there will be no (edited) text applied to the message.

The following site settings are added to chat:

chat editing grace period (seconds since message created)
chat editing grace period max diff for low trust levels (number of characters changed)
chat editing grace period max diff for high trust levels (number of characters changed)
2023-10-23 16:40:30 +08:00
Joffrey JAFFEUX
c8fff19b99
DEV: removes the notion of staged thread (#23612)
While very fast and powerful staged threads forces a lot of gymnastic and edge cases. This patch adds a new service `Chat::CreateThread` and uses it to create a thread unconditionally when a user replies to a message in a threading enabled channel. If the user actually doesn’t send a message we will have a thread with no messages which has no important impact and could even be periodically cleaned if necessary.

Note that this commit also moves message actions to .gjs as it was the original goal of this PR to correctly check for staged thread to show the menu or not.
2023-09-15 18:09:45 +02:00
Loïc Guitaut
243793ec6e
DEV: Migrate Chat::MessageCreator to a service (#22390)
Currently, the logic for creating a new chat message is scattered
between a controller and an “old” service.

This patch address this issue by creating a new service (using the “new”
sevice object system) encapsulating all the necessary logic.
(authorization, publishing events, etc.)
2023-09-07 08:57:29 +02:00
Joffrey JAFFEUX
39b598f304
UI: refines thread list item (#23207)
It will now replies count and participants list. Also the title will be OM excerpt or user defined title, no more default "Thread" title. Lastly, the author of the last reply is also shown as prefix of it.
2023-08-24 18:45:20 +02:00
Joffrey JAFFEUX
687c6c7515
FIX: correctly display max users message error (#23178) 2023-08-22 12:42:35 +02:00
Alan Guo Xiang Tan
bfc3132bb2
SECURITY: Impose a upper bound on limit params in various controllers
What is the problem here?

In multiple controllers, we are accepting a `limit` params but do not
impose any upper bound on the values being accepted. Without an upper
bound, we may be allowing arbituary users from generating DB queries
which may end up exhausing the resources on the server.

What is the fix here?

A new `fetch_limit_from_params` helper method is introduced in
`ApplicationController` that can be used by controller actions to safely
get the limit from the params as a default limit and maximum limit has
to be set. When an invalid limit params is encountered, the server will
respond with the 400 response code.
2023-07-28 12:53:46 +01:00
Joffrey JAFFEUX
2d567cee26
FEATURE: thread pagination (#22624)
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.
2023-07-27 09:57:03 +02:00
Andrei Prigorshnev
d1760727cf
DEV: check if user can_chat inside the can_join_chat_channel guardian (#21812)
Someone who cannot chat is also not able to join chat channels, 
so we may not check all the time user.can_chat? && user.can_join_chat_channel? 
and just call user.can_join_chat_channel? instead.
2023-07-19 21:55:00 +04:00
Roman Rizzi
61aeb2da90
FEATURE: Inline topic summary. Cached version accessible to everyone. (#22551)
* FEATURE:  Inline topic summary. Cached version accessible to everyone.

Anons and non-members of the `custom_summarization_allowed_groups_map` groups can see cached summaries for any accessible topic. After the first 12 hours and if the posts to summarize have changed, allowed users clicking on the button will automatically re-generate it.

* Ensure chat summaries work and prevent model hallucinations when there are no messages.
2023-07-12 11:21:51 -03:00
Joffrey JAFFEUX
aca0bf69ef
WIP: threads list pagination (#22502)
This implementation will need more work in the future. For simplification of tracking and other events (new thread, delete/restore OM...) we used the threads from `threadsManager` which makes pagination more complicated as we already have some results when we start.

Note this commit also simplify `Collection` to only have one `load` method which can be called repeatedly.
2023-07-12 09:38:44 +02:00
Martin Brennan
3ea8203719
FIX: Track thread in UI when user sends first message (#22462)
When a user sends their first message in a thread we
automatically track the thread in the backend, but we
don't reflect this in the UI until the user re-opens
the thread. This commit fixes that by showing the new
tracking level in the UI.
2023-07-07 13:09:06 +10:00
Joffrey JAFFEUX
c0808b2537
FIX: correctly makes dm creator to follow channel (#22470)
In previous changes we prevented creating a channel to also make users follow the channel. We were forcing recipients to follow the channel on message sent but this was not including the creator of the message itself.

This commit fixes it and also write an end-to-end system spec to cover these cases. The message creator service is currently being rewritten and should correctly test and ensure this logic is present.

This commit also makes changes on the frontend to instantly follow a DM when you open it, this change prevents a green dot to appear for a split second when you send a message in a channel you were previously not following. Only recipients will see the green dot.
2023-07-06 21:42:19 +02:00
Joffrey JAFFEUX
d75d64bf16
FEATURE: new jump to channel menu (#22383)
This commit replaces two existing screens:
- draft
- channel selection modal

Main features compared to existing solutions
- features are now combined, meaning you can for example create multi users DM
- it will show users with chat disabled
- it shows unread state
- hopefully a better look/feel
- lots of small details and fixes...

Other noticeable fixes
- starting a DM with a user, even from the user card and clicking <kbd>Chat</kbd> will not show a green dot for the target user (or even the channel) until a message is actually sent
- it should almost never do a full page reload anymore

---------

Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
Co-authored-by: Jordan Vidrine <30537603+jordanvidrine@users.noreply.github.com>
Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
Co-authored-by: Mark VanLandingham <markvanlan@gmail.com>
2023-07-05 18:18:27 +02:00
Martin Brennan
3f1024de76
DEV: Refactor DM channel creation into new service pattern (#22144)
This will be used when we move the channel creation for DMs
to happen when we first send a message in a DM channel to avoid
a double-request. For now we can just have a new API endpoint
for creating this that the existing frontend code can use,
that uses the new service pattern.

This also uses the new policy pattern for services where the policy
can be defined in a class so a more dynamic reason for the policy
failing can be sent to the controller.

Co-authored-by: Loïc Guitaut <loic@discourse.org>
2023-07-03 10:18:37 +10:00
Joffrey JAFFEUX
ea0b8ca38c
FEATURE: allows to enable/disable threading in UI (#22307)
Enabling/Disabling threading has been possible through command line until now. This commit introduces two new UIs:

- When creating a channel, it will be available once the category has been selected
- On the settings page of a channel for admins
2023-06-29 07:19:12 +02:00
Roman Rizzi
f4e7a80600
DEV: Cache summarization strategy results. (#22230)
Updates the interface for implementing summarization strategies and adds a cache layer to summarize topics once.

The cache stores the final summary and each chunk used to build it, which will be useful when we have to extend or rebuild it.
2023-06-27 11:44:34 -03:00
Andrei Prigorshnev
3ea31f443c
FEATURE: Export chat messages to CSV file (#22113)
To export chat messages, go to `/admin/plugins/chat` and click the Create export 
button in the _Export chat messages_ section. You'll receive a direct message 
when the export is finished.

Currently, this exports all messages from the last 6 months, but not more than 
10000 messages.

This exports all chat messages, including messages from private channels and 
users' direct conversations. This also exports messages that were deleted.
2023-06-21 16:13:36 +04:00
Jan Cernik
e51bbfa4e8
FEATURE: Scroll to first message when clicking date in chat (#21926)
This PR adds a new parameter to fetch chat messages: `target_date`.

It can be used to fetch messages by a specific date string. Note that it does not need to be the `created_at` date of an existing message, it can be any date. Similar to `target_message_id`, it retrieves an array of past and future messages following the query limits.
2023-06-20 15:58:38 +02:00
Martin Brennan
d6374fdc53
FEATURE: Allow users to manually track threads without replying (#22100)
This commit adds a tracking dropdown to each individual thread, similar to topics,
that allows the user to change the notification level for a thread manually. Previously
the user had to reply to a thread to track it and see unread indicators.

Since the user can now manually track threads, the thread index has also been changed
to only show threads that the user is a member of, rather than threads that they had sent
messages in.

Unread indicators also respect the notification level -- Normal level thread tracking
will not show unread indicators in the UI when new messages are sent in the thread.
2023-06-16 12:08:26 +10:00
Martin Brennan
f75ac9da30
FEATURE: Thread indicator improvements and participants (#21909)
This commit adds the initial part of thread indicator improvements:

* Show the reply count, last reply date and excerpt,
and the participants of the thread's avatars and
count of additional participants
* Add a participants component for the thread that
can be reused for the list
* Add a query class to get the thread participants
* Live update the thread indicator more consistently
with the last reply and participant details
image image

In subsequent PRs we will cache the participants since
they do not change often, and improve the thread list
further with participants.

This commit also adds a showPresence boolean (default
true) to ChatUserAvatar, since we don't want to show the
online indicator for thread participants.

---------

Co-authored-by: chapoi <charlie@discourse.org>
2023-06-15 10:49:27 +10:00
Roman Rizzi
8938ecabc2
FEATURE: Custom content summarization strategies. (#21813)
* FEATURE: Content custom summarization strategies.

This PR establishes a pattern for plugins to register alternative ways of summarizing content by extending a class that defines an interface.

Core controls which strategy we'll use and who has access to it through the `summarization_strategy` and `custom_summarization_allowed_groups`. It also defines the UI for summarizing topics.

Other plugins can access this summarization mechanism and implement their features, removing cross-plugin customizations, as it currently happens between chat and the discourse-ai plugin.

* Group membership validation and rate limiting

* Work with objects instead of classes

* Port summarization feature from discourse-ai to chat

* Rename available summaries to 'Top Replies' and 'Summary'
2023-06-13 14:21:46 -03:00
Joffrey JAFFEUX
111ac4c7f2
FIX: call composer reset with correct params (#21777)
We were calling reset without the proper params which was causing errors in the console. This commit does the following changes:

- ensures `composer.cancel()` is the only way to cancel editing/reply
- adds a `draftSaved` property to chat message to allow for better tests
- writes a spec to ensure the flow is correct
- adds more page objects for better tests
- homogenize the default state of objects on chat message

Co-authored-by: Martin Brennan <martin@discourse.org>
2023-05-30 18:37:30 +02:00
Martin Brennan
6ddd17a756
DEV: Remove old ChatController routes for messages & lookup (#21723)
Since 5cce829 and the new
channel view builder, we have no need of these obsolete
routes which have way too much logic in the controller, which
has been superseded by the view builder anyway.

Remove the routes and update the channel message loading to use it.
2023-05-29 09:37:10 +02:00
Joffrey JAFFEUX
acb4c19eea
PERF: sends publish_new_channel only when not followed (#21755) 2023-05-26 17:13:05 +02:00
Martin Brennan
ae74d5b32e
FIX: Chat deleted last read message and tracking state issues (#21762)
#### FIX: Do not use client lastReadMessageId when fetching channel messages

We had an issue where the following happened:

1. User opened channel and saw the last message, and we set the
   lastReadMessageId on the server and the client
2. User navigated to another channel
3. Another user deleted the message in the original channel
4. The first user navigated back to the original channel before
   the MessageBus event for the deleted message arrived, and got
   a 404 error because we were sending the deleted lastReadMessageId as
   target_message_id to the channel controller.

Instead of this which is a bit flaky and is hard to cover all
the issues for, instead we can pass a fetch_from_last_read boolean
param to the channels controller, and just get the user's
last_read_message_id straight from the database to use for the
target_message_id. This gets rid of any sources of race conditions
or lack of updates from MessageBus.

#### FIX: Include missing memberships for thread tracking publish

When we publish the channel/message tracking state for a
user and that message was a thread reply the publisher
was erroring because we were not telling Chat::TrackingStateReportQuery
to return missing memberships (which have zeroed out unread counts)
as well, which is what we do for the channel tracking state here.
Also just make sure that the TrackingStateReport does not error
when passed an ID it doesn't have data for.
2023-05-26 10:44:27 +02:00
Martin Brennan
c3779a371f
FIX: Serialize thread membership for user (#21743)
This commit follows up b6c5a2da08
by serializing the user's thread memberships in these cases:

1. When we do the initial channel fetch with messages, we get
   all threads and all the user's thread memberships for those
   messages.
2. When the thread list is fetched, we get all the user's memberships
   in that list.
3. When the single thread is fetched, either from opening it from
   the list, an OM indicator, or just from doing .find() on the
   manager when a new MessageBus message comes in

This will let us track the lastReadMessageId on the client, and
will also let us fix an issue where the unread indicator in the
channel header was incrementing for every thread that got a
new message, regardless of whether the user was a member.
2023-05-25 12:54:50 +02:00