Commit Graph

1784 Commits

Author SHA1 Message Date
Penar Musaraj
7776773a11
FIX: Simplify max-height calculation for chat composer (#29822)
In some rare cases, this was causing the input to be invisible. The
change here means the input will have a smaller max height, but since
here we are limiting this to 25% of the viewport height, it should be
more than fine.

It's also not necessary to include the `chat-header-offset`, it ends up
being only a few pixels' difference (since, again, it is divided by 4).
2024-11-19 12:18:05 -05:00
Joffrey JAFFEUX
582de0ffe3
DEV: adds blocks support to chat messages (#29782)
Blocks allow BOTS to augment the capacities of a chat message. At the moment only one block is available: `actions`, accepting only one type of element: `button`.

<img width="708" alt="Screenshot 2024-11-15 at 19 14 02" src="https://github.com/user-attachments/assets/63f32a29-05b1-4f32-9edd-8d8e1007d705">

# Usage

```ruby
Chat::CreateMessage.call(
  params: {
    message: "Welcome!",
    chat_channel_id: 2,
    blocks: [
      {
         type: "actions",
         elements: [
           { value: "foo", type: "button", text: { text: "How can I install themes?", type: "plain_text" } }
         ]
      }
    ]
  },
  guardian: Discourse.system_user.guardian
)
```

# Documentation

## Blocks

### Actions

Holds interactive elements: button.

#### Fields

| Field | Type | Description | Required? |
|--------|--------|--------|--------|
| type | string | For an actions block, type is always `actions` | Yes |
| elements | array | An array of interactive elements, maximum 10 elements | Yes |
| block_id | string | An unique identifier for the block, will be generated if not specified. It has to be unique per message | No |

#### Example

```json
{
  "type": "actions",
  "block_id": "actions_1",
  "elements": [...]
}
```

## Elements

### Button

#### Fields

| Field | Type | Description | Required? |
|--------|--------|--------|--------|
| type | string | For a button, type is always `button` | Yes |
| text | object | A text object holding the type and text. Max 75 characters | Yes |
| value | string | The value returned after the interaction has been validated. Maximum length is 2000 characters | No |
| style | string | Can be `primary` ,  `success` or `danger` | No |
| action_id | string | An unique identifier for the action, will be generated if not specified. It has to be unique per message | No |

#### Example

```json
{
  "type": "actions",
  "block_id": "actions_1",
  "elements": [
    {
      "type": "button",
      "text": {
          "type": "plain_text",
          "text": "Ok"
      },
      "value": "ok",
      "action_id": "button_1"
    }
  ]
}
```

## Interactions

When a user interactions with a button the following flow will happen:

- We send an interaction request to the server
- Server checks if the user can make this interaction
- If the user can make this interaction, the server will:

  * `DiscourseEvent.trigger(:chat_message_interaction, interaction)`
  * return a JSON document
  
  ```json
  {
    "interaction": {
        "user": {
            "id": 1,
            "username": "j.jaffeux"
        },
        "channel": {
            "id": 1,
            "title": "Staff"
        },
        "message": {
            "id": 1,
            "text": "test",
            "user_id": -1
        },
        "action": {
            "text": {
                "text": "How to install themes?",
                "type": "plain_text"
            },
            "type": "button",
            "value": "click_me_123",
            "action_id": "bf4f30b9-de99-4959-b3f5-632a6a1add04"
        }
    }
  }
  ```
  * Fire a `appEvents.trigger("chat:message_interaction", interaction)`
2024-11-19 07:07:58 +01:00
Gary Pendergast
69d9868c7f
FEATURE: Add keyboard shortcuts for jumping to unread channels (#29734) 2024-11-18 11:18:58 +11:00
Sérgio Saquetim
91ce470fce
FIX: Styleguide errors and add smoke test for component pages (#29747) 2024-11-14 15:07:05 -03:00
Régis Hanol
fd1220af69
FIX: chat bookmarks in drawer mode (#29757)
When using chat in drawer mode, after you've clicked on a chat bookmark in the user menu, clicking any other chat bookmark would "do nothing".

In 8b18fd1556 we added an optimization to prevent the same route from being reloaded, but it ended up breaking the bookmarks.

This commit reverts the changed made the above commit and adds a system specs that ensure we can click two chat bookmarks in the user menu when using chat in drawer mode.

Internal ref - t/134362
2024-11-14 17:20:11 +01:00
David Battersby
8dc772f2a8
UX: prevent shrinking unread badge for long DM channel names (#29756)
Fixes a small UX issue where the unread badge gets squashed in long DM channel names.
2024-11-14 15:27:14 +04:00
David Battersby
5ce4af1aa6
FEATURE: add mention count to threads (#29739)
Previously we only counted mentions that were made within channels, however for threads this was never implemented.

This change adds a mention count to the ThreadUnreadsQuery, which is used for channel thread lists and the user thread list. We are also expanding channel mentions count to include mentions within threads.

The goal is to have a more consistent urgent badge across chat, in places such as channel lists and the chat header.
2024-11-14 14:10:12 +04:00
Régis Hanol
fea82d04ec
DEV: fix chat:*:populate rake tasks (#29740) 2024-11-13 18:11:25 +01:00
Régis Hanol
b4156107df
DEV: restore AutoJoinChannelBatch job as a no-op to clear queue (#29743)
The job was removed in 6dfe2fbe16 as part of a performance-related refactor.

The issue was that job was already enqueued in sidekiq and now that the file has been deleted, it's generating a lot of `uninitialized constant Jobs::Chat::AutoJoinChannelBatch` errors.

Restoring this file will help clear the sidekiq queue. We'll remove the job in a few months.

Internal ref - t/141563
2024-11-13 18:10:03 +01:00
Jan Cernik
234133bd3b
UX: Split hide_profile_and_presence user option (#29632)
It splits the hide_profile_and_presence user option and the default_hide_profile_and_presence site setting for more granular control. It keeps the option to hide the profile under /u/username/preferences/interface and adds the presence toggle in the quick user menu.

Co-authored-by: Régis Hanol <regis@hanol.fr>
2024-11-12 22:22:58 -03:00
Loïc Guitaut
d637bd6519
DEV: Don’t replace Rails logger in specs (#29721)
Instead of replacing the Rails logger in specs, we can instead use
`#broadcast_to` which has been introduced in Rails 7.
2024-11-13 08:47:39 +08:00
Discourse Translator Bot
d7503a6153
Update translations (#29715) 2024-11-12 14:54:38 +01:00
David Taylor
fb2a688b29
DEV: Bump eslint, lint-configs, and move to flat config (#29661) 2024-11-12 12:33:17 +00:00
Régis Hanol
6dfe2fbe16
PERF: auto join & leave chat channels (#29193)
Chat channels that are linked to a category can be set to automatically join users.

This is handled by subscribing to the following events

- group_destroyed
- user_seen
- user_confirmed_email
- user_added_to_group
- user_removed_from_group
- category_updated
- site_setting_changed (for `chat_allowed_groups`)

As well as a

- hourly background job (`AutoJoinUsers`)
- `CreateCategoryChannel` service
- `UpdateChannel` service

There was however two issues with the current implementation

1. We were triggering a lot of background jobs, mostly because it was decided to batch to auto join/leave into groups of 1000 users, adding a lot of stress to the system
2. We had one "class" (a service or a background job) per "event" and all of them had slightly different ways to select users to join/leave, making it hard to keep everything in sync

This PR "simply" adds two new servicesL `AutoJoinChannels` and `AutoLeaveChannels` that takes care, in an efficient way, of all the cases when users might automatically join a leave a chat channel.

Every other changes come from the fact that we're now always calling either one of those services, depending on the event that happened.

In the making of these classes, a few bugs were encountered and fixed, notably

- A user is only ever able to access chat channels if and only if they're part of a group listed in the `chat_allowed_group` site setting
- A category that has no associated "category groups" is only accessible to staff members (and not "Everyone")
- A silenced user should not be able to automatically join channels
- We should not attempt to automatically join users to deleted chat channels
- There is no need to automatically join users to chat channels that have already more than `max_chat_auto_joined_users` users

Internal - t/135259 & t/70607

* DEV: add specs for auto join/leave channels services

* DEV: less hacky specs

* DEV: no instance variables in specs
2024-11-12 15:00:59 +11:00
Jarek Radosz
e68905510d
DEV: Use the new hasHtml/includesHtml from qunit-dom (#29680) 2024-11-11 13:06:12 +01:00
Jarek Radosz
2272b1340b
DEV: Use qunit-dom instead of raw href/title comparisons (#29678) 2024-11-11 11:44:54 +01:00
Joffrey JAFFEUX
c4de8565ec
FIX: flakey due to 0 width/height images (#29700)
https://github.com/mainmatter/qunit-dom/blob/master/API.md#isvisible will return true if offsetWidth or offsetHeight are zero which could happen in this case as the test could run before the image has loaded. By forcing a minimum height in the test we ensure it will be consistent.
2024-11-11 17:23:19 +09:00
Jarek Radosz
78ed0bb711
DEV: Use selectors instead of query() where possible (#29677) 2024-11-10 13:53:12 +01:00
Jarek Radosz
d67a6002eb
DEV: Replace count with qunit-dom (#29674) 2024-11-10 02:06:03 +01:00
Jarek Radosz
f9e58938ce
DEV: Update visible/invisible uses to qunit-dom (#29672) 2024-11-10 01:41:50 +01:00
Jarek Radosz
de6d575d40
DEV: Convert all uses of exists to qunit-dom (#29667) 2024-11-10 01:30:33 +01:00
Jarek Radosz
c1916f7984
DEV: Convert assert.true(exists()) to qunit-dom (#29638) 2024-11-08 20:27:32 +01:00
David Battersby
534e8c1628
UX: update chat channel sorting to include unread threads (#29617)
Adds channels with unread threads (watching/tracking) to the sorting logic for both public and direct message channels.

Previously channels with unread threads could easily be missed as we didn't bump them to the top when new thread replies were created.

We are also adding a blue unread badge next to DM channels when there is an unread thread, as previously they weren't appearing as unread within the DMs tab (they only showed within the My Threads section).
2024-11-08 12:31:03 +04:00
Joffrey JAFFEUX
467ecbabf5
FIX: supports escape sequence in chat (#29659)
Writing `\*test\*` will now correctly cook `*test*`, and not `<em>test</em>`.
2024-11-08 15:28:50 +09:00
Joffrey JAFFEUX
032b1f871b
DEV: cook grid bbcode in chat (#29658)
This change will only prevent a cooked message with [grid] to show [grid] instead the content will be wrapped in `div class="d-image-grid"`. This is only enabled on messages made by bot, as regular users could use grid but have no reason to use it ATM. It will also not apply the decoration which shouldn't change the behavior more than just remove grid markup from the message
2024-11-08 14:43:28 +09:00
Joffrey JAFFEUX
1d9f064d83
FIX: correctly account for composer height in PWA (#29656) 2024-11-08 11:16:15 +09:00
Joffrey JAFFEUX
79254c59f9
FIX: correctly render unicode in channel page title (#29653)
Before this fix we would render the emoji as text, eg: `🐱`
2024-11-08 09:41:14 +09:00
Joffrey JAFFEUX
fc5c0270f7
FIX: ensures thread panel closes on escape (#29651)
`chatThreadPane.isOpened` was returning `false` when it should return `true` due to an incorrect matching on the route.

Note that visiting a thread will focus the composer and the first escape will blur the input, only the second will close the panel.
2024-11-08 09:19:24 +09:00
Joffrey JAFFEUX
4840060568
DEV: fix flakey by duplicating constant (#29636)
Some checks are pending
Tests / core frontend (${{ matrix.browser }}) (Firefox ESR) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Firefox Evergreen) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (annotations, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (backend, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (backend, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (frontend, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (frontend, themes) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, chat) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, themes) (push) Waiting to run
Licenses / run (push) Waiting to run
Linting / run (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Chrome) (push) Waiting to run
This is because rules is pointing to the same array MARKDOWN_IT_RULES, which is modified directly. Modifying rules with << changes the original MARKDOWN_IT_RULES array, so every call to something works with the altered array state from previous calls.
2024-11-07 23:51:17 +09:00
Joffrey JAFFEUX
5010fced92
DEV: only supports headings in messages for bots (#29585)
The markdown it rule "heading" will only be used when the message is done by a bot, which means an id < 0.

This commit also adds a is-bot css class on messages made by a bot, for finer control.

---------

Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
2024-11-07 22:27:35 +09:00
Joffrey JAFFEUX
3d1571a852
UX: do not hide topic composer in mobile chat (#29633) 2024-11-07 14:49:59 +09:00
Bianca Nenciu
da43deb9ea
DEV: Fix mismatched column types (#29477)
The primary key is usually a bigint column, but the foreign key columns
are usually of integer type. This can lead to issues when joining these
columns due to mismatched types and different value ranges.

This was using a temporary plugin / test API to make tests pass. After
more careful consideration, we concluded that it is safe to alter the
tables directly.

Even for larger communities, with about 1M chat messages, the
slowest `ALTER` query runs in about 15 seconds, which well under the 30
seconds query timeout limit. As a result, chat messages will be delayed
for a few seconds, but the system will remain operational.
2024-11-06 20:00:40 +02:00
Loïc Guitaut
6158a1ae29 DEV: Refactor the Chat::CreateThread service a bit
Follow best practices from our docs.
2024-11-06 15:53:43 +01:00
Alan Guo Xiang Tan
57f4176b57
DEV: Bump rubocop_discourse (#29608) 2024-11-06 06:27:49 +08:00
Discourse Translator Bot
8a201c1e92
Update translations (#29595) 2024-11-05 16:55:45 +01:00
Martin Brennan
54e7dee6d7
FIX: Chat uploads over-secured in some situations (#29586)
Some checks are pending
Licenses / run (push) Waiting to run
Linting / run (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (annotations, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (backend, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (backend, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (frontend, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (frontend, themes) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, chat) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, themes) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Chrome) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Firefox ESR) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Firefox Evergreen) (push) Waiting to run
In the case where:

* Secure uploads were enabled
* Allow unsecure chat uploads was enabled
* For a site with login required enabled

When a chat upload was created, it was being marked as secure. Since
there is no provision for secure uploads in chat, this would lead to
broken uploads/images shown in the channel.

We can use the "public types" functionality of secure uploads to make
sure we never mark chat uploads as secure, and we can revisit this
whenever we get around to allowing secure uploads in chat.
2024-11-05 15:56:30 +10:00
Jarek Radosz
380974ce00
DEV: Use hasAttribute/hasAria/hasStyle in tests (#29568) 2024-11-04 11:30:38 +01:00
Jarek Radosz
9694d2477a
DEV: Convert more notOk assertions (#29556)
…to either qunit-dom or `strictEqual`
2024-11-04 10:27:30 +01:00
Joffrey JAFFEUX
88eb96b315
DEV: sets an icon_upload_id on a channel (#29566)
There's no UI for it at the moment but when creating a channel or updating it, it's now possible to pass `icon_upload_id` as param. This will be available on the channel as `icon_upload_url`.
2024-11-04 17:19:44 +09:00
Joffrey JAFFEUX
ce76b88eb2
DEV: start/stop reply implementation (#29542)
* DEV: join/leave presence chat-reply when streaming

This commit ensures that starting/stopping a chat message with the streaming option will automatically make the creator of the message as present in the chat-reply channel.

* implements start/stop reply

* not needed
2024-11-04 08:14:35 +11:00
Joffrey JAFFEUX
279fc846db
FEATURE: adds support for headings in chat (#29552)
```
```

Will now be converted into their html versions: <h1>, <h2>, <h3>, ...
2024-11-04 08:11:53 +11:00
Jarek Radosz
b81055a6d4
DEV: Convert more equal assertions (#29554)
…to either qunit-dom or `strictEqual`
2024-11-03 21:04:38 +01:00
Sam
e7f62ab52b
FEATURE: add custom fields to chat (channel/message/thread) (#29504)
This allows various extensions to store extra information the 3 most popular
chat entities

Useful for certain plugins and migrations
2024-11-01 09:12:19 +11:00
Penar Musaraj
041ac3d8b7
DEV: Refactor header offset calculations (#29398) 2024-10-31 09:50:01 -04:00
David Battersby
ec480e99ef
FIX: show chat thread notifications for direct message channels (#29414)
When adding threads to DM channels in #29170 we intentionally didn't add them to the My Threads section. However this makes it easy to miss notifications as we don't get the new thread badge on the sidebar and footer tabs (drawer/mobile). However they were also missing from the chat header and sidebar too, which is fixed with this PR.

When a new thread or a reply to an existing thread is created within a DM channel (either 1:1 or group), we now show the standard badges like we do for public channels.

We now also show the green dot in the sidebar for My Threads and public channels when they contain an unread watched thread.
2024-10-31 10:50:11 +04:00
Osama Sayegh
2ffe413b0b
FEATURE: Enable the new /about page for everyone (#29390)
This commit removes the feature flag for the new /about page, enabling it for all sites, and removes the code for old the /about page.

Internal topic: t/140413.
2024-10-29 18:40:11 +03:00
Loïc Guitaut
2f334964f2 DEV: Remove hash-like access from service contracts
We decided to keep only one way to access values from a contract. This
patch thus removes the hash-like access from contracts.
2024-10-29 16:02:51 +01:00
Discourse Translator Bot
4d0ed2e146
Update translations (#29467) 2024-10-29 15:31:41 +01:00
David Battersby
35f441739c
UX: fix emoji alignment in chat members user status (#29466)
Improves layout of channel members list with user status emojis.
2024-10-29 17:18:09 +04:00
Loïc Guitaut
c78211cf8d DEV: Make service contracts immutable
We decided to make contracts immutable once their validations have run.
Indeed, it doesn’t make a lot of sense to modify a contract value
outside the contract itself.

If processing is needed, then it should happen inside the contract
itself.
2024-10-29 12:23:35 +01:00
David Battersby
7bcd46b87d
DEV: use service worker for chat sound (#29388)
This change makes use of service workers to determine if we should play chat sounds in the current browser tab. Since users can have multiple tabs open, we currently attempt to play sound across all active tabs.

With this change we iterate over all clients and check if client.focused is true (ie. the current tab/window we have open), if so we allow playing the audio in the current tab and for all other hidden tabs/windows we return false.

---------

Co-authored-by: Bianca Nenciu <nbianca@users.noreply.github.com>
2024-10-29 13:15:53 +04:00
David Taylor
aa89acbda6
DEV: Upgrade Uppy to v4 (#29397)
Key changes include:

- `@uppy/aws-s3-multipart` is now part of `@uppy/aws-s3`, and controlled with a boolean

- Some minor changes/renames to Uppy APIs

- Uppy has removed batch signing from their S3 multipart implementation. This commit implements a batching system outside of Uppy to avoid needing one-signing-request-per-part

- Reduces concurrent part uploads to 6, because S3 uses HTTP/1.1 and browsers limit concurrent connections to 6-per-host.

- Upstream drop-target implementation has changed slightly, so we now need `pointer-events: none` on the hover element
2024-10-28 14:01:44 +00:00
Loïc Guitaut
584424594e DEV: Replace params by the contract object in services
This patch replaces the parameters provided to a service through
`params` by the contract object.

That way, it allows better consistency when accessing input params. For
example, if you have a service without a contract, to access a
parameter, you need to use `params[:my_parameter]`. But with a contract,
you do this through `contract.my_parameter`. Now, with this patch,
you’ll be able to access it through `params.my_parameter` or
`params[:my_parameter]`.

Some methods have been added to the contract object to better mimic a
Hash. That way, when accessing/using `params`, you don’t have to think
too much about it:
- `params.my_key` is also accessible through `params[:my_key]`.
- `params.my_key = value` can also be done through `params[:my_key] =
  value`.
- `#slice` and `#merge` are available.
- `#to_hash` has been implemented, so the contract object will be
  automatically cast as a hash by Ruby depending on the context. For
  example, with an AR model, you can do this: `user.update(**params)`.
2024-10-25 14:48:34 +02:00
Loïc Guitaut
41584ab40c DEV: Provide user input to services using params key
Currently in services, we don’t make a distinction between input
parameters, options and dependencies.

This can lead to user input modifying the service behavior, whereas it
was not the developer intention.

This patch addresses the issue by changing how data is provided to
services:
- `params` is now used to hold all data coming from outside (typically
  user input from a controller) and a contract will take its values from
  `params`.
- `options` is a new key to provide options to a service. This typically
  allows changing a service behavior at runtime. It is, of course,
  totally optional.
- `dependencies` is actually anything else provided to the service (like
  `guardian`) and available directly from the context object.

The `service_params` helper in controllers has been updated to reflect
those changes, so most of the existing services didn’t need specific
changes.

The options block has the same DSL as contracts, as it’s also based on
`ActiveModel`. There aren’t any validations, though. Here’s an example:
```ruby
options do
  attribute :allow_changing_hidden, :boolean, default: false
end
```
And here’s an example of how to call a service with the new keys:
```ruby
MyService.call(params: { key1: value1, … }, options: { my_option: true }, guardian:, …)
```
2024-10-25 09:57:59 +02:00
Ella E.
98a3e7d6e2
UX: Consistent styling for admin tables on mobile (#29360)
* UX: Apply admin table classes for consistent mobile styling on custom flags

* UX: Apply admin table classes for consistent mobile styling on custom flags

* UX: Apply admin table classes for consistent mobile styling on backups

* UX: Apply admin table classes for consistent mobile styling on plugins list

* DEV: tweaks on admin table

* UX: Apply admin table classes for consistent mobile styling on chat plugin

* apply prettier

* apply lint

* DEV: removed commented out code

* DEV: removed unnecessary div element

* scroll to the element

* remove the workaround

* revert

* add an extra assertion

* add enabled check

* improve switching

* rm

---------

Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2024-10-23 16:26:21 -06:00
David Taylor
52016e4596
DEV: Update chat-composer-uploads uppy usage (#29339) 2024-10-23 10:07:54 +01:00
Renato Atilio
5d1e67b3e1
DEV: refactor textarea text manipulation mixin (#29294)
Refactor of the TextareaTextManipulation from a Mixin to a native class
2024-10-22 17:20:11 -03:00
Jan Cernik
68539f6084
DEV: More specs for chat excerpts (#29344) 2024-10-22 14:53:42 -03:00
Loïc Guitaut
f79dd5c8b5 DEV: Stop injecting a service result object in the caller object
Currently, when calling a service with its block form, a `#result`
method is automatically created on the caller object. Even if it never
clashed so far, this could happen.

This patch removes that method, and instead use a more classical way of
doing things: the result object is now provided as an argument to the
main block. This means if we need to access the result object in an
outcome block, it will be done like this from now on:
```ruby
MyService.call(params) do |result|
  on_success do
    # do something with the result object
    do_something(result)
  end
end
```

In the same vein, this patch introduces the ability to match keys from
the result object in the outcome blocks, like we already do with step
definitions in a service. For example:
```ruby
on_success do |model:, contract:|
  do_something(model, contract)
end
```
Instead of
```ruby
on_success do
  do_something(result.model, result.contract)
end
```
2024-10-22 16:58:54 +02:00
Discourse Translator Bot
28c5fb94d3
Update translations (#29335) 2024-10-22 22:44:33 +09:00
Jarek Radosz
b9ec9c7e4f
DEV: Update more asserts to qunit-dom (#29326)
regex find&replace + removing now-unused imports + manually fixing incorrect css selectors (that now got flagged 😌) + manually updating selectors that relied on jq
2024-10-22 11:34:23 +02:00
Loïc Guitaut
08e9364573 DEV: Refactor some services from chat
Extracted from https://github.com/discourse/discourse/pull/29129.

This patch makes the code more compliant with the upcoming service docs best practices.
2024-10-21 16:16:25 +02:00
David Battersby
16acba6cf8
DEV: serialize image upload thumbnail (#29276)
Since we recently blocked accidental serialization of AR models, we are getting a 500 error in some cases with thumbnails. We can fix this by serializing the thumbnail, previously we just returned a raw OptimizedImage object.

Thumbnails are now attached to the serializer in core, therefore we no longer need to use add_to_serializer within the chat plugin to use thumbnails within chat message uploads.
2024-10-18 12:55:14 +04:00
Loïc Guitaut
23c486799f DEV: Improve array type in service contracts
This patch improves the custom `array` type available in contracts.
It’s now able to split strings on `|` on top of `,`, and to be more
consistent, it also tries to cast the resulting items to integers.
2024-10-17 17:02:02 +02:00
Loïc Guitaut
af6788fd33 DEV: Extract leave logic to the Chat::Channel model
Extracted from https://github.com/discourse/discourse/pull/29129.
2024-10-17 14:58:45 +02:00
David Taylor
7b8ebebe93
DEV: Fix regression in uppy-mixin (#29252)
This API change was unintentionally introduced in 06d32a8a89

Partially reverts 23d90ecb26, but keeps the new specs.
2024-10-17 10:38:19 +01:00
Loïc Guitaut
93e02069b0 DEV: Don’t provide an array to site settings group lists in specs
This is extracted from https://github.com/discourse/discourse/pull/29129.

In some chat specs, we provide an array as a value for group lists like
`chat_allowed_groups`, which is wrong. This results in a value like
`"1|2|[3]"` instead of `"1|2|3"`.
2024-10-17 11:25:31 +02:00
Joffrey JAFFEUX
23d90ecb26
FIX: _uploadDropTargetOptions is now public (#29246)
Chat was using a private function which has now been made public.

This commit also adds a test for this codepath.
2024-10-17 13:10:01 +09:00
David Battersby
6e6dbde898
DEV: move chat time formats to core locales (#29236)
This change moves the date/time formats to core locales, so that they can be used outside of the plugin.
2024-10-16 20:10:40 +04:00
Loïc Guitaut
76aa9b66d0 DEV: Allow ChatSDK.create to take extra parameters
Currently, `ChatSDK.create` restricts what parameters can be provided to
the underlying service. This prevents the `discourse-ai` plugin from
using it in one of its specs.

This patch allows extra parameters to be provided.
2024-10-16 17:34:01 +02:00
David Battersby
6078fb73ea
UX: consistent chat message date format (#29232)
In certain locales like English (GB), If a user posted 2 subsequent messages, the first would have a date displayed in 24 hour format, while the second message would be shown in 12 hour format (when hovering the message).

This change forces both messages to display in 12 hour format, the first message showing the am/pm, and the second showing the smaller version without am/pm.
2024-10-16 21:51:04 +08:00
David Taylor
06d32a8a89
DEV: Refactor uppy component mixins into standalone classes (#28710)
This commit replaces all uppy-related mixins with standalone classes. The main entrypoint is now lib/uppy/uppy-upload.js, which has a list of its config options listed at the top of the file. Functionality & logic is completely unchanged.

The uppy-upload mixin is replaced with a backwards-compatibility shim, which will allow us to migrate to the new pattern incrementally.
2024-10-16 11:15:19 +01:00
Discourse Translator Bot
e5f2416eff
Update translations (#29212) 2024-10-16 17:52:01 +09:00
Alan Guo Xiang Tan
322a3be2db
DEV: Remove logical OR assignment of constants (#29201)
Constants should always be only assigned once. The logical OR assignment
of a constant is a relic of the past before we used zeitwerk for
autoloading and had bugs where a file could be loaded twice resulting in
constant redefinition warnings.
2024-10-16 10:09:07 +08:00
Jarek Radosz
688f65a39d
DEV: Convert more test assertions to qunit-dom (#29214)
the PR is sponsored by vscode's regex support in find-and-replace 😉
2024-10-15 17:11:20 +02:00
Bianca Nenciu
8016fcab33
DEV: Drop old notification id columns (#28550)
The `id` column of `notifications` table and `notification_id` columns
of the other tables have been migrated to bigint in previous commits
(for example, 799a45a).

In order to run the migrations with zero downtime, the data had to be
copied to new columns and swapped, but the old columns have been kept
to allow for rollback. They are no longer needed now.
2024-10-15 11:58:57 +03:00
chapoi
c1325dbe13
UX: prevent unread indicator from shrinking in flexbox (#29207) 2024-10-15 10:08:45 +02:00
Martin Brennan
6c6cdd96e9
UX: Bump up chat delete messages limit (#29202)
50 is pretty restrictive, let's do 200 for now
2024-10-15 13:15:40 +10:00
David Battersby
492cf52bab
FIX: trashed channel thread view bug (#29192)
When chat channels are deleted, some users may be able to click the thread before it gets removed from the UI. This leads to a 500 error causing log noise. We can use the safe navigational operator to prevent calling chatable when the channel is not found (due to deleted_at constraint in query).
2024-10-14 17:45:50 +04:00
chapoi
1695971523
UX: change thread button in chat nav to use btn-transparent (#29186) 2024-10-14 09:25:27 +02:00
David Battersby
79d2eb5beb
FEATURE: enable threading in chat DM channels (#29170)
Support threads in DMs and group chats so members can keep their conversations organized.

This change adds a new toggle switch for threads within the Chat Channel Settings screen. For new direct message channels threading is enabled by default.

We have made a decision to exclude direct message threads from the My Threads screen for now.
2024-10-11 13:05:07 +04:00
Martin Brennan
2193667e1f
FIX: Plugin JS failing to load would break admin interface (#29139)
If a plugin's JS fails to load for some reason, most commonly
ad blockers, the entire admin interface would break. This is because
we are adding links to the admin routes for plugins that define
them in the sidebar.

We have a fix for this already in the plugin list which shows a warning
to the admin. This fix just prevents the broken link from rendering
in the sidebar if the route is not valid.
2024-10-11 09:26:10 +10:00
Bianca Nenciu
33a4ab13b5
DEV: Set bigint sequences to start at MAX_INT (#28961)
This helps uncover issues with bigint columns that are joined with int
columns. It also introduces a temporary API for plugins to migrate int
columns to bigint in test environment to make tests pass.
2024-10-10 19:28:45 +03:00
chapoi
3c03d9b1e5
UX: chat index flex issues (#29157) 2024-10-10 12:55:08 +02:00
chapoi
d58a2b853f
UX: fix missing text overflow ellipsis in chat index pages (#29150) 2024-10-10 09:57:32 +02:00
Sérgio Saquetim
08d5cf01cd
FIX: Don't override other sidebar panels when opening/closing the chat drawer (#29144)
This commit fixes an issue where the following happens:

1. The user opens a page where an alternative sidebar panel is displayed like /admin or other page where a plugin is displaying an alternative sidebar like the `docs-categories` plugin
2. Clicking the chat icon in the header and opening the drawer, or if you just minimize chat into drawer after it opens full-screen
3. The alternative sidebar panel is lost and reverted to the main panel.
2024-10-09 20:29:19 -03:00
Alan Guo Xiang Tan
ed6c9d1545
DEV: Call Discourse.redis.flushdb after the end of each test (#29117)
There have been too many flaky tests as a result of leaking state in
Redis so it is easier to resolve them by ensuring we flush Redis'
database.

Locally on my machine, calling `Discourse.redis.flushdb` takes around
0.1ms which means this change will have very little impact on test
runtimes.
2024-10-09 07:19:31 +08:00
Discourse Translator Bot
a4531be580
Update translations (#29123) 2024-10-08 20:21:43 +02:00
chapoi
d64d0ddd3d
UX: fix overflow on thread index pages (mobile) (#29126) 2024-10-08 15:27:41 +02:00
Joffrey JAFFEUX
268213a93c
FIX: adds post_quote as placeholder (#29083)
The script `send_chat_message` when used with the `post_created_edited` trigger now accepts `{{post_quote}}` as placeholder for the value of `message`.

This is made possible by a new method in `utils`. Usage:

```ruby
  placeholders["foo"] = utils.build_quote(post)
```
2024-10-08 21:55:11 +09:00
chapoi
0ba7a7ecab
UX: new sidebar styling (#29119) 2024-10-08 11:28:36 +02:00
David Battersby
a7a9148b1e
DEV: consolidate chat channel notification settings (#29080)
On the chat channel settings page, we want to show a single Send push notifications setting instead of the current Desktop notifications and Mobile push notifications settings.

For existing users, use the Mobile push notifications setting value for the new Send push notifications setting.
2024-10-08 13:13:01 +04:00
Loïc Guitaut
229773e7a8 DEV: Drop OpenStruct for the context object in services
While using `OpenStruct` is nice, it’s generally not a very good idea as
it usually leads to performance problems.

The `OpenStruct` source code even says basically to avoid it.

Since the context object is crucial in our services, this patch replaces
`OpenStruct` with a custom implementation instead.
2024-10-08 10:34:55 +02:00
Martin Brennan
85774cc214
UX: Automatically collapse admin page header buttons on mobile (#29040)
This commit attempts to improve the mobile experience for
admin page header and subheader by automatically collapsing
all action buttons in these components into a DMenu when viewing
mobile.

This is done by using different "list" wrapper components and a
DMenu trigger and a DropdownMenu on mobile only, and uses has-block
to determine whether to render the DMenu trigger at all.

This also removes the `PluginOutlet` in `AdminPluginConfigPage`, it
was too inflexible for this `DropdownMenu` case, and since the `:actions`
were always rendering we couldn't rely on `has-block`. A new plugin API,
`registerPluginHeaderActionComponent`, has been introduced instead to
replace it.
2024-10-08 08:28:32 +10:00
Alan Guo Xiang Tan
dc3c94961c
DEV: Fix flaky chat system tests (#29104)
`PageObjects::Pages::ChatThread#has_no_loading_skeleton?` was broken
because `.chat-thread__messages` is no longer a valid class.
2024-10-07 14:20:19 +08:00
chapoi
8d1867688f
UX: add padding bottom to chat index list (#29096) 2024-10-07 07:09:27 +02:00
Jan Cernik
1da97de7f0
SECURITY: Correctly parse URLs in chat excerpts 2024-10-07 11:48:41 +08:00
Penar Musaraj
d959bfdc61
UX: Improve bottom padding to chat index on mobile (#29086)
Minor adjustment to #29082
2024-10-04 11:33:38 -04:00
chapoi
c13ca6eb19
UX: chat index mini refactor (#29082) 2024-10-04 08:10:36 -04:00
David Battersby
9eaf908e63
DEV: cleanup chat desktop notification data (#28943)
Makes channel_id and is_direct_message_channel consistent across desktop notifications, which also removes the need to lookup the channel from Chat Notification Manager.
2024-10-03 12:43:17 +04:00