DEV: adds a addChatDrawerStateCallback API (#20640)

Usage:

```javascript
api.addChatDrawerStateCallback(({ isDrawerActive, isDrawerExpanded }) => {
  // do something
});
```

Note this commit also uses this new API to add a css class (chat-drawer-active) on the body when the drawer is active.
This commit is contained in:
Joffrey JAFFEUX 2023-03-10 18:49:59 +01:00 committed by GitHub
parent 6bb89ffea8
commit 727100d1e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 1 deletions

View File

@ -117,6 +117,14 @@ export default {
api.addToHeaderIcons("chat-header-icon"); api.addToHeaderIcons("chat-header-icon");
api.addChatDrawerStateCallback(({ isDrawerActive }) => {
if (isDrawerActive) {
document.body.classList.add("chat-drawer-active");
} else {
document.body.classList.remove("chat-drawer-active");
}
});
api.decorateChatMessage(function (chatMessage, chatChannel) { api.decorateChatMessage(function (chatMessage, chatChannel) {
if (!this.currentUser) { if (!this.currentUser) {
return; return;

View File

@ -4,6 +4,7 @@ import {
resetChatMessageDecorators, resetChatMessageDecorators,
} from "discourse/plugins/chat/discourse/components/chat-message"; } from "discourse/plugins/chat/discourse/components/chat-message";
import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib/chat-composer-buttons"; import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib/chat-composer-buttons";
import { addChatDrawerStateCallback } from "discourse/plugins/chat/discourse/services/chat-state-manager";
/** /**
* Class exposing the javascript API available to plugins and themes. * Class exposing the javascript API available to plugins and themes.
@ -19,6 +20,15 @@ import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib
* @param {ChatChannel} chatChannel - model * @param {ChatChannel} chatChannel - model
*/ */
/**
* Callback used to decorate a chat message
*
* @callback PluginApi~chatDrawerStateCallbak
* @param {Object} state
* @param {boolean} state.isDrawerActive - is the chat drawer active
* @param {boolean} state.isDrawerExpanded - is the chat drawer expanded
*/
/** /**
* Decorate a chat message * Decorate a chat message
* *
@ -65,6 +75,22 @@ import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib
* }); * });
*/ */
/**
* Callback when the sate of the chat drawer changes
*
* @memberof PluginApi
* @instance
* @function addChatDrawerStateCallback
* @param {PluginApi~chatDrawerStateCallbak} callback
* @example
*
* api.addChatDrawerStateCallback(({isDrawerExpanded, isDrawerActive}) => {
* if (isDrawerActive && isDrawerExpanded) {
* // do something
* }
* });
*/
export default { export default {
name: "chat-plugin-api", name: "chat-plugin-api",
after: "inject-discourse-objects", after: "inject-discourse-objects",
@ -88,6 +114,14 @@ export default {
}, },
}); });
} }
if (!apiPrototype.hasOwnProperty("addChatDrawerStateCallback")) {
Object.defineProperty(apiPrototype, "addChatDrawerStateCallback", {
value(callback) {
addChatDrawerStateCallback(callback);
},
});
}
}); });
}, },

View File

@ -9,6 +9,15 @@ const PREFERRED_MODE_STORE_NAMESPACE = "discourse_chat_";
const FULL_PAGE_CHAT = "FULL_PAGE_CHAT"; const FULL_PAGE_CHAT = "FULL_PAGE_CHAT";
const DRAWER_CHAT = "DRAWER_CHAT"; const DRAWER_CHAT = "DRAWER_CHAT";
let chatDrawerStateCallbacks = [];
export function addChatDrawerStateCallback(callback) {
chatDrawerStateCallbacks.push(callback);
}
export function resetChatDrawerStateCallbacks() {
chatDrawerStateCallbacks = [];
}
export default class ChatStateManager extends Service { export default class ChatStateManager extends Service {
@service chat; @service chat;
@service router; @service router;
@ -51,12 +60,14 @@ export default class ChatStateManager extends Service {
} }
this.chat.updatePresence(); this.chat.updatePresence();
this.#publishStateChange();
} }
didCloseDrawer() { didCloseDrawer() {
this.set("isDrawerActive", false); this.set("isDrawerActive", false);
this.set("isDrawerExpanded", false); this.set("isDrawerExpanded", false);
this.chat.updatePresence(); this.chat.updatePresence();
this.#publishStateChange();
} }
didExpandDrawer() { didExpandDrawer() {
@ -68,11 +79,13 @@ export default class ChatStateManager extends Service {
didCollapseDrawer() { didCollapseDrawer() {
this.set("isDrawerActive", true); this.set("isDrawerActive", true);
this.set("isDrawerExpanded", false); this.set("isDrawerExpanded", false);
this.#publishStateChange();
} }
didToggleDrawer() { didToggleDrawer() {
this.set("isDrawerExpanded", !this.isDrawerExpanded); this.set("isDrawerExpanded", !this.isDrawerExpanded);
this.set("isDrawerActive", true); this.set("isDrawerActive", true);
this.#publishStateChange();
} }
get isFullPagePreferred() { get isFullPagePreferred() {
@ -119,4 +132,13 @@ export default class ChatStateManager extends Service {
get lastKnownChatURL() { get lastKnownChatURL() {
return this._chatURL || "/chat"; return this._chatURL || "/chat";
} }
#publishStateChange() {
const state = {
isDrawerActive: this.isDrawerActive,
isDrawerExpanded: this.isDrawerExpanded,
};
chatDrawerStateCallbacks.forEach((callback) => callback(state));
}
} }

View File

@ -54,6 +54,20 @@ RSpec.describe "Drawer", type: :system, js: true do
end end
end end
context "when toggling open/close" do
it "toggles a css class on body" do
visit("/")
chat_page.open_from_header
expect(page.find("body.chat-drawer-active")).to be_visible
drawer.close
expect(page.find("body:not(.chat-drawer-active)")).to be_visible
end
end
context "when going from drawer to full page" do context "when going from drawer to full page" do
fab!(:channel_1) { Fabricate(:chat_channel) } fab!(:channel_1) { Fabricate(:chat_channel) }
fab!(:channel_2) { Fabricate(:chat_channel) } fab!(:channel_2) { Fabricate(:chat_channel) }

View File

@ -2,6 +2,11 @@ import { module, test } from "qunit";
import { setupTest } from "ember-qunit"; import { setupTest } from "ember-qunit";
import Site from "discourse/models/site"; import Site from "discourse/models/site";
import sinon from "sinon"; import sinon from "sinon";
import { getOwner } from "discourse-common/lib/get-owner";
import {
addChatDrawerStateCallback,
resetChatDrawerStateCallbacks,
} from "discourse/plugins/chat/discourse/services/chat-state-manager";
module( module(
"Discourse Chat | Unit | Service | chat-state-manager", "Discourse Chat | Unit | Service | chat-state-manager",
@ -9,7 +14,7 @@ module(
setupTest(hooks); setupTest(hooks);
hooks.beforeEach(function () { hooks.beforeEach(function () {
this.subject = this.owner.lookup("service:chat-state-manager"); this.subject = getOwner(this).lookup("service:chat-state-manager");
}); });
hooks.afterEach(function () { hooks.afterEach(function () {
@ -129,5 +134,24 @@ module(
assert.strictEqual(this.subject.lastKnownChatURL, "/foo"); assert.strictEqual(this.subject.lastKnownChatURL, "/foo");
sinon.assert.calledTwice(stub); sinon.assert.calledTwice(stub);
}); });
test("callbacks", function (assert) {
this.state = null;
addChatDrawerStateCallback((state) => {
this.state = state;
});
this.subject.didOpenDrawer();
assert.strictEqual(this.state.isDrawerActive, true);
assert.strictEqual(this.state.isDrawerExpanded, true);
this.subject.didCloseDrawer();
assert.strictEqual(this.state.isDrawerActive, false);
assert.strictEqual(this.state.isDrawerExpanded, false);
resetChatDrawerStateCallbacks();
});
} }
); );