FEATURE: implements user based sidebar mode (#23078)

This commit is contained in:
Joffrey JAFFEUX 2023-08-18 20:33:07 +02:00 committed by GitHub
parent 82b16f4f47
commit b2b84cc957
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 602 additions and 52 deletions

View File

@ -5,5 +5,6 @@
@icon={{button.switchButtonIcon}}
@disabled={{this.isSwitching}}
@translatedLabel={{button.switchButtonLabel}}
data-key={{button.key}}
/>
{{/each}}

View File

@ -16,9 +16,13 @@ export default class SwitchPanelButtons extends Component {
const url = panel.lastKnownURL || panel.switchButtonDefaultUrl;
const destination = url === "/" ? `discovery.${defaultHomepage()}` : url;
this.router.transitionTo(destination).finally(() => {
this.isSwitching = false;
this.sidebarState.setPanel(panel.key);
});
this.router
.transitionTo(destination)
.then(() => {
this.sidebarState.setPanel(panel.key);
})
.finally(() => {
this.isSwitching = false;
});
}
}

View File

@ -292,6 +292,7 @@ end
# sidebar_link_to_filtered_list :boolean default(FALSE), not null
# sidebar_show_count_of_new_items :boolean default(FALSE), not null
# watched_precedence_over_muted :boolean
# chat_separate_sidebar_mode :integer default(0), not null
#
# Indexes
#

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
module Chat
class SeparateSidebarModeSiteSetting < EnumSiteSetting
def self.valid_value?(val)
values.any? { |v| v[:value] == val }
end
def self.values
@values ||= [
{ name: "admin.site_settings.chat_separate_sidebar_mode.never", value: "never" },
{ name: "admin.site_settings.chat_separate_sidebar_mode.always", value: "always" },
{ name: "admin.site_settings.chat_separate_sidebar_mode.fullscreen", value: "fullscreen" },
]
end
def self.translate_names?
true
end
end
end

View File

@ -171,8 +171,8 @@ export default Component.extend({
@action
openURL(url = null) {
this.chat.activeChannel = null;
this.chatStateManager.didOpenDrawer(url);
this.chatDrawerRouter.stateFor(this._routeFromURL(url));
this.chatStateManager.didOpenDrawer(url);
},
_routeFromURL(url) {

View File

@ -2,8 +2,9 @@
href={{this.href}}
tabindex="0"
class={{concat-class "icon" "btn-flat" (if this.isActive "active")}}
title={{i18n this.title}}
>
{{d-icon "d-chat"}}
{{d-icon this.icon}}
{{#unless this.currentUserInDnD}}
<Chat::Header::Icon::UnreadIndicator
@urgentCount={{@urgentCount}}

View File

@ -1,7 +1,7 @@
import { inject as service } from "@ember/service";
import Component from "@glimmer/component";
import getURL from "discourse-common/lib/get-url";
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
export default class ChatHeaderIcon extends Component {
@service currentUser;
@service site;
@ -12,6 +12,10 @@ export default class ChatHeaderIcon extends Component {
return this.args.currentUserInDnD || this.currentUser.isInDoNotDisturb();
}
get chatSeparateSidebarMode() {
return getUserChatSeparateSidebarMode(this.currentUser);
}
get isActive() {
return (
this.args.isActive ||
@ -20,13 +24,38 @@ export default class ChatHeaderIcon extends Component {
);
}
get title() {
if (
this.chatStateManager.isFullPageActive &&
!this.chatSeparateSidebarMode.never
) {
return "sidebar.panels.forum.label";
}
return "chat.title_capitalized";
}
get icon() {
if (
this.chatStateManager.isFullPageActive &&
!this.chatSeparateSidebarMode.never
) {
return "random";
}
return "d-chat";
}
get href() {
if (this.chatStateManager.isFullPageActive) {
if (this.site.mobileView) {
return getURL("/chat");
} else {
return getURL(this.router.currentURL);
}
if (this.site.mobileView && this.chatStateManager.isFullPageActive) {
return getURL("/chat");
}
if (
this.chatStateManager.isFullPageActive &&
!this.chatSeparateSidebarMode.never
) {
return getURL(this.chatStateManager.lastKnownAppURL || "/");
}
if (this.chatStateManager.isDrawerActive) {

View File

@ -14,38 +14,65 @@ const CHAT_ATTRS = [
"chat_sound",
"chat_email_frequency",
"chat_header_indicator_preference",
"chat_separate_sidebar_mode",
];
const EMAIL_FREQUENCY_OPTIONS = [
{ name: I18n.t("chat.email_frequency.never"), value: "never" },
{ name: I18n.t("chat.email_frequency.when_away"), value: "when_away" },
];
export const HEADER_INDICATOR_PREFERENCE_NEVER = "never";
export const HEADER_INDICATOR_PREFERENCE_DM_AND_MENTIONS = "dm_and_mentions";
export const HEADER_INDICATOR_PREFERENCE_ALL_NEW = "all_new";
const EMAIL_FREQUENCY_OPTIONS = [
{ name: I18n.t(`chat.email_frequency.never`), value: "never" },
{ name: I18n.t(`chat.email_frequency.when_away`), value: "when_away" },
];
const HEADER_INDICATOR_OPTIONS = [
{
name: I18n.t(`chat.header_indicator_preference.all_new`),
name: I18n.t("chat.header_indicator_preference.all_new"),
value: HEADER_INDICATOR_PREFERENCE_ALL_NEW,
},
{
name: I18n.t(`chat.header_indicator_preference.dm_and_mentions`),
name: I18n.t("chat.header_indicator_preference.dm_and_mentions"),
value: HEADER_INDICATOR_PREFERENCE_DM_AND_MENTIONS,
},
{
name: I18n.t(`chat.header_indicator_preference.never`),
name: I18n.t("chat.header_indicator_preference.never"),
value: HEADER_INDICATOR_PREFERENCE_NEVER,
},
];
const CHAT_SEPARATE_SIDEBAR_MODE_OPTIONS = [
{
name: I18n.t("admin.site_settings.chat_separate_sidebar_mode.always"),
value: "always",
},
{
name: I18n.t("admin.site_settings.chat_separate_sidebar_mode.fullscreen"),
value: "fullscreen",
},
{
name: I18n.t("admin.site_settings.chat_separate_sidebar_mode.never"),
value: "never",
},
];
export default class PreferencesChatController extends Controller {
@service chatAudioManager;
@service siteSettings;
subpageTitle = I18n.t("chat.admin.title");
emailFrequencyOptions = EMAIL_FREQUENCY_OPTIONS;
headerIndicatorOptions = HEADER_INDICATOR_OPTIONS;
chatSeparateSidebarModeOptions = CHAT_SEPARATE_SIDEBAR_MODE_OPTIONS;
get chatSeparateSidebarMode() {
const mode = this.model.get("user_option.chat_separate_sidebar_mode");
if (mode === "default") {
return this.siteSettings.chat_separate_sidebar_mode;
} else {
return mode;
}
}
@discourseComputed
chatSounds() {

View File

@ -11,6 +11,7 @@ import { decorateUsername } from "discourse/helpers/decorate-username-selector";
import { until } from "discourse/lib/formatter";
import { inject as service } from "@ember/service";
import ChatModalNewMessage from "discourse/plugins/chat/discourse/components/chat/modal/new-message";
import getURL from "discourse-common/lib/get-url";
export default {
name: "chat-sidebar",
@ -23,6 +24,18 @@ export default {
this.siteSettings = container.lookup("service:site-settings");
withPluginApi("1.8.0", (api) => {
api.addSidebarPanel(
(BaseCustomSidebarPanel) =>
class ChatSidebarPanel extends BaseCustomSidebarPanel {
key = "chat";
switchButtonLabel = I18n.t("sidebar.panels.chat.label");
switchButtonIcon = "d-chat";
switchButtonDefaultUrl = getURL("/chat");
}
);
});
withPluginApi("1.3.0", (api) => {
if (this.siteSettings.enable_public_channels) {
api.addSidebarSection(
@ -180,7 +193,8 @@ export default {
};
return SidebarChatChannelsSection;
}
},
"chat"
);
}
@ -414,7 +428,8 @@ export default {
};
return SidebarChatDirectMessagesSection;
}
},
"chat"
);
});
},

View File

@ -6,6 +6,7 @@ const IGNORE_CHANNEL_WIDE_MENTION = "ignore_channel_wide_mention";
const CHAT_SOUND = "chat_sound";
const CHAT_EMAIL_FREQUENCY = "chat_email_frequency";
const CHAT_HEADER_INDICATOR_PREFERENCE = "chat_header_indicator_preference";
const CHAT_SEPARATE_SIDEBAR_MODE = "chat_separate_sidebar_mode";
export default {
name: "chat-user-options",
@ -20,6 +21,7 @@ export default {
api.addSaveableUserOptionField(CHAT_SOUND);
api.addSaveableUserOptionField(CHAT_EMAIL_FREQUENCY);
api.addSaveableUserOptionField(CHAT_HEADER_INDICATOR_PREFERENCE);
api.addSaveableUserOptionField(CHAT_SEPARATE_SIDEBAR_MODE);
}
});
},

View File

@ -0,0 +1,9 @@
export function getUserChatSeparateSidebarMode(user) {
const mode = user?.get("user_option.chat_separate_sidebar_mode");
return {
never: "never" === mode,
always: "always" === mode,
fullscreen: "fullscreen" === mode,
};
}

View File

@ -4,11 +4,13 @@ import { defaultHomepage } from "discourse/lib/utilities";
import { inject as service } from "@ember/service";
import { scrollTop } from "discourse/mixins/scroll-top";
import { schedule } from "@ember/runloop";
import { withPluginApi } from "discourse/lib/plugin-api";
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
export default class ChatRoute extends DiscourseRoute {
@service chat;
@service router;
@service chatStateManager;
@service currentUser;
titleToken() {
return I18n.t("chat.title_capitalized");
@ -57,6 +59,16 @@ export default class ChatRoute extends DiscourseRoute {
}
activate() {
withPluginApi("1.8.0", (api) => {
api.setSidebarPanel("chat");
if (getUserChatSeparateSidebarMode(this.currentUser).never) {
api.setCombinedSidebarMode();
api.hideSidebarSwitchPanelButtons();
} else {
api.setSeparatedSidebarMode();
}
});
this.chatStateManager.storeAppURL();
this.chat.updatePresence();
@ -68,6 +80,23 @@ export default class ChatRoute extends DiscourseRoute {
}
deactivate(transition) {
withPluginApi("1.8.0", (api) => {
api.setSidebarPanel("main");
const chatSeparateSidebarMode = getUserChatSeparateSidebarMode(
this.currentUser
);
if (chatSeparateSidebarMode.fullscreen) {
api.setCombinedSidebarMode();
api.showSidebarSwitchPanelButtons();
} else if (chatSeparateSidebarMode.always) {
api.setSeparatedSidebarMode();
} else {
api.setCombinedSidebarMode();
api.hideSidebarSwitchPanelButtons();
}
});
if (transition) {
const url = this.router.urlFor(transition.from.name);
this.chatStateManager.storeChatURL(url);

View File

@ -4,6 +4,8 @@ import { tracked } from "@glimmer/tracking";
import KeyValueStore from "discourse/lib/key-value-store";
import Site from "discourse/models/site";
import getURL from "discourse-common/lib/get-url";
import { getUserChatSeparateSidebarMode } from "discourse/plugins/chat/discourse/lib/get-user-chat-separate-sidebar-mode";
import { withPluginApi } from "discourse/lib/plugin-api";
const PREFERRED_MODE_KEY = "preferred_mode";
const PREFERRED_MODE_STORE_NAMESPACE = "discourse_chat_";
@ -56,6 +58,16 @@ export default class ChatStateManager extends Service {
}
didOpenDrawer(url = null) {
withPluginApi("1.8.0", (api) => {
if (getUserChatSeparateSidebarMode(this.currentUser).always) {
api.setSidebarPanel("main");
api.setSeparatedSidebarMode();
api.hideSidebarSwitchPanelButtons();
} else {
api.setCombinedSidebarMode();
}
});
this.isDrawerActive = true;
this.isDrawerExpanded = true;
@ -68,6 +80,24 @@ export default class ChatStateManager extends Service {
}
didCloseDrawer() {
withPluginApi("1.8.0", (api) => {
api.setSidebarPanel("main");
const chatSeparateSidebarMode = getUserChatSeparateSidebarMode(
this.currentUser
);
if (chatSeparateSidebarMode.fullscreen) {
api.setCombinedSidebarMode();
api.showSidebarSwitchPanelButtons();
} else if (chatSeparateSidebarMode.always) {
api.setSeparatedSidebarMode();
api.showSidebarSwitchPanelButtons();
} else {
api.setCombinedSidebarMode();
api.hideSidebarSwitchPanelButtons();
}
});
this.isDrawerActive = false;
this.isDrawerExpanded = false;
this.chat.updatePresence();

View File

@ -99,6 +99,23 @@
/>
</div>
<div
class="control-group chat-setting controls-dropdown"
data-setting-name="user_chat_separate_sidebar_mode"
>
<label for="user_chat_separate_sidebar_mode">
{{i18n "chat.separate_sidebar_mode.title"}}
</label>
<ComboBox
@valueProperty="value"
@content={{this.chatSeparateSidebarModeOptions}}
@value={{this.chatSeparateSidebarMode}}
@id="user_chat_separate_sidebar_mode"
@onChange={{action (mut this.model.user_option.chat_separate_sidebar_mode)}}
/>
</div>
<SaveControls
@id="user_chat_preference_save"
@model={{this.model}}

View File

@ -4,7 +4,6 @@ import { hbs } from "ember-cli-htmlbars";
export default createWidget("chat-header-icon", {
tagName: "li.header-dropdown-toggle.chat-header-icon",
title: "chat.title_capitalized",
services: ["chat"],

View File

@ -4,6 +4,10 @@ en:
site_settings:
categories:
chat: Chat
chat_separate_sidebar_mode:
always: "Always"
fullscreen: "When chat is in fullscreen"
never: "Never"
logs:
staff_actions:
actions:
@ -104,6 +108,8 @@ en:
all_new: "All New Messages"
dm_and_mentions: "Direct Messages and Mentions"
never: "Never"
separate_sidebar_mode:
title: "Show separate sidebar modes for forum and chat"
enable: "Enable chat"
flag: "Flag"
emoji: "Insert emoji"
@ -685,3 +691,8 @@ en:
sections:
chat:
title: Chat
sidebar:
panels:
chat:
label: "Chat"

View File

@ -1,5 +1,6 @@
en:
site_settings:
chat_separate_sidebar_mode: "Show separate sidebar modes for forum and chat."
chat_enabled: "Enable the chat plugin."
enable_public_channels: "Enable public channels based on categories."
chat_allowed_groups: "Users in these groups can chat. Note that staff can always access chat."

View File

@ -116,3 +116,8 @@ chat:
max_chat_draft_length:
default: 50_000
hidden: true
chat_separate_sidebar_mode:
client: true
default: "never"
type: enum
enum: "Chat::SeparateSidebarModeSiteSetting"

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddChatSeparateSidebarModeUserOption < ActiveRecord::Migration[7.0]
def change
add_column :user_options, :chat_separate_sidebar_mode, :integer, default: 0, null: false
end
end

View File

@ -14,19 +14,32 @@ module Chat
@chat_email_frequencies ||= { never: 0, when_away: 1 }
end
# Avoid attempting to override when autoloading
if !base.method_defined?(:send_chat_email_never?)
base.enum :chat_email_frequency, base.chat_email_frequencies, prefix: "send_chat_email"
end
def base.chat_header_indicator_preferences
@chat_header_indicator_preferences ||= { all_new: 0, dm_and_mentions: 1, never: 2 }
end
if !base.method_defined?(:send_chat_email_never?) # Avoid attempting to override when autoloading
base.enum :chat_email_frequency, base.chat_email_frequencies, prefix: "send_chat_email"
end
if !base.method_defined?(:chat_header_indicator_never?) # Avoid attempting to override when autoloading
# Avoid attempting to override when autoloading
if !base.method_defined?(:chat_header_indicator_never?)
base.enum :chat_header_indicator_preference,
base.chat_header_indicator_preferences,
prefix: "chat_header_indicator"
end
def base.chat_separate_sidebar_mode
@chat_separate_sidebar_mode ||= { default: 0, never: 1, always: 2, fullscreen: 3 }
end
# Avoid attempting to override when autoloading
if !base.method_defined?(:chat_separate_sidebar_mode_default?)
base.enum :chat_separate_sidebar_mode,
base.chat_separate_sidebar_mode,
prefix: "chat_separate_sidebar_mode"
end
end
end
end

View File

@ -47,6 +47,7 @@ after_initialize do
UserUpdater::OPTION_ATTR.push(:ignore_channel_wide_mention)
UserUpdater::OPTION_ATTR.push(:chat_email_frequency)
UserUpdater::OPTION_ATTR.push(:chat_header_indicator_preference)
UserUpdater::OPTION_ATTR.push(:chat_separate_sidebar_mode)
register_reviewable_type Chat::ReviewableMessage
@ -297,6 +298,12 @@ after_initialize do
object.chat_header_indicator_preference
end
add_to_serializer(:user_option, :chat_separate_sidebar_mode) { object.chat_separate_sidebar_mode }
add_to_serializer(:current_user_option, :chat_separate_sidebar_mode) do
object.chat_separate_sidebar_mode
end
RETENTION_SETTINGS_TO_USER_OPTION_FIELDS = {
chat_channel_retention_days: :dismissed_channel_retention_reminder,
chat_dm_retention_days: :dismissed_dm_retention_reminder,

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
require "rails_helper"
RSpec.describe UserOption do
describe "#chat_separate_sidebar_mode" do
it "is present" do
expect(described_class.new.chat_separate_sidebar_mode).to eq("default")
end
end
end

View File

@ -13,6 +13,12 @@ RSpec.describe CurrentUserSerializer do
current_user.user_option.update(chat_enabled: true)
end
describe "#chat_separate_sidebar_mode" do
it "is present" do
expect(serializer.as_json[:user_option][:chat_separate_sidebar_mode]).to eq("default")
end
end
describe "#chat_drafts" do
context "when user can't chat" do
before { SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:staff] }

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
RSpec.describe UserSerializer do
fab!(:current_user) { Fabricate(:user) }
let(:serializer) do
described_class.new(current_user, scope: Guardian.new(current_user), root: false)
end
describe "#chat_separate_sidebar_mode" do
it "is present" do
expect(serializer.as_json[:user_option][:chat_separate_sidebar_mode]).to eq("default")
end
end
end

View File

@ -19,6 +19,9 @@ RSpec.describe "Navigation", type: :system do
before do
chat_system_bootstrap(current_user, [category_channel, category_channel_2])
current_user.user_option.update(
chat_separate_sidebar_mode: UserOption.chat_separate_sidebar_modes[:never],
)
sign_in(current_user)
end
@ -36,7 +39,6 @@ RSpec.describe "Navigation", type: :system do
context "when clicking chat icon on mobile and is viewing channel" do
it "navigates to index", mobile: true do
visit("/chat")
chat_page.visit_channel(category_channel_2)
chat_page.open_from_header
@ -44,18 +46,6 @@ RSpec.describe "Navigation", type: :system do
end
end
context "when clicking chat icon on desktop and is viewing channel" do
it "stays on channel page" do
visit("/chat")
chat_page.visit_channel(category_channel_2)
chat_page.open_from_header
expect(page).to have_current_path(
chat.channel_path(category_channel_2.slug, category_channel_2.id),
)
end
end
context "when visiting /chat" do
it "opens full page" do
chat_page.open

View File

@ -17,6 +17,12 @@ module PageObjects
)
end
def prefers_drawer
page.execute_script(
"window.localStorage.setItem('discourse_chat_preferred_mode', '\"DRAWER_CHAT\"');",
)
end
def open_from_header
find(".chat-header-icon").click
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
module PageObjects
module Components
module Chat
class Header < PageObjects::Components::Base
def has_open_chat_button?
has_css?(".d-header .chat-header-icon .d-icon-d-chat")
end
def has_open_forum_button?
has_css?(".d-header .chat-header-icon .d-icon-random")
end
def has_no_chat_button?
has_no_css?(".d-header .chat-header-icon")
end
end
end
end
end

View File

@ -0,0 +1,202 @@
# frozen_string_literal: true
RSpec.describe "Separate sidebar mode", type: :system do
let(:chat_page) { PageObjects::Pages::Chat.new }
let(:sidebar_page) { PageObjects::Pages::Sidebar.new }
let(:sidebar_component) { PageObjects::Components::NavigationMenu::Sidebar.new }
let(:chat_drawer_page) { PageObjects::Pages::ChatDrawer.new }
let(:header_component) { PageObjects::Components::Chat::Header.new }
fab!(:current_user) { Fabricate(:user) }
fab!(:channel_1) { Fabricate(:chat_channel) }
before do
SiteSetting.navigation_menu = "sidebar"
channel_1.add(current_user)
chat_system_bootstrap
sign_in(current_user)
end
describe "when separate sidebar mode is never" do
before do
current_user.user_option.update!(
chat_separate_sidebar_mode: UserOption.chat_separate_sidebar_modes[:never],
)
end
context "with drawer" do
before { chat_page.prefers_drawer }
it "has the expected behavior" do
visit("/")
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
sidebar_page.open_channel(channel_1)
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
chat_drawer_page.close
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
end
end
context "with full page" do
before { chat_page.prefers_full_page }
it "has the expected behavior" do
visit("/")
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
sidebar_page.open_channel(channel_1)
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
find("#site-logo").click
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
end
end
end
describe "when separate sidebar mode is always" do
before do
current_user.user_option.update(
chat_separate_sidebar_mode: UserOption.chat_separate_sidebar_modes[:always],
)
end
context "with drawer" do
before { chat_page.prefers_drawer }
it "has the expected behavior" do
visit("/")
expect(sidebar_component).to have_switch_button("chat")
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_no_section("chat-channels")
chat_page.open_from_header
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_no_section("chat-channels")
chat_drawer_page.close
expect(sidebar_component).to have_switch_button("chat")
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_no_section("chat-channels")
end
end
context "with full page" do
before { chat_page.prefers_full_page }
it "has the expected behavior" do
visit("/")
expect(sidebar_component).to have_switch_button("chat")
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_no_section("chat-channels")
expect(sidebar_component).to have_section("Categories")
chat_page.open_from_header
expect(sidebar_component).to have_switch_button("main")
expect(header_component).to have_open_forum_button
expect(sidebar_component).to have_section("chat-channels")
expect(sidebar_component).to have_no_section("Categories")
find("#site-logo").click
expect(sidebar_component).to have_switch_button("chat")
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_no_section("chat-channels")
expect(sidebar_component).to have_section("Categories")
end
end
end
describe "when separate sidebar mode is fullscreen" do
before do
current_user.user_option.update(
chat_separate_sidebar_mode: UserOption.chat_separate_sidebar_modes[:fullscreen],
)
end
context "with drawer" do
before { chat_page.prefers_drawer }
it "has the expected behavior" do
visit("/")
expect(sidebar_component).to have_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
sidebar_page.open_channel(channel_1)
expect(sidebar_component).to have_no_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
chat_drawer_page.close
expect(sidebar_component).to have_switch_button
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("Categories")
expect(sidebar_component).to have_section("chat-channels")
end
end
context "with full page" do
before { chat_page.prefers_full_page }
it "has the expected behavior" do
visit("/")
expect(sidebar_component).to have_switch_button("chat")
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("chat-channels")
expect(sidebar_component).to have_section("Categories")
sidebar_page.open_channel(channel_1)
expect(sidebar_component).to have_switch_button("main")
expect(header_component).to have_open_forum_button
expect(sidebar_component).to have_section("chat-channels")
expect(sidebar_component).to have_no_section("Categories")
find("#site-logo").click
expect(sidebar_component).to have_switch_button("chat")
expect(header_component).to have_open_chat_button
expect(sidebar_component).to have_section("chat-channels")
expect(sidebar_component).to have_section("Categories")
end
end
end
end

View File

@ -25,22 +25,32 @@ RSpec.describe "User chat preferences", type: :system do
it "can select chat sound" do
visit("/u/#{current_user.username}/preferences/chat")
find("#user_chat_sounds .select-kit-header[data-value]").click
find("[data-value='bell']").click
select_kit = PageObjects::Components::SelectKit.new("#user_chat_sounds")
select_kit.expand
select_kit.select_row_by_value("bell")
find(".save-changes").click
expect(page).to have_css("#user_chat_sounds .select-kit-header[data-value='bell']")
expect(select_kit).to have_selected_value("bell")
end
it "can select header_indicator_preference" do
visit("/u/#{current_user.username}/preferences/chat")
find("#user_chat_header_indicator_preference .select-kit-header[data-value]").click
find("[data-value='dm_and_mentions']").click
select_kit = PageObjects::Components::SelectKit.new("#user_chat_header_indicator_preference")
select_kit.expand
select_kit.select_row_by_value("dm_and_mentions")
find(".save-changes").click
expect(page).to have_css(
"#user_chat_header_indicator_preference .select-kit-header[data-value='dm_and_mentions']",
)
expect(select_kit).to have_selected_value("dm_and_mentions")
end
it "can select separate sidebar mode" do
visit("/u/#{current_user.username}/preferences/chat")
select_kit = PageObjects::Components::SelectKit.new("#user_chat_separate_sidebar_mode")
select_kit.expand
select_kit.select_row_by_value("fullscreen")
find(".save-changes").click
expect(select_kit).to have_selected_value("fullscreen")
end
context "as an admin on another user's preferences" do

View File

@ -0,0 +1,44 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { render } from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import sinon from "sinon";
import I18n from "I18n";
module("Discourse Chat | Component | chat-header-icon", function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {});
test("full page - never separated sidebar mode", async function (assert) {
this.currentUser.user_option.chat_separate_sidebar_mode = "never";
sinon
.stub(this.owner.lookup("service:chat-state-manager"), "isFullPageActive")
.value(true);
await render(hbs`<Chat::Header::Icon />`);
assert
.dom(".icon.btn-flat")
.hasAttribute("title", I18n.t("chat.title_capitalized"))
.hasAttribute("href", "/chat");
assert.dom(".d-icon-d-chat").exists();
});
test("full page - always separated mode", async function (assert) {
this.currentUser.user_option.chat_separate_sidebar_mode = "always";
sinon
.stub(this.owner.lookup("service:chat-state-manager"), "isFullPageActive")
.value(true);
await render(hbs`<Chat::Header::Icon />`);
assert
.dom(".icon.btn-flat")
.hasAttribute("title", I18n.t("sidebar.panels.forum.label"))
.hasAttribute("href", "/latest");
assert.dom(".d-icon-random").exists();
});
});

View File

@ -34,6 +34,22 @@ module PageObjects
has_no_css?(".sidebar-sections [data-section-name='#{name.parameterize}']")
end
def has_switch_button?(key = nil)
if key
page.has_css?(".sidebar__panel-switch-button[data-key='#{key.parameterize}']")
else
page.has_css?(".sidebar__panel-switch-button")
end
end
def has_no_switch_button?(key = nil)
if key
page.has_no_css?(".sidebar__panel-switch-button[data-key='#{key.parameterize}']")
else
page.has_no_css?(".sidebar__panel-switch-button")
end
end
def has_categories_section?
has_section?("Categories")
end