Commit Graph

341 Commits

Author SHA1 Message Date
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
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
Jarek Radosz
89bd2b7df0
DEV: Remove unnecessary js: true options from specs (#24463) 2023-11-20 17:22:14 +01:00
Joffrey JAFFEUX
2b7ecee06e
FIX: correctly highlights message on reply click (#24431) 2023-11-17 18:05:38 +01:00
chapoi
f72899401d
UX: refactor .d-modal to use BEM and improve styling (#23967)
This PR refactors the following:
* leaving all the CSS applied to the old `modal-body` classes in their respective files
* made  new clean styling for `.d-modal` and refactored the template to use the new BEM classes
  * `inner-`, `middle-`, `outer-` container classes are gone and replaced with simplified `wrapper` and `container` classes  
  * use standardised max-sizes with modifiers `-large` and `-max`
  * lighter backdrop,
  * min-width to prevent puny modals
  * other styling changes regarding padding, close button,…
* pulled out all modal overrides into a general `modal-overrides` file + cleanup of outdated CSS
* pulled out login and create account modal styling into their own file, cause it's such a big override 
* removed old general login.scss file for mobile & desktop
* only kept some remainders I don't want to touch in `app/assets/stylesheets/common/base/login.scss`
2023-11-15 10:14:47 +00:00
Joffrey JAFFEUX
a0769f6f43
UX: improves search of message creator
- correctly show unread indicator
- handles disabled user correctly
- do not show new-group-chat when filtering
2023-11-13 22:03:47 +01:00
Kris
797da5870b
FEATURE: remove category badge style options, set bullet style as default (#24198) 2023-11-13 10:46:15 -05: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
Daniel Waterworth
6e161d3e75
DEV: Allow fab! without block (#24314)
The most common thing that we do with fab! is:

    fab!(:thing) { Fabricate(:thing) }

This commit adds a shorthand for this which is just simply:

    fab!(:thing)

i.e. If you omit the block, then, by default, you'll get a `Fabricate`d object using the fabricator of the same name.
2023-11-09 16:47:59 -06:00
Joffrey JAFFEUX
039d060832
DEV: improves reliability of delete/restore/update specs (#24265) 2023-11-07 11:34:35 +01:00
David Battersby
f20b6a0cc3
FEATURE: chat redesign - back button to exit threads (#24189)
Chat redesign work to improve chat navigation:

- New header title with channel name (thread list on mobile)
- New header title without channel name (thread list on full page chat)
- Removes the close button on threads (mobile only)
- Updates to back button route within thread (mobile), taking user to:
    - The thread index, if they accessed the thread from the thread index.
    - The channel itself, if they accessed the thread directly from the channel.
    - The channel itself, if they accessed the thread from a notification.
- Show thread title in chat drawer header
- Properly convert emoji in thread titles in chat header (all devices)
- Upgrades various templates to use gjs format.
2023-11-07 16:01:09 +08:00
Joffrey JAFFEUX
2797e0478e
FIX: target chat-message-text only on secondary action (#24255)
This is not necessary for other cases and was breaking specs. This commit also avoids using chat service when not necessary.
2023-11-07 00:45:13 +01:00
Joffrey JAFFEUX
2bd4cf69d0
FIX: targeting chat-message-text is more reliable (#24245) 2023-11-07 00:05:53 +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
David Battersby
65759c126b
FIX: add dominant color attribute to chat image uploads (#24214)
When uploading images, they are assigned a dominant color which gets used in various places, such as Discourse Hub and the new lightbox. Previously in chat we didn't assign this attribute, so it was defaulting to a null value. We did however use it as an inline CSS style for the image background (which is visible while the image is downloaded).

This change adds data-dominant-color to the uploaded image in chat and uses it correctly within lightbox.
2023-11-02 19:22:59 +08:00
David Battersby
8465324168
FEATURE: Add new chat indicator preference for Only Mentions (#23848)
Add new chat indicator preference within chat user preferences.

Enabling this option will mean that green notifications will only appear for mentions (within channels and DMs.

This change also enables mentions within direct messages.
2023-10-27 15:58:19 +08: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
7c057878e2
DEV: skips two flakey specs (#24044) 2023-10-22 18:50:04 +02:00
Joffrey JAFFEUX
b6d9aa5a4c
DEV: simplify reply to message smoke spec (#23928)
We now create threads on reply so the refresh check is not really necessary as there's nothing special about it anymore. We don't refresh every pages in other tests to check they still work.

Hopefully these changes will prevent few flakeys too.
2023-10-13 11:16:26 +02:00
Joffrey JAFFEUX
b122e69ed3
DEV: flakey members list spec (#23917)
No repro but, it's possible that we were at the limit of triggering the scroll, this should ensure we correctly trigger the scroll more.
2023-10-12 22:32:03 +02:00
Joffrey JAFFEUX
b77b0ee1c8
UX: opens thread on channel with unread threads (#23361)
When visiting a channel which has unread threads, we will now open the threads list panel.

Note that:

mobile
linking to message
linking to a thread

Won't open the threads list.
2023-10-11 12:19:30 +02:00
Joffrey JAFFEUX
a39ff830e8
UX: makes avatar non interactive in thread participants list (#23847)
It was slightly surprising to have a user card show when click on a thread item list.

More over this commit does:
- moves chat/user-avatar to chat-user-avatar and converts it to gjs
- moves chat/thread/participants to chat-thread-participants
- rewrite the `toggleCheckIfPossible` modifier to only be applied when selecting messages, it prevents the click event to collide with the click of avatars in regular messages
2023-10-09 21:12:50 +02:00
Joffrey JAFFEUX
42801c950f
UI: redesigned settings/members (#23804)
This PR is a first step towards private groups. It redesigns settings/members area of a channel and also drops the "about" page which is now mixed into settings.

This commit is also:
- introducing chat-form, a small DSL to create forms, ideally I would want something in core for this
- introducing a DToggleSwitch page object component to simplify testing toggles
- migrating various components to gjs
2023-10-09 14:11:16 +02:00
Joffrey JAFFEUX
c970cbeac4
DEV: ensures thread panel has been opened (#23836)
I don't have a repro of this ATM, but I suspect that ensuring the panel has been opened before moving to next tests could make this test more resilient.
2023-10-09 09:30:18 +02:00
Alan Guo Xiang Tan
832b3b9e60
FEATURE: Remove support for legacy navigation menu (#23752)
Why this change?

Back in May 17 2023 along with the release of Discourse 3.1, we announced
on meta that the legacy hamburger dropdown navigation menu is
deprecated and will be dropped in Discourse 3.2. This is the link to the announcement
on meta: https://meta.discourse.org/t/removing-the-legacy-hamburger-navigation-menu-option/265274

## What does this change do?

This change removes the `legacy` option from the `navigation_menu` site
setting and migrates existing sites on the `legacy` option to the
`header dropdown` option.

All references to the `legacy` option in code and tests have been
removed as well.
2023-10-09 07:24:10 +08:00
Joffrey JAFFEUX
b4c4f01b84
DEV: skip mobile copy link spec (#23805)
Most likely on CI sometimes it makes a press instead of a long press because there's a thread preview underneath.
2023-10-05 21:50:19 +02:00
Jarek Radosz
1251757d48
DEV: Fix random typos (#23801)
Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
2023-10-05 20:40:53 +02:00
Joffrey JAFFEUX
6cd4b8de6d
FIX: long press chat message test failure (#23791)
This commit brings two fixes.

- increase the delay to trigger the action menu

- check of user activation before using vibrate:

https://developer.mozilla.org/en-US/docs/Glossary/Sticky_activation
https://developer.mozilla.org/en-US/docs/Web/Security/User_activation
https://developer.mozilla.org/en-US/docs/Web/API/UserActivation/hasBeenActive

> Sticky activation is a window state that indicates a user has pressed a button, moved a mouse, used a menu, or performed some other user interaction. It is not reset after it has been set initially (unlike transient activation).
> APIs that require sticky activation (not exhaustive):
> - Navigator.vibrate()
> - VirtualKeyboard.show()
> - Autoplay of Media and Web Audio APIs (in particular for AudioContexts).


Before this fix, we could end up with this error in the console in tests:

> Blocked call to navigator.vibrate because user hasn't tapped on the frame or any embedded 

<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
2023-10-05 10:16:13 +02:00
Joffrey JAFFEUX
08df8fc1d1
UX: enhances chat copy features (#23770)
- Allows to copy quotes from mobile
- Allows to copy text of a message from mobile
- Allows to select messages by clicking on it when selection has started

Note this commit is also now using toasts to show a confirmation of copy, and refactors system specs helpers concerning secondary actions.

<!-- NOTE: All pull requests should have tests (rspec in Ruby, qunit in JavaScript). If your code does not include test coverage, please include an explanation of why it was omitted. -->
2023-10-04 16:14:37 +02:00
Joffrey JAFFEUX
2a10ea0e3f
DEV: FloatKit (#23650)
This PR introduces three new concepts to Discourse codebase through an addon called "FloatKit":

- menu
- tooltip
- toast


## Tooltips
### Component

Simple cases can be express with an API similar to DButton:

```hbs
<DTooltip 
  @Label={{i18n "foo.bar"}}
  @ICON="check"
  @content="Something"
/>
```

More complex cases can use blocks:

```hbs
<DTooltip>
  <:trigger>
   {{d-icon "check"}}
   <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
   Something
  </:content>
</DTooltip>
```

### Service

You can manually show a tooltip using the `tooltip` service:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  options
)

// and later manual close or destroy it
tooltipInstance.close();
tooltipInstance.destroy();

// you can also just close any open tooltip through the service
this.tooltip.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const tooltipInstance = this.tooltip.register(
  document.querySelector(".my-span"),
  options
)

// when done you can destroy the instance to remove the listeners
tooltipInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  { 
    component: MyComponent,
    data: { foo: 1 }
  }
)
```

## Menus

Menus are very similar to tooltips and provide the same kind of APIs:

### Component

```hbs
<DMenu @ICON="plus" @Label={{i18n "foo.bar"}}>
  <ul>
    <li>Foo</li>
    <li>Bat</li>
    <li>Baz</li>
  </ul>
</DMenu>
```

They also support blocks:

```hbs
<DMenu>
  <:trigger>
    {{d-icon "plus"}}
    <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
    <ul>
      <li>Foo</li>
      <li>Bat</li>
      <li>Baz</li>
    </ul>
  </:content>
</DMenu>
```

### Service

You can manually show a menu using the `menu` service:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  options
)

// and later manual close or destroy it
menuInstance.close();
menuInstance.destroy();

// you can also just close any open tooltip through the service
this.menu.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const menuInstance = this.menu.register(
   document.querySelector(".my-span"),
   options
)

// when done you can destroy the instance to remove the listeners
menuInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  { 
    component: MyComponent,
    data: { foo: 1 }
  }
)
```


## Toasts

Interacting with toasts is made only through the `toasts` service.

A default component is provided (DDefaultToast) and can be used through dedicated service methods:

- this.toasts.success({ ... });
- this.toasts.warning({ ... });
- this.toasts.info({ ... });
- this.toasts.error({ ... });
- this.toasts.default({ ... });

```javascript
this.toasts.success({
  data: {
    title: "Foo",
    message: "Bar",
    actions: [
      {
        label: "Ok",
        class: "btn-primary",
        action: (componentArgs) => {
          // eslint-disable-next-line no-alert
          alert("Closing toast:" + componentArgs.data.title);
          componentArgs.close();
        },
      }
    ]
  },
});
```

You can also provide your own component:

```javascript
this.toasts.show(MyComponent, {
  autoClose: false,
  class: "foo",
  data: { baz: 1 },
})
```

Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
Co-authored-by: David Taylor <david@taylorhq.com>
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2023-09-26 13:39:52 +02:00
Alan Guo Xiang Tan
e2c7ecfe65
DEV: Change PageObjects::Components::Chat::Message#exists? to exact match (#23660)
Why this change?

Before this change, we were doing a partial match when checking for
existence. This is a source of flaky tests because a chat message with
text `this is a message` will match any substring like `message` or `a`.

What does this change do?

This change removes the partial match and instead opts for the
`exact_text` option instead.
2023-09-26 10:20:21 +08:00
Joffrey JAFFEUX
92839dc722
FIX: ensures an empty last message won't cause errors (#23647)
This would cause an error when deleting the original message of a thread, due to the non existing `last_message`. This fix is implemented using the null pattern.

Note this commit is also using this opportunity to unify naming of null objects, `Chat::DeletedUser` becomes `Chat::NullUser`, it feels better to have a name describing what is the object, instead of a name describing why this object has to be used, which can change depending on cases.
2023-09-25 12:43:04 +02:00
Joffrey JAFFEUX
85fddf58bc
Revert "DEV: FloatKit (#23541)" (#23549)
This reverts commits

0623ac684a
408e71e437
a32fa3b947

User tips were running into some issues.
2023-09-12 13:55:12 -04:00
Joffrey JAFFEUX
0623ac684a
DEV: FloatKit (#23541)
Second iteration of https://github.com/discourse/discourse/pull/23312 with a fix for embroider not resolving an export file using .gjs extension.

---

This PR introduces three new concepts to Discourse codebase through an addon called "FloatKit":

- menu
- tooltip
- toast


## Tooltips
### Component

Simple cases can be express with an API similar to DButton:

```hbs
<DTooltip 
  @label={{i18n "foo.bar"}}
  @icon="check"
  @content="Something"
/>
```

More complex cases can use blocks:

```hbs
<DTooltip>
  <:trigger>
   {{d-icon "check"}}
   <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
   Something
  </:content>
</DTooltip>
```

### Service

You can manually show a tooltip using the `tooltip` service:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  options
)

// and later manual close or destroy it
tooltipInstance.close();
tooltipInstance.destroy();

// you can also just close any open tooltip through the service
this.tooltip.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const tooltipInstance = this.tooltip.register(
  document.querySelector(".my-span"),
  options
)

// when done you can destroy the instance to remove the listeners
tooltipInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  { 
    component: MyComponent,
    data: { foo: 1 }
  }
)
```

## Menus

Menus are very similar to tooltips and provide the same kind of APIs:

### Component

```hbs
<DMenu @icon="plus" @label={{i18n "foo.bar"}}>
  <ul>
    <li>Foo</li>
    <li>Bat</li>
    <li>Baz</li>
  </ul>
</DMenu>
```

They also support blocks:

```hbs
<DMenu>
  <:trigger>
    {{d-icon "plus"}}
    <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
    <ul>
      <li>Foo</li>
      <li>Bat</li>
      <li>Baz</li>
    </ul>
  </:content>
</DMenu>
```

### Service

You can manually show a menu using the `menu` service:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  options
)

// and later manual close or destroy it
menuInstance.close();
menuInstance.destroy();

// you can also just close any open tooltip through the service
this.menu.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const menuInstance = this.menu.register(
   document.querySelector(".my-span"),
   options
)

// when done you can destroy the instance to remove the listeners
menuInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  { 
    component: MyComponent,
    data: { foo: 1 }
  }
)
```


## Toasts

Interacting with toasts is made only through the `toasts` service.

A default component is provided (DDefaultToast) and can be used through dedicated service methods:

- this.toasts.success({ ... });
- this.toasts.warning({ ... });
- this.toasts.info({ ... });
- this.toasts.error({ ... });
- this.toasts.default({ ... });

```javascript
this.toasts.success({
  data: {
    title: "Foo",
    message: "Bar",
    actions: [
      {
        label: "Ok",
        class: "btn-primary",
        action: (componentArgs) => {
          // eslint-disable-next-line no-alert
          alert("Closing toast:" + componentArgs.data.title);
          componentArgs.close();
        },
      }
    ]
  },
});
```

You can also provide your own component:

```javascript
this.toasts.show(MyComponent, {
  autoClose: false,
  class: "foo",
  data: { baz: 1 },
})
```

Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
Co-authored-by: David Taylor <david@taylorhq.com>
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2023-09-12 15:50:26 +02:00
Joffrey JAFFEUX
b8cc1072cc
Revert "DEV: FloatKit (#23312)" (#23540)
This reverts commit abcdd8d367.
2023-09-12 15:37:16 +02:00
Joffrey JAFFEUX
abcdd8d367
DEV: FloatKit (#23312)
This PR introduces three new UI elements to Discourse codebase through an addon called "FloatKit":

- menu
- tooltip
- toast

Simple cases can be express with an API similar to DButton:

```hbs
<DTooltip
  @label={{i18n "foo.bar"}}
  @icon="check"
  @content="Something"
/>
```

More complex cases can use blocks:

```hbs
<DTooltip>
  <:trigger>
   {{d-icon "check"}}
   <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
   Something
  </:content>
</DTooltip>
```

You can manually show a tooltip using the `tooltip` service:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  options
)

// and later manually close or destroy it
tooltipInstance.close();
tooltipInstance.destroy();

// you can also just close any open tooltip through the service
this.tooltip.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const tooltipInstance = this.tooltip.register(
  document.querySelector(".my-span"),
  options
)

// when done you can destroy the instance to remove the listeners
tooltipInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  {
    component: MyComponent,
    data: { foo: 1 }
  }
)
```

Menus are very similar to tooltips and provide the same kind of APIs:

```hbs
<DMenu @icon="plus" @label={{i18n "foo.bar"}}>
  <ul>
    <li>Foo</li>
    <li>Bat</li>
    <li>Baz</li>
  </ul>
</DMenu>
```

They also support blocks:

```hbs
<DMenu>
  <:trigger>
    {{d-icon "plus"}}
    <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
    <ul>
      <li>Foo</li>
      <li>Bat</li>
      <li>Baz</li>
    </ul>
  </:content>
</DMenu>
```

You can manually show a menu using the `menu` service:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  options
)

// and later manually close or destroy it
menuInstance.close();
menuInstance.destroy();

// you can also just close any open tooltip through the service
this.menu.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const menuInstance = this.menu.register(
   document.querySelector(".my-span"),
   options
)

// when done you can destroy the instance to remove the listeners
menuInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  {
    component: MyComponent,
    data: { foo: 1 }
  }
)
```

Interacting with toasts is made only through the `toasts` service.

A default component is provided (DDefaultToast) and can be used through dedicated service methods:

- this.toasts.success({ ... });
- this.toasts.warning({ ... });
- this.toasts.info({ ... });
- this.toasts.error({ ... });
- this.toasts.default({ ... });

```javascript
this.toasts.success({
  data: {
    title: "Foo",
    message: "Bar",
    actions: [
      {
        label: "Ok",
        class: "btn-primary",
        action: (componentArgs) => {
          // eslint-disable-next-line no-alert
          alert("Closing toast:" + componentArgs.data.title);
          componentArgs.close();
        },
      }
    ]
  },
});
```

You can also provide your own component:

```javascript
this.toasts.show(MyComponent, {
  autoClose: false,
  class: "foo",
  data: { baz: 1 },
})
```

Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
Co-authored-by: David Taylor <david@taylorhq.com>
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2023-09-12 15:06:51 +02:00
Jan Cernik
d9a2595e7c
FIX: Prevent chat message actions to disappear on mouseleave (#23063) 2023-09-11 16:54:01 -03:00
Joffrey JAFFEUX
b8d5f951f6
UX: implements swipe on row channel (#23436)
On mobile swiping a channel row will now show a "Remove" option. Holding this to the end will now remove this row from your list of followed direct message channels.

Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
2023-09-11 14:51:13 +02:00
Mark VanLandingham
9c65e2140a
DEV: Use Notice API for mention warnings (#23238)
This PR swaps out the custom pathway to publishing and rendering mention warnings after a message is sent.

ChatPublisher#publish_notice is used, and expanded. Now, instead of only accepting text_content as an argument, component and component_args are accepted and there is a renderer for these components.

Translations moved to server, as notices expect text to be passed in unless a component is rendered

The warnings are rendered at the top now, outside of the scope of the single message that sent it.

I entirely removed the jit_messages_spec b/c it's duplicate testing of other parts of the app. IMO we don't need a backend test for a feature, a component test for the feature AND a system test (that is slow and potentially even flakey due to timing issues with wait) to test the same thing. So jit_messages_spec is gone.
2023-09-01 09:07:23 -05:00
chapoi
c9c2a73441
UX: thread list design changes (#23348) 2023-08-31 18:09:41 +02:00
Loïc Guitaut
e1ae32103d DEV: Refactor chat specs related to message creation
This is extracted from #22390.

This patch aims to ease the transition to the new message creation
service. (in progress in #22390) Indeed, the new service patch is
breaking some specs from `discourse-ai` and `discourse-templates`
because these plugins are using either `Chat::MessageCreator` or the
`chat_message` fabricator.

This patch addresses theses issues by normalizing how we create a chat
message in specs. To do so, the preferred way is to use
`Fabricate(:chat_message)` with a new `:use_service` option allowing to
call the service under the hood. While this patch will obviously call
`Chat::MessageCreator`, the new service patch will now be able to simply
change the call to `Chat::CreateMessage` without breaking any specs from
other plugins.

Another thing this patch does is to not create chat messages using the
service for specs that aren’t system ones, thus speeding the execution
time a bit in the process.
2023-08-31 11:21:23 +02:00
Martin Brennan
64a4390e17
DEV: Fix flaky network-based upload spec (#23286)
Tries to fix the composer upload spec by making the upload
slow enough to allow clicking the Cancel button, and improves
generally the API for CDP network changes.
2023-08-28 12:59:22 +08:00
Joffrey JAFFEUX
c5ac500181
UX: minor tweaks to thread list item (#23259)
- drop @
- prevents +X  (participants) to show on next line
- few spacing/fonts adjustments

Note that this commit is also stripping links from chat excerpts.
2023-08-25 11:20:03 +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
46c7e47f50
FIX: prevents setPanel to also set separated mode (#23227)
This could happen after you had already change the separation mode and would cause unexpected bugs.

This PR also adds more tests around using switch buttons with chat.
2023-08-24 18:21:28 +02:00
Joffrey JAFFEUX
fc93604b9e
FIX: correctly resets editing state when done (#23209)
Prior to this fix, attempting to reply to a recently edited message would show the edit icon instead of the reply icon.
2023-08-24 09:41:37 +02:00
Joffrey JAFFEUX
fef0225a22
FIX: correctly check chat tab is present (#23200)
Prior to this fix we would test by visiting the tab which could create a false positive, as the tab could not be present but we could still access the tab, the implementation and tests have been changed to correctly ensure this.
2023-08-23 13:06:29 +02:00
Joffrey JAFFEUX
a008f61f8f
FIX: correctly closes panel when exiting chat (#23201)
We don't use activate/deactivate as it would cause: close/open in short succession when going from threads to thread for example.
2023-08-23 13:05:15 +02:00
Mark VanLandingham
68eba53e09
FEATURE: Chat global mention warnings (pre-send & post-send) (#22764)
This is also fixes the issue of chat composer warnings persisting across channels. Currently if you try to mention more groups than is allowed for example, a mention warning pops up. When you change channels the mention warning will not disappear even if there is no text in the composer.

This adds a reset function to the chat-composer-warnings-tracker.js, which is called when the channel is changed and the message is empty. In the event that the message is not empty we call captureMentions to check the loaded drafts' mentions.

This PR would be nicer if the post-send notice used the new chat notices API to publish the mention warnings but we would have to change the existing ones and I thought that would be too much change for this PR. It'd be a good followup though.
2023-08-22 15:54:35 -05:00