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.
This commit is contained in:
David Battersby 2024-10-11 13:05:07 +04:00 committed by GitHub
parent d90203f27f
commit 79d2eb5beb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 58 additions and 11 deletions

View File

@ -1,12 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class Chat::Api::ChannelsController < Chat::ApiController class Chat::Api::ChannelsController < Chat::ApiController
CHANNEL_EDITABLE_PARAMS ||= %i[name description slug] CHANNEL_EDITABLE_PARAMS ||= %i[name description slug threading_enabled]
CATEGORY_CHANNEL_EDITABLE_PARAMS ||= %i[ CATEGORY_CHANNEL_EDITABLE_PARAMS ||= %i[auto_join_users allow_channel_wide_mentions]
auto_join_users
allow_channel_wide_mentions
threading_enabled
]
def index def index
permitted = params.permit(:filter, :limit, :offset, :status) permitted = params.permit(:filter, :limit, :offset, :status)

View File

@ -3,6 +3,7 @@
module Chat module Chat
class DirectMessageChannel < Channel class DirectMessageChannel < Channel
alias_method :direct_message, :chatable alias_method :direct_message, :chatable
before_validation(on: :create) { self.threading_enabled = true }
def direct_message_channel? def direct_message_channel?
true true

View File

@ -98,10 +98,14 @@ export default class ChatRouteChannelInfoSettings extends Component {
return this.args.channel.isCategoryChannel && this.args.channel.isOpen; return this.args.channel.isCategoryChannel && this.args.channel.isOpen;
} }
get toggleThreadingAvailable() { get toggleThreadingCategoryChannel() {
return this.args.channel.isCategoryChannel && this.args.channel.isOpen; return this.args.channel.isCategoryChannel && this.args.channel.isOpen;
} }
get toggleThreadingDirectMessage() {
return this.args.channel.isDirectMessageChannel && this.args.channel.isOpen;
}
get channelWideMentionsDescription() { get channelWideMentionsDescription() {
return I18n.t("chat.settings.channel_wide_mentions_description", { return I18n.t("chat.settings.channel_wide_mentions_description", {
channel: this.args.channel.title, channel: this.args.channel.title,
@ -420,6 +424,28 @@ export default class ChatRouteChannelInfoSettings extends Component {
</:action> </:action>
</section.row> </section.row>
{{/if}} {{/if}}
{{#if this.toggleThreadingDirectMessage}}
<section.row @label={{this.toggleThreadingLabel}}>
<:action>
<DToggleSwitch
@state={{@channel.threadingEnabled}}
class="c-channel-settings__threading-switch"
{{on
"click"
(fn
this.onToggleThreadingEnabled
@channel.threadingEnabled
)
}}
/>
</:action>
<:description>
{{this.toggleThreadingDescription}}
</:description>
</section.row>
{{/if}}
</form.section> </form.section>
{{/if}} {{/if}}
@ -482,7 +508,7 @@ export default class ChatRouteChannelInfoSettings extends Component {
</section.row> </section.row>
{{/if}} {{/if}}
{{#if this.toggleThreadingAvailable}} {{#if this.toggleThreadingCategoryChannel}}
<section.row @label={{this.toggleThreadingLabel}}> <section.row @label={{this.toggleThreadingLabel}}>
<:action> <:action>
<DToggleSwitch <DToggleSwitch

View File

@ -44,7 +44,7 @@ module Chat
# name and description can be edited. # name and description can be edited.
def can_edit_chat_channel?(channel) def can_edit_chat_channel?(channel)
if channel.direct_message_channel? if channel.direct_message_channel?
channel.chatable.group && (is_staff? || channel.chatable.user_can_access?(@user)) is_staff? || channel.chatable.user_can_access?(@user)
elsif channel.category_channel? elsif channel.category_channel?
is_staff? is_staff?
end end

View File

@ -43,6 +43,7 @@ Fabricator(:direct_message_channel, from: :chat_channel) do
end end
status { :open } status { :open }
name nil name nil
threading_enabled true
after_create do |channel, attrs| after_create do |channel, attrs|
if attrs[:with_membership] if attrs[:with_membership]
channel.chatable.users.each do |user| channel.chatable.users.each do |user|

View File

@ -87,9 +87,9 @@ RSpec.describe Chat::GuardianExtensions do
end end
context "when not group" do context "when not group" do
it "doesnt allow to edit the channel" do it "allows to edit the channel" do
Chat::DirectMessageUser.create(user: user, direct_message: dm_channel.chatable) Chat::DirectMessageUser.create(user: user, direct_message: dm_channel.chatable)
expect(user.guardian.can_edit_chat_channel?(dm_channel)).to eq(false) expect(user.guardian.can_edit_chat_channel?(dm_channel)).to eq(true)
end end
end end
end end

View File

@ -52,6 +52,12 @@ RSpec.describe Chat::DirectMessageChannel do
end end
end end
describe "#threading_enabled" do
it "defaults to true" do
expect(channel.threading_enabled).to be(true)
end
end
describe "#title" do describe "#title" do
subject(:title) { channel.title(user) } subject(:title) { channel.title(user) }

View File

@ -166,6 +166,23 @@ RSpec.describe "Channel - Info - Settings page", type: :system do
).to eq(false) ).to eq(false)
end end
end end
context "when direct message channel" do
fab!(:channel_1) do
Fabricate(:direct_message_channel, users: [current_user, Fabricate(:user)])
end
before { channel_1.add(current_user) }
it "can toggle threading" do
chat_page.visit_channel_settings(channel_1)
expect {
PageObjects::Components::DToggleSwitch.new(".c-channel-settings__threading-switch").toggle
expect(toasts).to have_success(I18n.t("js.saved"))
}.to change { channel_1.reload.threading_enabled }.from(true).to(false)
end
end
end end
context "as staff" do context "as staff" do