REFACTOR: naming and state refactor (#19187)

- better handling of drawer state using chat state manager
- removes various float and topic occurrences to use drawer
- ensures user can chat before doing a lot of chat setup
- fixes a bug which was creating presence errors in tests
- removes dead code
This commit is contained in:
Joffrey JAFFEUX 2022-11-25 14:15:38 +01:00 committed by GitHub
parent cad2fe6089
commit 84c1cc70d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 401 additions and 391 deletions

View File

@ -336,7 +336,6 @@ acceptance("Bookmarking", function (needs) {
// open the modal and accept deleting // open the modal and accept deleting
await click("#topic-footer-button-bookmark"); await click("#topic-footer-button-bookmark");
// pauseTest();
await click(yesButton); await click(yesButton);
assert.ok( assert.ok(

View File

@ -98,7 +98,7 @@ export default class ChannelsList extends Component {
@bind @bind
_applyScrollPosition() { _applyScrollPosition() {
const position = this.chatStateManager.isFullPage const position = this.chatStateManager.isFullPageActive
? this.session.channelsListPosition || 0 ? this.session.channelsListPosition || 0
: 0; : 0;
const scroller = document.querySelector(".channels-list"); const scroller = document.querySelector(".channels-list");

View File

@ -66,12 +66,10 @@ export default Component.extend(UppyUploadMixin, {
_uploadDropTargetOptions() { _uploadDropTargetOptions() {
let targetEl; let targetEl;
if (this.chatStateManager.isFullPage) { if (this.chatStateManager.isFullPageActive) {
targetEl = document.querySelector(".full-page-chat"); targetEl = document.querySelector(".full-page-chat");
} else { } else {
targetEl = document.querySelector( targetEl = document.querySelector(".chat-drawer.is-expanded");
".topic-chat-container.expanded.visible"
);
} }
if (!targetEl) { if (!targetEl) {

View File

@ -63,7 +63,7 @@ export default Component.extend(TextareaTextManipulation, {
return picker.opened && picker.context === "chat-composer"; return picker.opened && picker.context === "chat-composer";
}, },
@discourseComputed("chatStateManager.isFullPage") @discourseComputed("chatStateManager.isFullPageActive")
fileUploadElementId(fullPage) { fileUploadElementId(fullPage) {
return fullPage ? "chat-full-page-uploader" : "chat-widget-uploader"; return fullPage ? "chat-full-page-uploader" : "chat-widget-uploader";
}, },

View File

@ -11,16 +11,14 @@ import { cancel, next, throttle } from "@ember/runloop";
import { inject as service } from "@ember/service"; import { inject as service } from "@ember/service";
export default Component.extend({ export default Component.extend({
tagName: "",
listView: equal("view", LIST_VIEW), listView: equal("view", LIST_VIEW),
chatView: equal("view", CHAT_VIEW), chatView: equal("view", CHAT_VIEW),
draftChannelView: equal("view", DRAFT_CHANNEL_VIEW), draftChannelView: equal("view", DRAFT_CHANNEL_VIEW),
classNameBindings: [":topic-chat-float-container", "hidden"],
chat: service(), chat: service(),
router: service(), router: service(),
chatStateManager: service(), chatStateManager: service(),
hidden: true,
loading: false, loading: false,
expanded: true, // TODO - false when not first-load topic
showClose: true, // TODO - false when on same topic showClose: true, // TODO - false when on same topic
sizeTimer: null, sizeTimer: null,
rafTimer: null, rafTimer: null,
@ -95,19 +93,18 @@ export default Component.extend({
} }
}, },
@observes("hidden") @observes("chatStateManager.isDrawerActive")
_fireHiddenAppEvents() { _fireHiddenAppEvents() {
this.chat.set("chatOpen", !this.hidden);
this.appEvents.trigger("chat:rerender-header"); this.appEvents.trigger("chat:rerender-header");
}, },
@discourseComputed("expanded") @discourseComputed("chatStateManager.isDrawerExpanded")
topLineClass(expanded) { topLineClass(expanded) {
const baseClass = "topic-chat-drawer-header__top-line"; const baseClass = "chat-drawer-header__top-line";
return expanded ? `${baseClass}--expanded` : `${baseClass}--collapsed`; return expanded ? `${baseClass}--expanded` : `${baseClass}--collapsed`;
}, },
@discourseComputed("expanded", "chat.activeChannel") @discourseComputed("chatStateManager.isDrawerExpanded", "chat.activeChannel")
displayMembers(expanded, channel) { displayMembers(expanded, channel) {
return expanded && !channel?.isDirectMessageChannel; return expanded && !channel?.isDirectMessageChannel;
}, },
@ -163,28 +160,7 @@ export default Component.extend({
); );
}, },
@discourseComputed( @discourseComputed("chatStateManager.isDrawerExpanded")
"hidden",
"expanded",
"displayMembers",
"chat.activeChannel",
"chatView"
)
containerClassNames(hidden, expanded, displayMembers, activeChannel) {
const classNames = ["topic-chat-container"];
if (expanded) {
classNames.push("expanded");
}
if (!hidden && expanded) {
classNames.push("visible");
}
if (activeChannel) {
classNames.push(`channel-${activeChannel.id}`);
}
return classNames.join(" ");
},
@discourseComputed("expanded")
expandIcon(expanded) { expandIcon(expanded) {
if (expanded) { if (expanded) {
return "angle-double-down"; return "angle-double-down";
@ -204,10 +180,7 @@ export default Component.extend({
@action @action
openURL(URL = null) { openURL(URL = null) {
this.chat.setActiveChannel(null); this.chat.setActiveChannel(null);
this.set("hidden", false); this.chatStateManager.didOpenDrawer(URL);
this.set("expanded", true);
this.chatStateManager.storeChatURL(URL);
const route = this._buildRouteFromURL( const route = this._buildRouteFromURL(
URL || this.chatStateManager.lastKnownChatURL URL || this.chatStateManager.lastKnownChatURL
@ -216,6 +189,7 @@ export default Component.extend({
switch (route.name) { switch (route.name) {
case "chat": case "chat":
this.set("view", LIST_VIEW); this.set("view", LIST_VIEW);
this.refreshChannels();
this.appEvents.trigger("chat:float-toggled", false); this.appEvents.trigger("chat:float-toggled", false);
return; return;
case "chat.draft-channel": case "chat.draft-channel":
@ -245,16 +219,18 @@ export default Component.extend({
@action @action
toggleExpand() { toggleExpand() {
this.set("expanded", !this.expanded); this.chatStateManager.didToggleDrawer();
this.appEvents.trigger("chat:toggle-expand", this.expanded); this.appEvents.trigger(
"chat:toggle-expand",
this.chatStateManager.isDrawerExpanded
);
}, },
@action @action
close() { close() {
this.set("hidden", true); this.chatStateManager.didCloseDrawer();
this.set("expanded", false);
this.chat.setActiveChannel(null); this.chat.setActiveChannel(null);
this.appEvents.trigger("chat:float-toggled", this.hidden); this.appEvents.trigger("chat:float-toggled", true);
}, },
@action @action
@ -275,10 +251,10 @@ export default Component.extend({
this.setProperties({ this.setProperties({
loading: false, loading: false,
expanded: true,
view: LIST_VIEW, view: LIST_VIEW,
}); });
this.chatStateManager.didExpandDrawer();
this.chat.setActiveChannel(null); this.chat.setActiveChannel(null);
}); });
}, },

View File

@ -701,9 +701,9 @@ export default Component.extend({
} }
}, },
@observes("floatHidden") @observes("chatStateManager.isDrawerActive")
onFloatHiddenChange() { onFloatHiddenChange() {
if (!this.floatHidden) { if (this.chatStateManager.isDrawerActive) {
this.set("expanded", true); this.set("expanded", true);
this._markLastReadMessage({ reRender: true }); this._markLastReadMessage({ reRender: true });
this._stickScrollToBottom(); this._stickScrollToBottom();
@ -1265,7 +1265,6 @@ export default Component.extend({
@action @action
onCloseFullScreen() { onCloseFullScreen() {
this.chatStateManager.prefersDrawer(); this.chatStateManager.prefersDrawer();
this.router.transitionTo(this.chatStateManager.lastKnownAppURL).then(() => { this.router.transitionTo(this.chatStateManager.lastKnownAppURL).then(() => {
this.appEvents.trigger( this.appEvents.trigger(
"chat:open-url", "chat:open-url",
@ -1381,6 +1380,10 @@ export default Component.extend({
}, },
_reportReplyingPresence(composerValue) { _reportReplyingPresence(composerValue) {
if (this._selfDeleted) {
return;
}
if (this.chatChannel.isDraft) { if (this.chatChannel.isDraft) {
return; return;
} }

View File

@ -0,0 +1,4 @@
<div class="chat-drawer-outlet-container">
<ChatDrawer />
</div>

View File

@ -11,6 +11,7 @@ export default {
name: "chat-decorators", name: "chat-decorators",
initializeWithPluginApi(api, container) { initializeWithPluginApi(api, container) {
const siteSettings = container.lookup("service:site-settings");
api.decorateChatMessage((element) => decorateGithubOneboxBody(element), { api.decorateChatMessage((element) => decorateGithubOneboxBody(element), {
id: "onebox-github-body", id: "onebox-github-body",
}); });
@ -44,7 +45,6 @@ export default {
} }
); );
const siteSettings = container.lookup("service:site-settings");
api.decorateChatMessage( api.decorateChatMessage(
(element) => (element) =>
highlightSyntax( highlightSyntax(
@ -147,8 +147,10 @@ export default {
}, },
initialize(container) { initialize(container) {
withPluginApi("0.8.42", (api) => if (container.lookup("service:chat").userCanChat) {
this.initializeWithPluginApi(api, container) withPluginApi("0.8.42", (api) =>
); this.initializeWithPluginApi(api, container)
);
}
}, },
}; };

View File

@ -49,12 +49,6 @@ export default {
} }
return true; return true;
}; };
const isDrawerExpanded = () => {
return document.querySelector(".topic-chat-float-container:not(.hidden)")
? true
: false;
};
const modifyComposerSelection = (event, type) => { const modifyComposerSelection = (event, type) => {
if (!isChatComposer(event.target)) { if (!isChatComposer(event.target)) {
return; return;
@ -85,7 +79,7 @@ export default {
}; };
const closeChatDrawer = (event) => { const closeChatDrawer = (event) => {
if (!isDrawerExpanded()) { if (!chatStateManager.isDrawerActive) {
return; return;
} }

View File

@ -50,9 +50,11 @@ export default {
}, },
initialize(container) { initialize(container) {
const siteSettings = container.lookup("service:site-settings"); if (container.lookup("service:chat").userCanChat) {
withPluginApi("0.8.42", (api) => const siteSettings = container.lookup("service:site-settings");
this.initializeWithPluginApi(api, siteSettings) withPluginApi("0.8.42", (api) => {
); this.initializeWithPluginApi(api, siteSettings);
});
}
}, },
}; };

View File

@ -12,8 +12,12 @@ export default {
name: "chat-setup", name: "chat-setup",
initialize(container) { initialize(container) {
this.chatService = container.lookup("service:chat"); this.chatService = container.lookup("service:chat");
this.siteSettings = container.lookup("service:site-settings");
if (!this.chatService.userCanChat) {
return;
}
this.siteSettings = container.lookup("service:site-settings");
this.appEvents = container.lookup("service:appEvents"); this.appEvents = container.lookup("service:appEvents");
this.appEvents.on("discourse:focus-changed", this, "_handleFocusChanged"); this.appEvents.on("discourse:focus-changed", this, "_handleFocusChanged");
@ -110,7 +114,7 @@ export default {
this._registeredDocumentTitleCountCallback = true; this._registeredDocumentTitleCountCallback = true;
} }
api.addCardClickListenerSelector(".topic-chat-float-container"); api.addCardClickListenerSelector(".chat-drawer-outlet");
api.dispatchWidgetAppEvent( api.dispatchWidgetAppEvent(
"site-header", "site-header",
@ -152,6 +156,10 @@ export default {
}, },
teardown() { teardown() {
if (!this.chatService.userCanChat) {
return;
}
this.appEvents.off("discourse:focus-changed", this, "_handleFocusChanged"); this.appEvents.off("discourse:focus-changed", this, "_handleFocusChanged");
_lastForcedRefreshAt = null; _lastForcedRefreshAt = null;
clearChatComposerButtons(); clearChatComposerButtons();

View File

@ -79,6 +79,7 @@ export default class ChatRoute extends DiscourseRoute {
willTransition(transition) { willTransition(transition) {
if (!transition?.to?.name?.startsWith("chat.")) { if (!transition?.to?.name?.startsWith("chat.")) {
this.chatStateManager.storeChatURL(); this.chatStateManager.storeChatURL();
this.chat.updatePresence();
} }
} }
} }

View File

@ -10,7 +10,10 @@ const FULL_PAGE_CHAT = "FULL_PAGE_CHAT";
const DRAWER_CHAT = "DRAWER_CHAT"; const DRAWER_CHAT = "DRAWER_CHAT";
export default class ChatStateManager extends Service { export default class ChatStateManager extends Service {
@service chat;
@service router; @service router;
isDrawerExpanded = false;
isDrawerActive = false;
@tracked _chatURL = null; @tracked _chatURL = null;
@tracked _appURL = null; @tracked _appURL = null;
@ -30,6 +33,39 @@ export default class ChatStateManager extends Service {
this._store.setObject({ key: PREFERRED_MODE_KEY, value: DRAWER_CHAT }); this._store.setObject({ key: PREFERRED_MODE_KEY, value: DRAWER_CHAT });
} }
didOpenDrawer(URL = null) {
this.set("isDrawerActive", true);
this.set("isDrawerExpanded", true);
if (URL) {
this.storeChatURL(URL);
}
this.chat.updatePresence();
}
didCloseDrawer() {
this.set("isDrawerActive", false);
this.set("isDrawerExpanded", false);
this.chat.updatePresence();
}
didExpandDrawer() {
this.set("isDrawerActive", true);
this.set("isDrawerExpanded", true);
this.chat.updatePresence();
}
didCollapseDrawer() {
this.set("isDrawerActive", true);
this.set("isDrawerExpanded", false);
}
didToggleDrawer() {
this.set("isDrawerExpanded", !this.isDrawerExpanded);
this.set("isDrawerActive", true);
}
get isFullPagePreferred() { get isFullPagePreferred() {
return !!( return !!(
Site.currentProp("mobileView") || Site.currentProp("mobileView") ||
@ -46,7 +82,7 @@ export default class ChatStateManager extends Service {
); );
} }
get isFullPage() { get isFullPageActive() {
return this.router.currentRouteName?.startsWith("chat"); return this.router.currentRouteName?.startsWith("chat");
} }

View File

@ -56,7 +56,6 @@ export default class Chat extends Service {
directMessagesLimit = 20; directMessagesLimit = 20;
isNetworkUnreliable = false; isNetworkUnreliable = false;
@and("currentUser.has_chat_enabled", "siteSettings.chat_enabled") userCanChat; @and("currentUser.has_chat_enabled", "siteSettings.chat_enabled") userCanChat;
_chatOpen = false;
_fetchingChannels = null; _fetchingChannels = null;
@computed("currentUser.staff", "currentUser.groups.[]") @computed("currentUser.staff", "currentUser.groups.[]")
@ -168,18 +167,16 @@ export default class Chat extends Service {
}); });
} }
get chatOpen() {
return this._chatOpen;
}
set chatOpen(status) {
this.set("_chatOpen", status);
this.updatePresence();
}
updatePresence() { updatePresence() {
next(() => { next(() => {
if (this.chatStateManager.isFullPage || this.chatOpen) { if (this.isDestroyed || this.isDestroying) {
return;
}
if (
this.chatStateManager.isFullPageActive ||
this.chatStateManager.isDrawerActive
) {
this.presenceChannel.enter({ activeOptions: CHAT_ONLINE_OPTIONS }); this.presenceChannel.enter({ activeOptions: CHAT_ONLINE_OPTIONS });
} else { } else {
this.presenceChannel.leave(); this.presenceChannel.leave();
@ -204,19 +201,6 @@ export default class Chat extends Service {
return channels.slice(0, this.directMessagesLimit); return channels.slice(0, this.directMessagesLimit);
} }
getActiveChannel() {
let channelId;
if (this.router.currentRouteName === "chat.channel") {
channelId = this.router.currentRoute.params.channelId;
} else {
channelId = document.querySelector(".topic-chat-container.visible")
?.dataset?.chatChannelId;
}
return channelId
? this.allChannels.findBy("id", parseInt(channelId, 10))
: null;
}
async getChannelsWithFilter(filter, opts = { excludeActiveChannel: true }) { async getChannelsWithFilter(filter, opts = { excludeActiveChannel: true }) {
let sortedChannels = this.allChannels.sort((a, b) => { let sortedChannels = this.allChannels.sort((a, b) => {
return new Date(a.last_message_sent_at) > new Date(b.last_message_sent_at) return new Date(a.last_message_sent_at) > new Date(b.last_message_sent_at)
@ -528,7 +512,7 @@ export default class Chat extends Service {
this.setActiveChannel(channel); this.setActiveChannel(channel);
if ( if (
this.chatStateManager.isFullPage || this.chatStateManager.isFullPageActive ||
this.site.mobileView || this.site.mobileView ||
this.chatStateManager.isFullPagePreferred this.chatStateManager.isFullPagePreferred
) { ) {

View File

@ -11,13 +11,13 @@
class={{concat-class class={{concat-class
"full-page-chat" "full-page-chat"
(if (if
this.site.siteSettings.enable_sidebar this.siteSettings.enable_sidebar
"full-page-chat-sidebar-enabled" "full-page-chat-sidebar-enabled"
) )
}} }}
> >
{{#if {{#if
(and (not this.site.siteSettings.enable_sidebar) (not this.site.mobileView)) (and (not this.siteSettings.enable_sidebar) (not this.site.mobileView))
}} }}
<ChannelsList @onSelect={{action "switchChannel"}} /> <ChannelsList @onSelect={{action "switchChannel"}} />
{{/if}} {{/if}}

View File

@ -8,7 +8,7 @@
role="region" role="region"
aria-label={{i18n "chat.aria_roles.channels_list"}} aria-label={{i18n "chat.aria_roles.channels_list"}}
class="channels-list" class="channels-list"
{{on "scroll" (if this.chatStateManager.isFullPage this.storeScrollPosition (noop))}} {{on "scroll" (if this.chatStateManager.isFullPageActive this.storeScrollPosition (noop))}}
> >
{{#if this.displayPublicChannels}} {{#if this.displayPublicChannels}}
<div class="chat-channel-divider public-channels-section"> <div class="chat-channel-divider public-channels-section">

View File

@ -21,8 +21,6 @@
{{#if this.previewedChannel}} {{#if this.previewedChannel}}
<ChatLivePane <ChatLivePane
@chatChannel={{this.previewedChannel}} @chatChannel={{this.previewedChannel}}
@expanded={{true}}
@floatHidden={{false}}
@includeHeader={{false}} @includeHeader={{false}}
@onSwitchChannel={{action "onSwitchFromDraftChannel"}} @onSwitchChannel={{action "onSwitchFromDraftChannel"}}
/> />

View File

@ -0,0 +1,85 @@
{{#if this.chatStateManager.isDrawerActive}}
<div data-chat-channel-id={{this.chat.activeChannel.id}} class={{concat-class "chat-drawer" (if this.chatStateManager.isDrawerExpanded "is-expanded")}}>
<div class="chat-drawer-container">
<div
role="region"
aria-label={{i18n "chat.aria_roles.header"}}
class="chat-drawer-header"
>
{{#if (and this.draftChannelView this.chatStateManager.isDrawerExpanded)}}
<div class="chat-drawer-header__left-actions">
<div class="chat-drawer-header__top-line">
<LinkTo title={{i18n "chat.return_to_list"}} class="chat-drawer-header__return-to-channels-btn" @route="chat">
{{d-icon "chevron-left"}}
</LinkTo>
</div>
</div>
<span class="chat-drawer-header__title">
<div class="chat-drawer-header__top-line">
{{i18n "chat.direct_message_creator.title"}}
</div>
</span>
{{else if this.chatView}}
{{#if this.chatStateManager.isDrawerExpanded}}
<LinkTo title={{i18n "chat.return_to_list"}} class="chat-drawer-header__return-to-channels-btn" @route="chat">
{{d-icon "chevron-left"}}
</LinkTo>
{{/if}}
{{#if this.chat.activeChannel}}
{{#if this.chatStateManager.isDrawerExpanded}}
<LinkTo @route={{this.infoTabRoute}} @models={{array this.chat.activeChannel.id (slugify-channel this.chat.activeChannel)}} class="chat-drawer-header__title">
<div class="chat-drawer-header__top-line">
<ChatChannelTitle @channel={{this.chat.activeChannel}} />
</div>
</LinkTo>
{{else}}
<div role="button" {{on "click" (action "toggleExpand")}} class="chat-drawer-header__title">
<div class="chat-drawer-header__top-line">
<ChatChannelTitle @channel={{this.chat.activeChannel}}>
{{#if this.unreadCount}}
<span class="chat-unread-count">{{this.unreadCount}}</span>
{{/if}}
</ChatChannelTitle>
</div>
</div>
{{/if}}
{{/if}}
{{else}}
<span class="chat-drawer-header__title">
<div class="chat-drawer-header__top-line">
{{i18n "chat.heading"}}
</div>
</span>
{{/if}}
<div class="chat-drawer-header__right-actions">
<div class="chat-drawer-header__top-line {{this.topLineClass}}">
{{#if this.chatStateManager.isDrawerExpanded}}
<DButton @icon="discourse-expand" class="btn-flat btn-link chat-drawer-header__full-screen-btn" @title={{"chat.open_full_page"}} @action={{this.openInFullPage}} />
{{/if}}
<FlatButton @icon={{this.expandIcon}} @class="chat-drawer-header__expand-btn" @action={{action "toggleExpand"}} @title="chat.collapse" />
{{#if this.showClose}}
<FlatButton @icon="times" @action={{action "close"}} @title="chat.close" @class="chat-drawer-header__close-btn" />
{{/if}}
</div>
</div>
</div>
{{#if this.chatStateManager.isDrawerExpanded}}
<div class="chat-drawer-content">
{{#if (and this.chatView this.chat.activeChannel)}}
<ChatLivePane @chatChannel={{this.chat.activeChannel}} @onSwitchChannel={{action "switchChannel"}} />
{{else if this.draftChannelView}}
<ChatDraftChannelScreen @onSwitchChannel={{action "switchChannel"}} />
{{else}}
<ChannelsList @onOpenView={{action "openURL"}} @onSelect={{action "switchChannel"}} />
{{/if}}
</div>
{{/if}}
</div>
</div>
{{/if}}

View File

@ -1,4 +1,4 @@
{{#if (and this.chatStateManager.isFullPage this.includeHeader)}} {{#if (and this.chatStateManager.isFullPageActive this.includeHeader)}}
<div <div
class="chat-full-page-header class="chat-full-page-header
{{unless this.chatChannel.isFollowing "-not-following"}}" {{unless this.chatChannel.isFollowing "-not-following"}}"
@ -16,7 +16,7 @@
{{#if this.showCloseFullScreenBtn}} {{#if this.showCloseFullScreenBtn}}
<div class="chat-full-page-header__right-actions"> <div class="chat-full-page-header__right-actions">
<DButton @icon="discourse-compress" @title="chat.close_full_page" class="open-drawer-btn btn-flat no-text" @action={{action "onCloseFullScreen"}} /> <DButton @icon="discourse-compress" @title="chat.close_full_page" class="open-drawer-btn btn-flat no-text" @action={{action this.onCloseFullScreen}} />
</div> </div>
{{/if}} {{/if}}
</div> </div>
@ -86,14 +86,12 @@
</div> </div>
{{/if}} {{/if}}
{{#if this.expanded}} {{#if this.selectingMessages}}
{{#if this.selectingMessages}} <ChatSelectionManager @selectedMessageIds={{this.selectedMessageIds}} @chatChannel={{this.chatChannel}} @canModerate={{this.details.can_moderate}} @cancelSelecting={{action "cancelSelecting"}} />
<ChatSelectionManager @selectedMessageIds={{this.selectedMessageIds}} @chatChannel={{this.chatChannel}} @canModerate={{this.details.can_moderate}} @cancelSelecting={{action "cancelSelecting"}} /> {{else}}
{{#if (or this.chatChannel.isDraft this.chatChannel.isFollowing)}}
<ChatComposer @draft={{this.draft}} @details={{this.details}} @canInteractWithChat={{this.canInteractWithChat}} @sendMessage={{action "sendMessage"}} @editMessage={{action "editMessage"}} @setReplyTo={{action "setReplyTo"}} @loading={{this.sendingLoading}} @editingMessage={{readonly this.editingMessage}} @onCancelEditing={{this.cancelEditing}} @setInReplyToMsg={{this.setInReplyToMsg}} @onEditLastMessageRequested={{this.editLastMessageRequested}} @onValueChange={{action "composerValueChanged"}} @chatChannel={{this.chatChannel}} />
{{else}} {{else}}
{{#if (or this.chatChannel.isDraft this.chatChannel.isFollowing)}} <ChatChannelPreviewCard @channel={{this.chatChannel}} />
<ChatComposer @draft={{this.draft}} @details={{this.details}} @canInteractWithChat={{this.canInteractWithChat}} @sendMessage={{action "sendMessage"}} @editMessage={{action "editMessage"}} @setReplyTo={{action "setReplyTo"}} @loading={{this.sendingLoading}} @editingMessage={{readonly this.editingMessage}} @onCancelEditing={{this.cancelEditing}} @setInReplyToMsg={{this.setInReplyToMsg}} @onEditLastMessageRequested={{this.editLastMessageRequested}} @onValueChange={{action "composerValueChanged"}} @fullPage={{this.fullPage}} @chatChannel={{this.chatChannel}} />
{{else}}
<ChatChannelPreviewCard @channel={{this.chatChannel}} />
{{/if}}
{{/if}} {{/if}}
{{/if}} {{/if}}

View File

@ -1,6 +1,6 @@
<div class="chat-message-actions-container" data-id={{this.message.id}}> <div class="chat-message-actions-container" data-id={{this.message.id}}>
<div class="chat-message-actions"> <div class="chat-message-actions">
{{#if this.chatStateManager.isFullPage}} {{#if this.chatStateManager.isFullPageActive}}
{{#each this.emojiReactions as |reaction|}} {{#each this.emojiReactions as |reaction|}}
<ChatMessageReaction @reaction={{reaction}} @react={{this.messageActions.react}} @class="show" /> <ChatMessageReaction @reaction={{reaction}} @react={{this.messageActions.react}} @class="show" />
{{/each}} {{/each}}

View File

@ -1,3 +1,3 @@
{{#if this.chat.activeChannel}} {{#if this.chat.activeChannel}}
<ChatLivePane @chatChannel={{this.chat.activeChannel}} @expanded={{true}} @floatHidden={{false}} @onBackClick={{action "navigateToIndex"}} @onSwitchChannel={{action "switchChannel"}} /> <ChatLivePane @chatChannel={{this.chat.activeChannel}} @onBackClick={{action "navigateToIndex"}} @onSwitchChannel={{action "switchChannel"}} />
{{/if}} {{/if}}

View File

@ -1,86 +0,0 @@
<div class="chat-drawer">
<div
class={{this.containerClassNames}}
data-chat-channel-id={{this.chat.activeChannel.id}}
>
<div
role="region"
aria-label={{i18n "chat.aria_roles.header"}}
class="topic-chat-drawer-header"
>
{{#if (and this.draftChannelView this.expanded)}}
<div class="topic-chat-drawer-header__left-actions">
<div class="topic-chat-drawer-header__top-line">
<LinkTo title={{i18n "chat.return_to_list"}} class="topic-chat-drawer-header__return-to-channels-btn" @route="chat">
{{d-icon "chevron-left"}}
</LinkTo>
</div>
</div>
<span class="topic-chat-drawer-header__title">
<div class="topic-chat-drawer-header__top-line">
{{i18n "chat.direct_message_creator.title"}}
</div>
</span>
{{else if this.chatView}}
{{#if this.expanded}}
<LinkTo title={{i18n "chat.return_to_list"}} class="topic-chat-drawer-header__return-to-channels-btn" @route="chat">
{{d-icon "chevron-left"}}
</LinkTo>
{{/if}}
{{#if this.chat.activeChannel}}
{{#if this.expanded}}
<LinkTo @route={{this.infoTabRoute}} @models={{array this.chat.activeChannel.id (slugify-channel this.chat.activeChannel)}} class="topic-chat-drawer-header__title">
<div class="topic-chat-drawer-header__top-line">
<ChatChannelTitle @channel={{this.chat.activeChannel}} />
</div>
</LinkTo>
{{else}}
<div role="button" {{on "click" (action "toggleExpand")}} class="topic-chat-drawer-header__title">
<div class="topic-chat-drawer-header__top-line">
<ChatChannelTitle @channel={{this.chat.activeChannel}}>
{{#if this.unreadCount}}
<span class="chat-unread-count">{{this.unreadCount}}</span>
{{/if}}
</ChatChannelTitle>
</div>
</div>
{{/if}}
{{/if}}
{{else}}
<span class="topic-chat-drawer-header__title">
<div class="topic-chat-drawer-header__top-line">
{{i18n "chat.heading"}}
</div>
</span>
{{/if}}
<div class="topic-chat-drawer-header__right-actions">
<div class="topic-chat-drawer-header__top-line {{this.topLineClass}}">
{{#if this.expanded}}
<DButton @icon="discourse-expand" class="btn-flat btn-link topic-chat-drawer-header__full-screen-btn" @title={{"chat.open_full_page"}} @action={{this.openInFullPage}} />
{{/if}}
<FlatButton @icon={{this.expandIcon}} @class="topic-chat-drawer-header__expand-btn" @action={{action "toggleExpand"}} @title="chat.collapse" />
{{#if this.showClose}}
<FlatButton @icon="times" @action={{action "close"}} @title="chat.close" @class="topic-chat-drawer-header__close-btn" />
{{/if}}
</div>
</div>
</div>
{{#if this.expanded}}
<div class="topic-chat-drawer-content">
{{#if (and this.chatView this.chat.activeChannel)}}
<ChatLivePane @chatChannel={{this.chat.activeChannel}} @expanded={{this.expanded}} @floatHidden={{this.hidden}} @onSwitchChannel={{action "switchChannel"}} />
{{else if this.draftChannelView}}
<ChatDraftChannelScreen @onSwitchChannel={{action "switchChannel"}} />
{{else}}
<ChannelsList @floatHidden={{this.hidden}} @onOpenView={{action "openURL"}} @onSelect={{action "switchChannel"}} />
{{/if}}
</div>
{{/if}}
</div>
</div>

View File

@ -40,7 +40,10 @@ export default createWidget("header-chat-link", {
chatLinkHtml(indicatorNode) { chatLinkHtml(indicatorNode) {
return h( return h(
`a.icon${ `a.icon${
this.chatStateManager.isFullPage || this.chat.chatOpen ? ".active" : "" this.chatStateManager.isFullPageActive ||
this.chatStateManager.isDrawerActive
? ".active"
: ""
}`, }`,
{ attributes: { tabindex: 0 } }, { attributes: { tabindex: 0 } },
[iconNode("comment"), indicatorNode].filter(Boolean) [iconNode("comment"), indicatorNode].filter(Boolean)
@ -61,7 +64,7 @@ export default createWidget("header-chat-link", {
}, },
click() { click() {
if (this.chatStateManager.isFullPage && !this.site.mobileView) { if (this.chatStateManager.isFullPageActive && !this.site.mobileView) {
return; return;
} }

View File

@ -21,8 +21,6 @@
.chat-name, .chat-name,
.category-chat-name, .category-chat-name,
.topic-chat-name,
.tag-chat-name,
&__usernames, &__usernames,
.dm-usernames { .dm-usernames {
@include ellipsis; @include ellipsis;

View File

@ -1,8 +1,8 @@
body.composer-open .topic-chat-float-container { body.composer-open .chat-drawer-outlet-container {
bottom: 11px; // prevent height of grippie from obscuring ...is typing indicator bottom: 11px; // prevent height of grippie from obscuring ...is typing indicator
} }
.topic-chat-float-container { .chat-drawer-outlet-container {
font-family: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, font-family: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
// higher than timeline, lower than composer, lower than user card (bump up below) // higher than timeline, lower than composer, lower than user card (bump up below)
@ -60,22 +60,24 @@ body.composer-open .topic-chat-float-container {
.chat-drawer { .chat-drawer {
align-self: flex-end; align-self: flex-end;
}
.topic-chat-container { .chat-drawer-container {
background: var(--secondary); background: var(--secondary);
border: 1px solid var(--primary-low); border: 1px solid var(--primary-low);
border-bottom: 0; border-bottom: 0;
border-top-left-radius: 8px; border-top-left-radius: 8px;
border-top-right-radius: 8px; border-top-right-radius: 8px;
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.125); box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.125);
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
}
&.expanded { &.is-expanded {
max-height: $float-height; .chat-drawer-container {
height: calc(85vh - var(--composer-height, 0px)); max-height: $float-height;
height: calc(85vh - var(--composer-height, 0px));
}
} }
.chat-live-pane { .chat-live-pane {
@ -83,30 +85,30 @@ body.composer-open .topic-chat-float-container {
} }
} }
.topic-chat-drawer-header__left-actions { .chat-drawer-header__left-actions {
display: flex; display: flex;
height: 100%; height: 100%;
} }
.topic-chat-drawer-header__right-actions { .chat-drawer-header__right-actions {
display: flex; display: flex;
height: 100%; height: 100%;
margin-left: auto; margin-left: auto;
} }
.topic-chat-drawer-header__top-line { .chat-drawer-header__top-line {
height: 2.5rem; height: 2.5rem;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.topic-chat-drawer-header__bottom-line { .chat-drawer-header__bottom-line {
height: 1.5rem; height: 1.5rem;
display: flex; display: flex;
align-items: start; align-items: start;
} }
.topic-chat-drawer-header__title { .chat-drawer-header__title {
@include ellipsis; @include ellipsis;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -120,7 +122,7 @@ body.composer-open .topic-chat-float-container {
} }
} }
.topic-chat-drawer-header { .chat-drawer-header {
box-sizing: border-box; box-sizing: border-box;
border-bottom: solid 1px var(--primary-low); border-bottom: solid 1px var(--primary-low);
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
@ -138,13 +140,13 @@ body.composer-open .topic-chat-float-container {
width: 100%; width: 100%;
.chat-name, .chat-name,
.topic-chat-name, .chat-drawer-name,
.category-chat-name, .category-chat-name,
.dm-usernames { .dm-usernames {
color: var(--primary); color: var(--primary);
} }
.category-chat-badge, .category-chat-badge,
.topic-chat-badge { .chat-drawer-badge {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-content: center; align-content: center;
@ -213,7 +215,7 @@ body.composer-open .topic-chat-float-container {
} }
} }
.topic-chat-drawer-content { .chat-drawer-content {
box-sizing: border-box; box-sizing: border-box;
height: 100%; height: 100%;
min-height: 1px; min-height: 1px;

View File

@ -288,7 +288,7 @@
} }
.has-full-page-chat .chat-message .onebox:not(img), .has-full-page-chat .chat-message .onebox:not(img),
.topic-chat-float-container .chat-message .onebox { .chat-drawer-container .chat-message .onebox {
margin: 0.5em 0; margin: 0.5em 0;
border-width: 2px; border-width: 2px;
@ -311,7 +311,7 @@
} }
} }
.topic-chat-float-container .chat-message .onebox { .chat-drawer-container .chat-message .onebox {
width: 85%; width: 85%;
border: 2px solid var(--primary-low); border: 2px solid var(--primary-low);

View File

@ -4,7 +4,7 @@
gap: 0.5rem; gap: 0.5rem;
padding: 0.5rem; padding: 0.5rem;
.topic-chat-drawer-content & { .chat-drawer-content & {
flex-direction: column; flex-direction: column;
} }
@ -12,7 +12,7 @@
display: flex; display: flex;
gap: 0.5rem; gap: 0.5rem;
.topic-chat-drawer-content & { .chat-drawer-content & {
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
} }

View File

@ -471,9 +471,6 @@ $float-height: 530px;
&:hover, &:hover,
&.active { &.active {
.topic-chat-badge .topic-chat-icon .d-icon {
background: transparent;
}
&.active { &.active {
font-weight: 600; font-weight: 600;
} }
@ -632,8 +629,6 @@ body.has-full-page-chat {
background-color: var(--primary-low); background-color: var(--primary-low);
.chat-channel-title { .chat-channel-title {
.category-chat-name, .category-chat-name,
.topic-chat-name,
.tag-chat-name,
.chat-name, .chat-name,
.dm-usernames { .dm-usernames {
color: var(--primary); color: var(--primary);
@ -664,8 +659,6 @@ body.has-full-page-chat {
.chat-channel-title { .chat-channel-title {
.category-chat-name, .category-chat-name,
.topic-chat-name,
.tag-chat-name,
.chat-name, .chat-name,
.dm-usernames { .dm-usernames {
color: var(--primary); color: var(--primary);
@ -735,8 +728,7 @@ body.has-full-page-chat {
} }
.category-chat-name, .category-chat-name,
.dm-username, .dm-username {
.topic-chat-name {
font-weight: 700; font-weight: 700;
font-size: var(--font-up-1); font-size: var(--font-up-1);
line-height: var(--font-up-1); line-height: var(--font-up-1);
@ -754,9 +746,7 @@ body.has-full-page-chat {
} }
.channels-list { .channels-list {
.tag-chat-badge, .category-chat-badge {
.category-chat-badge,
.topic-chat-badge {
color: var(--primary-low-mid); color: var(--primary-low-mid);
display: flex; display: flex;
align-items: center; align-items: center;
@ -769,12 +759,6 @@ body.has-full-page-chat {
} }
} }
.topic-chat-badge {
.d-icon {
z-index: 1;
}
}
.category-chat-private .d-icon { .category-chat-private .d-icon {
background-color: var(--secondary); background-color: var(--secondary);
position: absolute; position: absolute;

View File

@ -34,7 +34,7 @@ RSpec.describe "Navigation", type: :system, js: true do
visit("/") visit("/")
chat_page.open_from_header chat_page.open_from_header
expect(page).to have_css(".topic-chat-container.expanded.visible") expect(page).to have_css(".chat-drawer.is-expanded")
end end
end end
@ -62,12 +62,12 @@ RSpec.describe "Navigation", type: :system, js: true do
chat_page.open chat_page.open
chat_page.minimize_full_page chat_page.minimize_full_page
expect(page).to have_css(".topic-chat-container.expanded.visible") expect(page).to have_css(".chat-drawer.is-expanded")
visit("/") visit("/")
chat_page.open_from_header chat_page.open_from_header
expect(page).to have_css(".topic-chat-container.expanded.visible") expect(page).to have_css(".chat-drawer.is-expanded")
end end
end end
@ -114,7 +114,7 @@ RSpec.describe "Navigation", type: :system, js: true do
find("a", text: "foo").click find("a", text: "foo").click
expect(page).to have_css( expect(page).to have_css(
".topic-chat-container.expanded.visible .chat-message-container.highlighted[data-id='#{message.id}']", ".chat-drawer.is-expanded .chat-message-container.highlighted[data-id='#{message.id}']",
) )
end end
end end
@ -156,7 +156,7 @@ RSpec.describe "Navigation", type: :system, js: true do
sidebar_page.open_draft_channel sidebar_page.open_draft_channel
expect(page).to have_current_path("/") expect(page).to have_current_path("/")
expect(page).to have_css(".topic-chat-container.expanded.visible .direct-message-creator") expect(page).to have_css(".chat-drawer.is-expanded .direct-message-creator")
end end
end end
@ -167,7 +167,7 @@ RSpec.describe "Navigation", type: :system, js: true do
chat_drawer_page.open_draft_channel chat_drawer_page.open_draft_channel
expect(page).to have_current_path("/") expect(page).to have_current_path("/")
expect(page).to have_css(".topic-chat-container.expanded.visible .direct-message-creator") expect(page).to have_css(".chat-drawer.is-expanded .direct-message-creator")
end end
end end
@ -180,7 +180,7 @@ RSpec.describe "Navigation", type: :system, js: true do
sidebar_page.open_draft_channel sidebar_page.open_draft_channel
expect(page).to have_current_path("/chat/draft-channel") expect(page).to have_current_path("/chat/draft-channel")
expect(page).not_to have_css(".topic-chat-container.expanded.visible") expect(page).not_to have_css(".chat-drawer.is-expanded")
end end
end end
@ -191,7 +191,7 @@ RSpec.describe "Navigation", type: :system, js: true do
chat_drawer_page.open_browse chat_drawer_page.open_browse
expect(page).to have_current_path("/chat/browse/open") expect(page).to have_current_path("/chat/browse/open")
expect(page).not_to have_css(".topic-chat-container.expanded.visible") expect(page).not_to have_css(".chat-drawer.is-expanded")
end end
end end
@ -202,7 +202,7 @@ RSpec.describe "Navigation", type: :system, js: true do
sidebar_page.open_browse sidebar_page.open_browse
expect(page).to have_current_path("/chat/browse/open") expect(page).to have_current_path("/chat/browse/open")
expect(page).not_to have_css(".topic-chat-container.expanded.visible") expect(page).not_to have_css(".chat-drawer.is-expanded")
end end
end end
@ -216,7 +216,7 @@ RSpec.describe "Navigation", type: :system, js: true do
chat_page.open_from_header chat_page.open_from_header
expect(page).to have_current_path("/") expect(page).to have_current_path("/")
expect(page).to have_css(".topic-chat-container.expanded.visible") expect(page).to have_css(".chat-drawer.is-expanded")
expect(page).to have_content(category_channel_2.title) expect(page).to have_content(category_channel_2.title)
end end
end end

View File

@ -3,7 +3,7 @@
module PageObjects module PageObjects
module Pages module Pages
class ChatDrawer < PageObjects::Pages::Base class ChatDrawer < PageObjects::Pages::Base
VISIBLE_DRAWER = ".topic-chat-container.expanded.visible" VISIBLE_DRAWER = ".chat-drawer.is-expanded"
def open_browse def open_browse
find("#{VISIBLE_DRAWER} .open-browse-page-btn").click find("#{VISIBLE_DRAWER} .open-browse-page-btn").click
end end
@ -13,11 +13,11 @@ module PageObjects
end end
def close def close
find("#{VISIBLE_DRAWER} .topic-chat-drawer-header__close-btn").click find("#{VISIBLE_DRAWER} .chat-drawer-header__close-btn").click
end end
def open_index def open_index
find("#{VISIBLE_DRAWER} .topic-chat-drawer-header__return-to-channels-btn").click find("#{VISIBLE_DRAWER} .chat-drawer-header__return-to-channels-btn").click
end end
def open_channel(channel) def open_channel(channel)
@ -27,7 +27,7 @@ module PageObjects
end end
def maximize def maximize
find("#{VISIBLE_DRAWER} .topic-chat-drawer-header__full-screen-btn").click find("#{VISIBLE_DRAWER} .chat-drawer-header__full-screen-btn").click
end end
end end
end end

View File

@ -0,0 +1,44 @@
# frozen_string_literal: true
RSpec.describe "Navigation", type: :system, js: true do
fab!(:user_1) { Fabricate(:admin) }
fab!(:category_channel_1) { Fabricate(:category_channel) }
fab!(:category_channel_2) { Fabricate(:category_channel) }
let(:chat_page) { PageObjects::Pages::Chat.new }
let(:chat_drawer_page) { PageObjects::Pages::ChatDrawer.new }
before do
chat_system_bootstrap(user_1, [category_channel_1, category_channel_2])
sign_in(user_1)
end
context "when drawer is closed" do
before { visit("/") }
context "when pressing dash" do
it "opens the drawer" do
find("body").send_keys("-")
expect(page).to have_css(".chat-drawer.is-expanded")
end
end
end
context "when drawer is opened" do
before do
visit("/")
chat_page.open_from_header
end
context "when pressing escape" do
it "opens the drawer" do
expect(page).to have_css(".chat-drawer.is-expanded")
chat_drawer_page.open_channel(category_channel_1)
find(".chat-composer-input").send_keys(:escape)
expect(page).to_not have_css(".chat-drawer.is-expanded")
end
end
end
end

View File

@ -15,6 +15,8 @@ acceptance(
needs.settings({ needs.settings({
chat_enabled: true, chat_enabled: true,
enable_sidebar: false,
enable_experimental_sidebar_hamburger: false,
}); });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {

View File

@ -18,7 +18,7 @@ import {
} from "../helpers/chat-pretenders"; } from "../helpers/chat-pretenders";
acceptance("Discourse Chat - Composer", function (needs) { acceptance("Discourse Chat - Composer", function (needs) {
needs.user({ id: 1, has_chat_enabled: true }); needs.user({ has_chat_enabled: true });
needs.settings({ chat_enabled: true, enable_rich_text_paste: true }); needs.settings({ chat_enabled: true, enable_rich_text_paste: true });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
baseChatPretenders(server, helper); baseChatPretenders(server, helper);

View File

@ -5,7 +5,6 @@ import {
loggedInUser, loggedInUser,
query, query,
queryAll, queryAll,
visible,
} from "discourse/tests/helpers/qunit-helpers"; } from "discourse/tests/helpers/qunit-helpers";
import { import {
click, click,
@ -84,9 +83,9 @@ acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
test("channel selector opens channel in float", async function (assert) { test("channel selector opens channel in float", async function (assert) {
await visit("/latest"); await visit("/latest");
await showModal("chat-channel-selector-modal"); await showModal("chat-channel-selector-modal");
await settled(); await settled();
assert.ok(exists("#chat-channel-selector-modal-inner")); assert.ok(exists("#chat-channel-selector-modal-inner"));
// All channels should show because the input is blank // All channels should show because the input is blank
@ -110,7 +109,8 @@ acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
); );
await triggerKeyEvent(document.body, "keyup", "Enter"); await triggerKeyEvent(document.body, "keyup", "Enter");
assert.ok(exists(".topic-chat-container.visible"));
assert.ok(exists(".chat-drawer.is-expanded"));
assert.notOk(exists("#chat-channel-selector-modal-inner")); assert.notOk(exists("#chat-channel-selector-modal-inner"));
assert.equal(currentURL(), "/latest"); assert.equal(currentURL(), "/latest");
}); });
@ -164,28 +164,24 @@ acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
test("switching channel with alt+arrow keys in float", async function (assert) { test("switching channel with alt+arrow keys in float", async function (assert) {
await visit("/latest"); await visit("/latest");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click("#chat-channel-row-4"); await click("#chat-channel-row-4");
assert.ok(visible(".topic-chat-float-container"), "chat float is open"); assert.ok(exists(`.chat-drawer.is-expanded[data-chat-channel-id="4"]`));
assert.ok(query(".topic-chat-container").classList.contains("channel-4"));
await triggerKeyEvent(document.body, "keydown", "ArrowDown", { await triggerKeyEvent(document.body, "keydown", "ArrowDown", {
altKey: true, altKey: true,
}); });
assert.ok(query(".topic-chat-container").classList.contains("channel-10")); assert.ok(exists(`.chat-drawer.is-expanded[data-chat-channel-id="10`));
await triggerKeyEvent(document.body, "keydown", "ArrowUp", { await triggerKeyEvent(document.body, "keydown", "ArrowUp", {
altKey: true, altKey: true,
}); });
assert.ok(query(".topic-chat-container").classList.contains("channel-4")); assert.ok(exists(`.chat-drawer.is-expanded[data-chat-channel-id="4"]`));
}); });
test("simple composer formatting shortcuts", async function (assert) { test("simple composer formatting shortcuts", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/latest"); await visit("/latest");
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row"); await click(".chat-channel-row");
@ -230,7 +226,6 @@ acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
const stagedMessageText = "This is a test"; const stagedMessageText = "This is a test";
await visit("/latest"); await visit("/latest");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row"); await click(".chat-channel-row");
await fillIn(".chat-composer-input", stagedMessageText); await fillIn(".chat-composer-input", stagedMessageText);
@ -246,7 +241,6 @@ acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
test("insert link shortcut", async function (assert) { test("insert link shortcut", async function (assert) {
await visit("/latest"); await visit("/latest");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row"); await click(".chat-channel-row");
@ -276,32 +270,7 @@ acceptance("Discourse Chat - Keyboard shortcuts", function (needs) {
); );
}); });
test("Dash key (-) opens chat float", async function (assert) {
await visit("/latest");
this.chatService.set("sidebarActive", false);
await triggerKeyEvent(document.body, "keydown", "-");
assert.ok(exists(".topic-chat-drawer-content"), "chat float is open");
});
test("Pressing Escape when drawer is opened", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/latest");
await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row");
const composerInput = query(".chat-composer-input");
await focus(composerInput);
await triggerKeyEvent(composerInput, "keydown", "Escape");
assert.ok(
exists(".topic-chat-float-container.hidden"),
"it closes the drawer"
);
});
test("Pressing Escape when full page is opened", async function (assert) { test("Pressing Escape when full page is opened", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/chat/channel/75/@hawk"); await visit("/chat/channel/75/@hawk");
const composerInput = query(".chat-composer-input"); const composerInput = query(".chat-composer-input");
await focus(composerInput); await focus(composerInput);

View File

@ -110,7 +110,7 @@ acceptance("Discourse Chat | Quoting in composer", async function (needs) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
assert.ok(visible(".topic-chat-float-container"), "chat float is open"); assert.ok(visible(".chat-drawer-container"), "chat drawer is open");
assert.ok(exists(".chat-message-container")); assert.ok(exists(".chat-message-container"));
const firstMessage = query(".chat-message-container"); const firstMessage = query(".chat-message-container");

View File

@ -61,6 +61,7 @@ acceptance(
needs.settings({ needs.settings({
chat_enabled: true, chat_enabled: true,
chat_allow_archiving_channels: true, chat_allow_archiving_channels: true,
enable_sidebar: false,
}); });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {

View File

@ -65,6 +65,7 @@ acceptance("Discourse Chat - without unread", function (needs) {
has_chat_enabled: true, has_chat_enabled: true,
}); });
needs.settings({ needs.settings({
enable_sidebar: false,
chat_enabled: true, chat_enabled: true,
}); });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
@ -144,8 +145,8 @@ acceptance("Discourse Chat - without unread", function (needs) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
await click(".header-dropdown-toggle.current-user"); await click(".header-dropdown-toggle.current-user");
await click("#quick-access-notifications .chat-mention"); await click("#quick-access-notifications .chat-mention");
assert.ok(visible(".topic-chat-float-container"), "chat float is open"); assert.ok(visible(".chat-drawer-container"), "drawer is open");
assert.ok(query(".topic-chat-container").classList.contains("channel-9")); assert.ok(query(".chat-drawer-container").classList.contains("channel-9"));
}); });
test("notifications for current user and here/all are highlighted", async function (assert) { test("notifications for current user and here/all are highlighted", async function (assert) {
@ -366,20 +367,18 @@ acceptance("Discourse Chat - without unread", function (needs) {
}); });
test("Reply-to is stored in draft", async function (assert) { test("Reply-to is stored in draft", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/latest"); await visit("/latest");
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row"); await click(".chat-channel-row");
await settled(); await settled();
await click(".topic-chat-drawer-header__return-to-channels-btn"); await click(".chat-drawer-header__return-to-channels-btn");
await click(".chat-channel-row.chat-channel-9"); await click(".chat-channel-row.chat-channel-9");
await triggerEvent(".chat-message-container[data-id='174']", "mouseenter"); await triggerEvent(".chat-message-container[data-id='174']", "mouseenter");
await click(".chat-message-actions-container[data-id='174'] .reply-btn"); await click(".chat-message-actions-container[data-id='174'] .reply-btn");
// Reply-to line is present // Reply-to line is present
assert.ok(exists(".chat-composer-message-details .chat-reply")); assert.ok(exists(".chat-composer-message-details .chat-reply"));
await click(".topic-chat-drawer-header__return-to-channels-btn"); await click(".chat-drawer-header__return-to-channels-btn");
await click(".chat-channel-row.chat-channel-11"); await click(".chat-channel-row.chat-channel-11");
// Reply-to line is gone since switching channels // Reply-to line is gone since switching channels
assert.notOk(exists(".chat-composer-message-details .chat-reply")); assert.notOk(exists(".chat-composer-message-details .chat-reply"));
@ -390,13 +389,13 @@ acceptance("Discourse Chat - without unread", function (needs) {
await click(".cancel-message-action"); await click(".cancel-message-action");
// Go back to channel 9 and check that reply-to is present // Go back to channel 9 and check that reply-to is present
await click(".topic-chat-drawer-header__return-to-channels-btn"); await click(".chat-drawer-header__return-to-channels-btn");
await click(".chat-channel-row.chat-channel-9"); await click(".chat-channel-row.chat-channel-9");
// Now reply-to should be back and loaded from draft // Now reply-to should be back and loaded from draft
assert.ok(exists(".chat-composer-message-details .chat-reply")); assert.ok(exists(".chat-composer-message-details .chat-reply"));
// Go back one for time to channel 7 and make sure reply-to is gone // Go back one for time to channel 7 and make sure reply-to is gone
await click(".topic-chat-drawer-header__return-to-channels-btn"); await click(".chat-drawer-header__return-to-channels-btn");
await click(".chat-channel-row.chat-channel-11"); await click(".chat-channel-row.chat-channel-11");
assert.notOk(exists(".chat-composer-message-details .chat-reply")); assert.notOk(exists(".chat-composer-message-details .chat-reply"));
}); });
@ -725,7 +724,7 @@ Widget.triangulate(arg: "test")
}); });
test("creating a new direct message channel from popup chat works", async function (assert) { test("creating a new direct message channel from popup chat works", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/chat");
await click(".open-draft-channel-page-btn"); await click(".open-draft-channel-page-btn");
await fillIn(".filter-usernames", "hawk"); await fillIn(".filter-usernames", "hawk");
await click('.chat-user-avatar-container[data-user-card="hawk"]'); await click('.chat-user-avatar-container[data-user-card="hawk"]');
@ -978,9 +977,8 @@ acceptance(
test("Expand button takes you to full page chat on the correct channel", async function (assert) { test("Expand button takes you to full page chat on the correct channel", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".topic-chat-drawer-header__full-screen-btn"); await click(".chat-drawer-header__full-screen-btn");
assert.equal(currentURL(), `/chat/channel/11/another-category`); assert.equal(currentURL(), `/chat/channel/11/another-category`);
}); });
@ -1032,7 +1030,7 @@ acceptance(
); );
acceptance( acceptance(
"Discourse Chat - Expand and collapse chat drawer (topic-chat-float)", "Discourse Chat - Expand and collapse drawer (chat-drawer)",
function (needs) { function (needs) {
needs.user({ needs.user({
admin: false, admin: false,
@ -1061,62 +1059,59 @@ acceptance(
}); });
}); });
test("chat drawer can be collapsed and expanded", async function (assert) { test("drawer can be collapsed and expanded", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--expanded"), visible(".chat-drawer-header__top-line--expanded"),
"chat float is expanded" "drawer is expanded"
); );
await click(".topic-chat-drawer-header__expand-btn"); await click(".chat-drawer-header__expand-btn");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--collapsed"), visible(".chat-drawer-header__top-line--collapsed"),
"chat float is collapsed" "drawer is collapsed"
); );
await click(".topic-chat-drawer-header__expand-btn"); await click(".chat-drawer-header__expand-btn");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--expanded"), visible(".chat-drawer-header__top-line--expanded"),
"chat float is expanded" "drawer is expanded"
); );
}); });
test("chat drawer title links to channel info when expanded", async function (assert) { test("drawer title links to channel info when expanded", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--expanded"), visible(".chat-drawer-header__top-line--expanded"),
"chat float is expanded" "drawer is expanded"
); );
await click("#chat-channel-row-9"); await click("#chat-channel-row-9");
await click(".topic-chat-drawer-header__title"); await click(".chat-drawer-header__title");
assert.equal(currentURL(), `/chat/channel/9/site/info/members`); assert.equal(currentURL(), `/chat/channel/9/site/info/members`);
}); });
test("chat drawer title expands the chat drawer when collapsed", async function (assert) { test("drawer title expands the drawer when collapsed", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row"); await click(".chat-channel-row");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--expanded"), visible(".chat-drawer-header__top-line--expanded"),
"chat float is expanded" "drawer is expanded"
); );
await click(".topic-chat-drawer-header__expand-btn"); await click(".chat-drawer-header__expand-btn");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--collapsed"), visible(".chat-drawer-header__top-line--collapsed"),
"chat float is collapsed" "drawer is collapsed"
); );
await click(".topic-chat-drawer-header__title"); await click(".chat-drawer-header__title");
assert.ok( assert.ok(
visible(".topic-chat-drawer-header__top-line--expanded"), visible(".chat-drawer-header__top-line--expanded"),
"chat float is expanded" "drawer is expanded"
); );
}); });
} }
@ -1164,14 +1159,12 @@ acceptance(
); );
}); });
test("Chat float open to DM channel with unread messages with sidebar off", async function (assert) { test("drawer open to DM channel with unread messages with sidebar off", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
this.chatService.set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click("#chat-channel-row-75"); await click("#chat-channel-row-75");
const chatContainer = query(".topic-chat-container"); const chatContainer = query(".chat-drawer");
assert.ok(chatContainer.classList.contains("channel-75")); assert.strictEqual(chatContainer.dataset.chatChannelId, "75");
}); });
test("Chat full page open to DM channel with unread messages with sidebar on", async function (assert) { test("Chat full page open to DM channel with unread messages with sidebar on", async function (assert) {
@ -1400,10 +1393,10 @@ acceptance("Discourse Chat - image uploads", function (needs) {
test("uploading files in chat works", async function (assert) { test("uploading files in chat works", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
this.container.lookup("service:chat").set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row");
assert.ok(visible(".topic-chat-float-container"), "chat float is open"); assert.ok(exists(".chat-drawer.is-expanded"), "drawer is open");
const appEvents = loggedInUser().appEvents; const appEvents = loggedInUser().appEvents;
const done = assert.async(); const done = assert.async();
@ -1462,7 +1455,7 @@ acceptance("Discourse Chat - image uploads", function (needs) {
this.container.lookup("service:chat").set("sidebarActive", false); this.container.lookup("service:chat").set("sidebarActive", false);
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row"); await click(".chat-channel-row");
assert.ok(visible(".topic-chat-float-container"), "chat float is open"); assert.ok(visible(".chat-drawer-container"), "drawer is open");
const appEvents = loggedInUser().appEvents; const appEvents = loggedInUser().appEvents;
const done = assert.async(); const done = assert.async();
@ -1811,34 +1804,6 @@ acceptance("Discourse Chat - Direct Message Creator", function (needs) {
}); });
}); });
acceptance("Discourse Chat - Drawer", function (needs) {
needs.user({ has_chat_enabled: true });
needs.settings({ chat_enabled: true });
needs.pretender((server, helper) => {
baseChatPretenders(server, helper);
chatChannelPretender(server, helper);
});
needs.hooks.beforeEach(function () {
Object.defineProperty(this, "chatService", {
get: () => this.container.lookup("service:chat"),
});
});
test("Position after closing reduced composer", async function (assert) {
await visit("/t/internationalization-localization/280");
await click(".btn.create");
await click(".toggle-preview");
await click(".header-dropdown-toggle.open-chat");
await click(".save-or-cancel .cancel");
const float = document.querySelector(".topic-chat-float-container");
const key = "--composer-right";
const value = getComputedStyle(float).getPropertyValue(key);
assert.strictEqual(value, "15px");
});
});
function createFile(name, type = "image/png") { function createFile(name, type = "image/png") {
// the blob content doesn't matter at all, just want it to be random-ish // the blob content doesn't matter at all, just want it to be random-ish
const file = new Blob([(Math.random() + 1).toString(36).substring(2)], { const file = new Blob([(Math.random() + 1).toString(36).substring(2)], {

View File

@ -418,7 +418,7 @@ acceptance("Discourse Chat - Core Sidebar", function (needs) {
await click(".sidebar-section-chat-dms .sidebar-section-header-button"); await click(".sidebar-section-chat-dms .sidebar-section-header-button");
assert.ok(exists(".direct-message-creator")); assert.ok(exists(".direct-message-creator"));
assert.ok(exists(".topic-chat-container.expanded.visible")); assert.ok(exists(".chat-drawer.is-expanded"));
assert.strictEqual(currentURL(), "/"); assert.strictEqual(currentURL(), "/");
}); });

View File

@ -4,8 +4,6 @@ import {
acceptance, acceptance,
exists, exists,
loggedInUser, loggedInUser,
query,
visible,
} from "discourse/tests/helpers/qunit-helpers"; } from "discourse/tests/helpers/qunit-helpers";
import { click, visit } from "@ember/test-helpers"; import { click, visit } from "@ember/test-helpers";
import { import {
@ -82,7 +80,6 @@ acceptance("Discourse Chat - User card test", function (needs) {
}); });
test("user card has chat button that opens the correct channel", async function (assert) { test("user card has chat button that opens the correct channel", async function (assert) {
this.chatService.set("sidebarActive", false);
await visit("/"); await visit("/");
await click(".header-dropdown-toggle.open-chat"); await click(".header-dropdown-toggle.open-chat");
await click(".chat-channel-row.chat-channel-9"); await click(".chat-channel-row.chat-channel-9");
@ -92,8 +89,7 @@ acceptance("Discourse Chat - User card test", function (needs) {
await click(".user-card-chat-btn"); await click(".user-card-chat-btn");
assert.ok(visible(".topic-chat-float-container"), "chat float is open"); assert.ok(exists(`.chat-drawer.is-expanded[data-chat-channel-id="75"]`));
assert.ok(query(".topic-chat-container").classList.contains("channel-75"));
}); });
}); });

View File

@ -32,7 +32,7 @@ module("Discourse Chat | Component | sidebar-channels", function (hooks) {
template: hbs`{{sidebar-channels}}`, template: hbs`{{sidebar-channels}}`,
beforeEach() { beforeEach() {
setupChatStub(this, { fullScreenChatOpen: true }); setupChatStub(this, {});
}, },
afterEach() { afterEach() {
@ -48,7 +48,7 @@ module("Discourse Chat | Component | sidebar-channels", function (hooks) {
template: hbs`{{sidebar-channels}}`, template: hbs`{{sidebar-channels}}`,
beforeEach() { beforeEach() {
setupChatStub(this, { userCanChat: false, fullScreenChatOpen: false }); setupChatStub(this, { userCanChat: false });
}, },
afterEach() { afterEach() {

View File

@ -4,12 +4,10 @@ import Service from "@ember/service";
let publicChannels; let publicChannels;
let userCanChat; let userCanChat;
let fullScreenChatOpen;
class ChatStub extends Service { class ChatStub extends Service {
userCanChat = userCanChat; userCanChat = userCanChat;
publicChannels = publicChannels; publicChannels = publicChannels;
fullScreenChatOpen = fullScreenChatOpen;
} }
export function setup(context, options = {}) { export function setup(context, options = {}) {
@ -20,13 +18,9 @@ export function setup(context, options = {}) {
? options.publicChannels ? options.publicChannels
: [fabricators.chatChannel()]; : [fabricators.chatChannel()];
userCanChat = isPresent(options.userCanChat) ? options.userCanChat : true; userCanChat = isPresent(options.userCanChat) ? options.userCanChat : true;
fullScreenChatOpen = isPresent(options.fullScreenChatOpen)
? options.fullScreenChatOpen
: false;
} }
export function teardown() { export function teardown() {
publicChannels = []; publicChannels = [];
userCanChat = true; userCanChat = true;
fullScreenChatOpen = false;
} }

View File

@ -71,12 +71,63 @@ module(
assert.strictEqual(this.subject.lastKnownAppURL, "/bar"); assert.strictEqual(this.subject.lastKnownAppURL, "/bar");
}); });
test("isFullPage", function (assert) { test("isFullPageActive", function (assert) {
sinon.stub(this.subject.router, "currentRouteName").value("foo"); sinon.stub(this.subject.router, "currentRouteName").value("foo");
assert.notOk(this.subject.isFullPage); assert.notOk(this.subject.isFullPageActive);
sinon.stub(this.subject.router, "currentRouteName").value("chat"); sinon.stub(this.subject.router, "currentRouteName").value("chat");
assert.ok(this.subject.isFullPage); assert.ok(this.subject.isFullPageActive);
});
test("didCollapseDrawer", function (assert) {
this.subject.didCollapseDrawer();
assert.strictEqual(this.subject.isDrawerExpanded, false);
assert.strictEqual(this.subject.isDrawerActive, true);
});
test("didExpandDrawer", function (assert) {
const stub = sinon.stub(
this.owner.lookup("service:chat"),
"updatePresence"
);
this.subject.didExpandDrawer();
assert.strictEqual(this.subject.isDrawerExpanded, true);
assert.strictEqual(this.subject.isDrawerActive, true);
sinon.assert.calledOnce(stub);
});
test("didCloseDrawer", function (assert) {
const stub = sinon.stub(
this.owner.lookup("service:chat"),
"updatePresence"
);
this.subject.didCloseDrawer();
assert.strictEqual(this.subject.isDrawerExpanded, false);
assert.strictEqual(this.subject.isDrawerActive, false);
sinon.assert.calledOnce(stub);
});
test("didOpenDrawer", function (assert) {
const stub = sinon.stub(
this.owner.lookup("service:chat"),
"updatePresence"
);
this.subject.didOpenDrawer();
assert.strictEqual(this.subject.isDrawerExpanded, true);
assert.strictEqual(this.subject.isDrawerActive, true);
assert.strictEqual(this.subject.lastKnownChatURL, "/chat");
this.subject.didOpenDrawer("/foo");
assert.strictEqual(this.subject.lastKnownChatURL, "/foo");
sinon.assert.calledTwice(stub);
}); });
} }
); );