FEATURE: Create a link to start a new chat (#25722)

This feature adds the functionality to start a new chat directly from the URL using query params.

The format is: /chat/new-message?recipients=buford,jona

The initial version of this feature allows for the following:

- Open an existing direct message channel with a single user
- Create a new direct message channel with a single user (and auto redirect)
- Create or open a channel with multiple users (and auto redirect)
- Redirects to chat home if the recipients param is missing
This commit is contained in:
David Battersby 2024-02-20 18:08:57 +08:00 committed by GitHub
parent d8d756cd2f
commit a460dbcb37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 85 additions and 0 deletions

View File

@ -15,6 +15,8 @@ export default function () {
this.route("channels"); this.route("channels");
this.route("threads"); this.route("threads");
this.route("new-message");
this.route( this.route(
"channel.info", "channel.info",
{ path: "/c/:channelTitle/:channelId/info" }, { path: "/c/:channelTitle/:channelId/info" },

View File

@ -0,0 +1,5 @@
import Controller from "@ember/controller";
export default class ChatNewMessageController extends Controller {
queryParams = ["recipients"];
}

View File

@ -0,0 +1,20 @@
import { inject as service } from "@ember/service";
import DiscourseRoute from "discourse/routes/discourse";
export default class ChatNewMessageRoute extends DiscourseRoute {
@service chat;
@service router;
beforeModel(transition) {
const recipients = this.paramsFor(this.routeName).recipients?.split(",");
if (!recipients) {
transition.abort();
return this.router.transitionTo("chat");
}
this.chat.upsertDmChannel({ usernames: recipients }).then((channel) => {
this.router.transitionTo("chat.channel", channel.title, channel.id);
});
}
}

View File

@ -75,6 +75,7 @@ Chat::Engine.routes.draw do
# chat_controller routes # chat_controller routes
get "/" => "chat#respond" get "/" => "chat#respond"
get "/new-message" => "chat#respond"
get "/direct-messages" => "chat#respond" get "/direct-messages" => "chat#respond"
get "/channels" => "chat#respond" get "/channels" => "chat#respond"
get "/threads" => "chat#respond" get "/threads" => "chat#respond"

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
RSpec.describe "Chat New Message from params", type: :system do
fab!(:current_user) { Fabricate(:user) }
fab!(:user_1) { Fabricate(:user) }
fab!(:user_2) { Fabricate(:user) }
fab!(:public_channel) { Fabricate(:chat_channel) }
fab!(:user_1_channel) { Fabricate(:direct_message_channel, users: [current_user, user_1]) }
let(:chat_page) { PageObjects::Pages::Chat.new }
before do
chat_system_bootstrap
public_channel.add(current_user)
sign_in(current_user)
end
context "with a single user" do
it "redirects to existing chat channel" do
chat_page.visit_new_message(user_1)
expect(page).to have_current_path("/chat/c/#{user_1.username}/#{user_1_channel.id}")
end
it "creates a dm channel and redirects if none exists" do
chat_page.visit_new_message(user_2)
expect(page).to have_current_path("/chat/c/#{user_2.username}/#{Chat::Channel.last.id}")
end
it "redirects to chat channel if recipients param is missing" do
visit("/chat/new-message")
# chat service selects public channel from getIdealFirstChannelId
expect(page).to have_current_path("/chat/c/#{public_channel.slug}/#{public_channel.id}")
end
end
context "with multiple users" do
it "creates a dm channel with multiple users" do
chat_page.visit_new_message([user_1, user_2])
expect(page).to have_current_path(
"/chat/c/#{user_1.username}-#{user_2.username}/#{Chat::Channel.last.id}",
)
end
end
end

View File

@ -91,6 +91,16 @@ module PageObjects
PageObjects::Pages::ChatBrowse.new.has_finished_loading? PageObjects::Pages::ChatBrowse.new.has_finished_loading?
end end
def visit_new_message(recipients)
if recipients.is_a?(Array)
recipients = recipients.map(&:username).join(",")
elsif recipients.respond_to?(:username)
recipients = recipients.username
end
visit("/chat/new-message?recipients=#{recipients}")
end
def has_finished_loading? def has_finished_loading?
has_no_css?(".chat-channel--not-loaded-once") has_no_css?(".chat-channel--not-loaded-once")
has_no_css?(".chat-skeleton") has_no_css?(".chat-skeleton")