Commit Graph

431 Commits

Author SHA1 Message Date
David Battersby e944468162
FIX: chat channel row indicator should only show urgent count (#25458)
Correctly shows the number of urgent notifications in channel list, rather than showing all new notifications as urgent.
2024-01-31 16:47:54 +08:00
Jan Cernik 8654757581
FIX: Hide 'My Threads' if no followed channels have threads (#25470)
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2024-01-30 10:53:32 -03:00
David Battersby 6b3a68e562
FEATURE: Mobile Chat Notification Badges (#25438)
This change adds notification badges to the new footer tabs on mobile chat, to help users easily find areas where there’s new activity to review.

When on mobile chat:
- Show a badge on the DMs footer when there is unread activity in DMs.
- Show a badge on the Channels footer tab when there is unread channel activity.
- Show a badge on the Threads footer tab when there is unread activity in a followed thread.
- Notification badges should be removed once the unread activity is viewed.

Additionally this change will:
- Show green notification badges for channel mentions or DMs
- Show blue notification badges for unread messages in channels or threads

Co-authored-by: chapoi <101828855+chapoi@users.noreply.github.com>
2024-01-29 10:38:14 +08:00
Joffrey JAFFEUX 7b173e883f
FEATURE: display last message on mobile (#25384)
Direct messages on mobile will now display the last message in the channels list.
2024-01-25 15:30:21 +01:00
Joffrey JAFFEUX a3c1fff65a
DEV: removes flakey spec (#25405)
scroll position is not reliable enough
2024-01-24 18:56:50 +01:00
David Battersby 85d74ec8bf
DEV: remove pseudo-class selector in chat channel page object (#25399)
The channels-list div is only rendered once now so the :first-child pseudo-class can be removed.
2024-01-24 12:24:40 +08:00
David Battersby 67244a2318
FIX: use site setting to show my threads chat footer tab (#25277)
Fixes an issue with delayed rendering of the My Threads tab in chat mobile footer.

Previously we made an ajax request to determine the number of threads a user had before rendering the tab, however it is much faster (and better UX) if we can rely on a site setting for this.

The new chat_threads_enabled site setting is set to true when the site has chat channels with threading enabled.
2024-01-23 19:14:46 +08:00
Joffrey JAFFEUX aee7197c43
FIX: correctly save scroll position in channel (#25345)
Due to an incorrect test the previous service was incorrectly implementing the map, and was most importantly not deleting the state when reaching bottom.
2024-01-19 22:49:14 +01:00
Joffrey JAFFEUX 9365d8b544
FEATURE: save/retrieve scroll position in chat channel (#25336)
Note this is only saved on each tab session.
2024-01-19 16:34:11 +01:00
Joffrey JAFFEUX 2014f1a0b7
FEATURE: implements dates separators for threads (#25335)
This commit creates a shared implementation of the dates computation and moves all the logic (new messages since last visit and dates separator into one single component <ChatMessageSeparator />).

The frontend tests have been removed and only a single system spec has been added for threads as everything is sharing the same implementation and the existing channel specs should catch any regression.
2024-01-19 16:21:48 +01:00
Jan Cernik f4e51e0789
FEATURE: Allow users to DM groups in chat (#25189)
Allows users to create DMs by selecting groups as a target. It also allows adding user groups to an existing chat

- When creating the channel, it expands the user group and adds all its members with chat enabled to the channel.
- After creation, there's no difference between adding a group or adding its members individually.
- Users can add multiple groups and users simultaneously.
- There are UI validations; the member count preview updates according to the member count of added groups, and it does not allow users to add more members than SiteSetting.chat_max_direct_message_users."
2024-01-19 11:09:47 -03:00
Andrei Prigorshnev 62f423da15
DEV: Redesign chat mentions (#24752)
At the moment, when someone is mentioning a group, or using here or 
all mention, we create a chat_mention record per user. What we want 
instead is to have special kinds of mentions, so we can create only one 
chat_mention record in such cases. This PR implements that.

Note, that such mentions will still have N related notifications, one 
notification per a user. We don't expect we'll have performance 
problems on the notifications side, but if at some point we do, we 
should be able to solve them on the side of notifications 
(notifications are handled in jobs, also some little delays with 
the notifications are acceptable, so we can make sure notifications 
are properly queued, and that processing of every notification is 
fast enough to make delays small enough).

The preparation work for this PR was done in fbd24fa, where we make 
it possible for one mention to have several related notifications.

A pretty tricky part of this PR is schema and data migration, I've explained 
related details inline on the migration files.
2024-01-17 15:24:01 +04:00
David Battersby 6876c52857
FIX: set channels tab as default on mobile chat footer (#25296)
This change moves the "Channels" tab to first position in the chat footer nav, and loads it as the default page when opening chat for the first time on mobile.
2024-01-17 17:12:55 +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
Martin Brennan 8c6144d116
DEV: Change enable_admin_sidebar_navigation to group setting (#25159)
This will make it easier to do more focused
testing of this change.
2024-01-09 09:06:27 +10:00
Jan Cernik 117611ea82
FIX: 500 error when reviewable has a missing message (#25113) 2024-01-03 11:49:54 -03:00
David Battersby 406f4c9e80
DEV: fix flaky back to forum spec (#25071)
Fixes a flaky test by ensuring Capybara finishes loading the topic page before attempting to open chat. The back to forum url relies on a tracked property (previous url), which is set when visiting the topic page.
2023-12-29 16:55:12 +08:00
Alan Guo Xiang Tan ea910e291b
DEV: Remove assertion causing test to be flaky (#25069)
Why this change?

The assertion does not make use of Capybara's waiting strategy and is
not really testing anything meaningful by asserting for the src of the
img element.
2023-12-29 13:23:16 +08:00
Alan Guo Xiang Tan 655c106101
DEV: Capture and log AR debug logs on GitHub actions for flaky tests (#25048)
Why this change?

We have been running into flaky tests which seems to be related to
AR transaction problems. However, we are not able to reproduce this
locally and do not have sufficient information on our builds now to
debug the problem.

What does this change do?

Noe the following changes only applies when `ENV["GITHUB_ACTIONS"]` is
present.

This change introduces an RSpec around hook when `capture_log: true` has
been set for a test. The responsibility of the hook is to capture the
ActiveRecord debug logs and print them out.
2023-12-27 14:40:00 +08:00
David Battersby 67d736a045
FEATURE: chat header redesign on mobile (#24938)
This change simplifies the layout of our header when chat is open on mobile. The search icon and hamburger menu icons are also hidden and the Discourse logo is replaced by a ← Forum link to make it easier to continue where you left off within the forum (prior to this update the user could only go back to the forum index page).
2023-12-26 17:36:26 +08:00
Martin Brennan 7fcef5f2f9
FIX: Show admin plugin route sub-links in sidebar (#24982)
This changes the Plugins link in the admin sidebar to
be a section instead, which then shows all enabled plugin
admin routes (which are custom routes some plugins e.g.
chat define).

This is done via adding some special preloaded data for
all controllers based on AdminController, and also specifically
on Admin::PluginsController, to have the routes loaded without
additional requests on page load.

We just use a cog for all the route icons for now...we don't
have anything better.
2023-12-21 11:37:20 +10:00
Alan Guo Xiang Tan 68a3f7783e
DEV: Remove the use of `Capybara::Session#quit` (#24978)
Why this change?

This is what `Capybara::Session#quit` does:

```
    def quit
      @driver.quit if @driver.respond_to? :quit
      @document = @driver = nil
      @touched = false
      @server&.reset_error!
    end
```

One notable thing is that it resets server errors which means that any
server errors encountered by a session is cleared. That is not what we
want since it hides errors even though `Capybara.raise_server_errors`
has been set to `true`.
2023-12-20 13:20:14 +08:00
chapoi 70f0cb610a
UX: Chat info area back button + styling tweaks (#24966)
## Back button to navigate out of add-member area

Currently on mobile, once you're in the member area, there is no easy to return to the general settings area, except exiting the settings altogether, which isn't very user friendly. A go-back link solves the problem.

## Styling tweaks

* Removed the background from the leave button
* Added more spacing between the sections on desktop and removed the fixed height for rows

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2023-12-19 16:28:07 +01:00
Joffrey JAFFEUX c467af97ac
DEV: skip two flakey specs (#24965) 2023-12-19 09:27:09 +01:00
chapoi dce5e811ef
UX: chat channel info area > classname changes (#24954) 2023-12-18 22:09:47 +01:00
Joffrey JAFFEUX 53b96638c5
DEV: implements <Chat::Navbar /> (#24917)
This new navbar component is used for every navbar in chat, full page or drawer, and any screen.

This commit also uses this opportunity to correctly decouple drawer-routes from full page routes. This will avoid having this kind of properties in components: `@includeHeader={{false}}`. The header is now defined in the parent template using a navbar. Each route has now its own template wrapped in a div of the name of the route, eg: `<div class="c-routes-threads">..</div>`.

The navbar API:

```gjs
<Navbar as |navbar|>
 <navbar.BackButton />
 <navbar.Title @title="Foo" />
 <navbar.ChannelTitle @channel={{@channel}} />
 <navbar.Actions as |action|>
   <action.CloseThreadButton />
 </navbar.Actions>
</navbar>
```

The full list of components is listed in `plugins/chat/assets/javascripts/discourse/components/navbar/index.gjs` and `plugins/chat/assets/javascripts/discourse/components/navbar/actions.gjs`.

Visually the header is not changing much, only in drawer mode the background has been removed.

This commit also introduces a `<List />` component to facilitate rendering lists in chat plugin.
2023-12-18 17:49:58 +01:00
chapoi 7da33ad6ba
UX: user threads styling tweaks 2023-12-13 14:10:52 +01:00
Joffrey JAFFEUX 54724f7c09
UX: allow users to click thread title to open it (#24816) 2023-12-11 13:54:00 +01:00
Jan Cernik cf9bef0499
FIX: Navigating out of thread shows other unread threads (#24693)
* FIX: Navigating out of thread shows other unread threads

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2023-12-11 09:44:50 -03: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
Jarek Radosz 694b5f108b
DEV: Fix various rubocop lints (#24749)
These (21 + 3 from previous PRs) are soon to be enabled in rubocop-discourse:

Capybara/VisibilityMatcher
Lint/DeprecatedOpenSSLConstant
Lint/DisjunctiveAssignmentInConstructor
Lint/EmptyConditionalBody
Lint/EmptyEnsure
Lint/LiteralInInterpolation
Lint/NonLocalExitFromIterator
Lint/ParenthesesAsGroupedExpression
Lint/RedundantCopDisableDirective
Lint/RedundantRequireStatement
Lint/RedundantSafeNavigation
Lint/RedundantStringCoercion
Lint/RedundantWithIndex
Lint/RedundantWithObject
Lint/SafeNavigationChain
Lint/SafeNavigationConsistency
Lint/SelfAssignment
Lint/UnreachableCode
Lint/UselessMethodDefinition
Lint/Void

Previous PRs:
Lint/ShadowedArgument
Lint/DuplicateMethods
Lint/BooleanSymbol
RSpec/SpecFilePathSuffix
2023-12-06 23:25:00 +01:00
Jarek Radosz 8623631a06
DEV: Fix random typos (#24756) 2023-12-06 22:25:26 +01:00
Jarek Radosz 6eb1cadb73
DEV: Fix RSpec/SpecFilePathSuffix / enable 3 chat spec files (#24750)
* RSpec/SpecFilePathSuffix
* removes failing specs
* More specific selectors?

---------

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2023-12-06 22:25:11 +01:00
Jarek Radosz 6a66dc1cfb
DEV: Fix Lint/BooleanSymbol (#24747) 2023-12-06 13:19:09 +01:00
Jarek Radosz 138bf486d3
DEV: Fix Lint/DuplicateMethods (#24746) 2023-12-06 13:18:34 +01:00
David Battersby 78c2f116e0
DEV: skip flaky upload spec for large image thumbnails (#24745) 2023-12-06 19:08:56 +08:00
David Battersby 6dd4937b69
update matchers to improve test suite perf for upload specs (#24744)
This change speeds up our upload specs by avoiding Capybara's default_max_wait_time.
2023-12-06 18:02:55 +08:00
David Battersby 8b46dc8bb5
FEATURE: Add thumbnails for chat image uploads (#24328)
Introduces the concept of image thumbnails in chat, prior to this we uploaded and used full size chat images within channels and direct messages.

The following changes are covered:
- Post processing of image uploads to create the thumbnail within Chat::MessageProcessor
- Extract responsive image ratios into CookedProcessorMixin (used for creating upload variations)
- Add thumbnail to upload serializer from plugin.rb
- Convert chat upload template to glimmer component using .gjs format
- Use thumbnail image within chat upload component (stores full size img in orig-src data attribute)
- Old uploads which don't have thumbnails will fallback to full size images in channels/DMs
- Update Magnific lightbox to use full size image when clicked
- Update Glimmer lightbox to use full size image (enables zooming for chat images)
2023-12-06 14:59:18 +08:00
Joffrey JAFFEUX a7a7d8e41e
DEV: correctly uses link to message endpoint in spec (#24652)
- correctly uses link to message endpoint in spec
- correctly uses "chat with"
2023-11-30 19:33:41 +01:00
Joffrey JAFFEUX 0b65aa8b77
DEV: ensures we have error message before message check (#24647)
Previously the spec could be flakey as the long message could show on the screen while we await for processing. Now we will first check to have the error message on screen, at this point the erroneous message should never be visible.
2023-11-30 10:55:05 +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 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
Joffrey JAFFEUX 0e00784218
UX: do not show user tab preference when disabled (#23188)
Prior to this fix we would only check if the user is allowed to chat and not if chat is enabled.
2023-08-22 18:22:25 +02:00
Joffrey JAFFEUX 89259205d6
FIX: do not delete empty message with uploads (#23177)
Prior to this fix when editing a message containing only upload, if we would save it, it would delete it by considering it empty.
2023-08-22 15:21:21 +02:00
Joffrey JAFFEUX 687c6c7515
FIX: correctly display max users message error (#23178) 2023-08-22 12:42:35 +02:00
Joffrey JAFFEUX 3bb2f3a604
FIX: correctly recognizes URL with subfolder (#23173)
Prior to this fix minimizing a full page chat on a subfolder install would cause the drawer to not show.
2023-08-21 22:12:05 +02:00
Joffrey JAFFEUX f179eef6ae
DEV: makes every spec use new messages helper (#23163)
It's been introduced months ago, but not everything was transitioned to it.
2023-08-21 16:31:58 +02:00
Joffrey JAFFEUX b03c26ebf5
FIX: correctly handles mobile and default (#23152)
This commit ensures we have correct icon and title on mobile for the chat header icon.

It also fixes a bug where the site setting was not correctly used when the user has not yet set the user option.

Both cases are now correctly tested.
2023-08-18 22:32:43 +02:00
Joffrey JAFFEUX b2b84cc957
FEATURE: implements user based sidebar mode (#23078) 2023-08-18 20:33:07 +02:00
David Taylor edb276b9a9
DEV: Raise exception when capybara finder times out (#22686)
If a selenium finder takes the full wait duration to resolve, that means it has been written inefficiently. Most likely a matcher has been negated incorrectly.

This commit introduces a patch which will raise an error in this situation so that we can catch the issues while developing specs.

This commit also fixes chat's visit_thread helper. It was spinning on `has_css?(".chat-skeleton")` for the full selenium wait duration, and then returns false. That's because the thread is often already fully loaded before `has_css?` is even called. It's now updated to only look for the final expected state.
2023-08-08 10:16:09 +01:00
Martin Brennan 09223e5ae7
DEV: Remove enable_experimental_hashtag_autocomplete logic (#22820)
This commit removes any logic in the app and in specs around
enable_experimental_hashtag_autocomplete and deletes some
old category hashtag code that is no longer necessary.

It also adds a `slug_ref` category instance method, which
will generate a reference like `parent:child` for a category,
with an optional depth, which hashtags use. Also refactors
PostRevisor which was using CategoryHashtagDataSource directly
which is a no-no.

Deletes the old hashtag markdown rule as well.
2023-08-08 11:18:55 +10:00
Martin Brennan 3e44f04ff5
DEV: Unskip chat delete message spec (#22951)
Skipped in https://github.com/discourse/discourse/pull/22862 but
it seems like that may have been a sidebar error, unskipping to
see if it's ok now
2023-08-07 11:04:10 +10:00