mirror of
https://github.com/discourse/discourse.git
synced 2025-02-20 11:48:45 +08:00
DEV: Added chat api to remove secondary actions (#21982)
In some cases, plugins may want to hide some of these actions at all times, overriding the rules for canX with hiding these buttons. To achieve this, a plugin can call the API `removeChatComposerSecondaryButtons` and pass the list of button IDs that should be removed as argument, like the example below: ``` withPluginApi("1.2.0", (api) => { api.removeChatComposerSecondaryActions("copyLink", "select"); }); ``` --------- Co-authored-by: Martin Brennan <martin@discourse.org>
This commit is contained in:
parent
44eabde12f
commit
e306a521fd
|
@ -10,7 +10,15 @@
|
|||
}}
|
||||
data-id={{this.message.id}}
|
||||
>
|
||||
<div class="chat-message-actions">
|
||||
<div
|
||||
class={{concat-class
|
||||
"chat-message-actions"
|
||||
(unless
|
||||
this.messageInteractor.secondaryActions.length
|
||||
"has-no-secondary-actions"
|
||||
)
|
||||
}}
|
||||
>
|
||||
{{#if this.shouldRenderFavoriteReactions}}
|
||||
{{#each
|
||||
this.messageInteractor.emojiReactions
|
||||
|
@ -57,14 +65,14 @@
|
|||
{{#if
|
||||
(and
|
||||
this.messageInteractor.message
|
||||
this.messageInteractor.secondaryButtons.length
|
||||
this.messageInteractor.secondaryActions.length
|
||||
)
|
||||
}}
|
||||
<DropdownSelectBox
|
||||
@class="more-buttons"
|
||||
@class="more-buttons secondary-actions"
|
||||
@options={{hash icon="ellipsis-v" placement="left"}}
|
||||
@content={{this.messageInteractor.secondaryButtons}}
|
||||
@onChange={{action this.messageInteractor.handleSecondaryButtons}}
|
||||
@content={{this.messageInteractor.secondaryActions}}
|
||||
@onChange={{action this.messageInteractor.handleSecondaryActions}}
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -31,12 +31,10 @@ export default class ChatMessageActionsDesktop extends Component {
|
|||
}
|
||||
|
||||
get messageInteractor() {
|
||||
const activeMessage = this.chat.activeMessage;
|
||||
|
||||
return new ChatMessageInteractor(
|
||||
getOwner(this),
|
||||
activeMessage.model,
|
||||
activeMessage.context
|
||||
this.message,
|
||||
this.context
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</div>
|
||||
|
||||
<ul class="secondary-actions">
|
||||
{{#each this.messageInteractor.secondaryButtons as |button|}}
|
||||
{{#each this.messageInteractor.secondaryActions as |button|}}
|
||||
<li class="chat-message-action-item" data-id={{button.id}}>
|
||||
<DButton
|
||||
@class="chat-message-action"
|
||||
|
|
|
@ -21,13 +21,15 @@ export default class ChatMessageActionsMobile extends Component {
|
|||
return this.chat.activeMessage.model;
|
||||
}
|
||||
|
||||
get messageInteractor() {
|
||||
const activeMessage = this.chat.activeMessage;
|
||||
get context() {
|
||||
return this.chat.activeMessage.context;
|
||||
}
|
||||
|
||||
get messageInteractor() {
|
||||
return new ChatMessageInteractor(
|
||||
getOwner(this),
|
||||
activeMessage.model,
|
||||
activeMessage.context
|
||||
this.message,
|
||||
this.context
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,16 @@ import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
|
|||
import { MESSAGE_CONTEXT_THREAD } from "discourse/plugins/chat/discourse/components/chat-message";
|
||||
import I18n from "I18n";
|
||||
|
||||
const removedSecondaryActions = new Set();
|
||||
|
||||
export function removeChatComposerSecondaryActions(actionIds) {
|
||||
actionIds.forEach((id) => removedSecondaryActions.add(id));
|
||||
}
|
||||
|
||||
export function resetRemovedChatComposerSecondaryActions() {
|
||||
removedSecondaryActions.clear();
|
||||
}
|
||||
|
||||
export default class ChatMessageInteractor {
|
||||
@service appEvents;
|
||||
@service dialog;
|
||||
|
@ -147,7 +157,7 @@ export default class ChatMessageInteractor {
|
|||
: this.chatChannelComposer;
|
||||
}
|
||||
|
||||
get secondaryButtons() {
|
||||
get secondaryActions() {
|
||||
const buttons = [];
|
||||
|
||||
buttons.push({
|
||||
|
@ -204,7 +214,7 @@ export default class ChatMessageInteractor {
|
|||
});
|
||||
}
|
||||
|
||||
return buttons;
|
||||
return buttons.reject((button) => removedSecondaryActions.has(button.id));
|
||||
}
|
||||
|
||||
select(checked = true) {
|
||||
|
@ -377,7 +387,7 @@ export default class ChatMessageInteractor {
|
|||
}
|
||||
|
||||
@action
|
||||
handleSecondaryButtons(id) {
|
||||
handleSecondaryActions(id) {
|
||||
this[id](this.message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
} from "discourse/plugins/chat/discourse/components/chat-message";
|
||||
import { registerChatComposerButton } from "discourse/plugins/chat/discourse/lib/chat-composer-buttons";
|
||||
import { addChatDrawerStateCallback } from "discourse/plugins/chat/discourse/services/chat-state-manager";
|
||||
import { removeChatComposerSecondaryActions } from "discourse/plugins/chat/discourse/lib/chat-message-interactor";
|
||||
|
||||
/**
|
||||
* Class exposing the javascript API available to plugins and themes.
|
||||
|
@ -111,6 +112,18 @@ import { addChatDrawerStateCallback } from "discourse/plugins/chat/discourse/ser
|
|||
* );
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes secondary actions from the chat composer
|
||||
*
|
||||
* @memberof PluginApi
|
||||
* @instance
|
||||
* @function removeChatComposerSecondaryActions
|
||||
* @param {...string} [1] - List of secondary action ids to remove, eg: `"copyLink", "select"
|
||||
* @example
|
||||
*
|
||||
* api.removeChatComposerSecondaryActions("copyLink", "select");
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "chat-plugin-api",
|
||||
after: "inject-discourse-objects",
|
||||
|
@ -156,6 +169,18 @@ export default {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!apiPrototype.hasOwnProperty("removeChatComposerSecondaryActions")) {
|
||||
Object.defineProperty(
|
||||
apiPrototype,
|
||||
"removeChatComposerSecondaryActions",
|
||||
{
|
||||
value(...actionIds) {
|
||||
removeChatComposerSecondaryActions(actionIds);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -76,6 +76,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.has-no-secondary-actions {
|
||||
.reply-btn {
|
||||
border-right: 1px solid var(--primary-300);
|
||||
border-top: 1px solid var(--primary-300);
|
||||
border-bottom: 1px solid var(--primary-300);
|
||||
border-radius: 0 0.25em 0.25em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.more-buttons.dropdown-select-box {
|
||||
.select-kit-header {
|
||||
background: none;
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import { module, test } from "qunit";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { setupTest } from "ember-qunit";
|
||||
import { module, test } from "qunit";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import User from "discourse/models/user";
|
||||
import ChatMessageInteractor, {
|
||||
resetRemovedChatComposerSecondaryActions,
|
||||
} from "discourse/plugins/chat/discourse/lib/chat-message-interactor";
|
||||
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||
import pretender from "discourse/tests/helpers/create-pretender";
|
||||
import { logIn } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
module("Chat | Unit | Utility | plugin-api", function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
@ -20,4 +27,52 @@ module("Chat | Unit | Utility | plugin-api", function (hooks) {
|
|||
await api.sendChatMessage(1, { message: "hello", threadId: 2 });
|
||||
});
|
||||
});
|
||||
|
||||
test("#removeChatComposerSecondaryActions", async function (assert) {
|
||||
withPluginApi("1.1.0", async (api) => {
|
||||
// assert that the api method is defined
|
||||
assert.equal(typeof api.removeChatComposerSecondaryActions, "function");
|
||||
|
||||
logIn();
|
||||
const currentUser = User.current();
|
||||
getOwner(this).unregister("service:current-user");
|
||||
getOwner(this).register("service:current-user", currentUser, {
|
||||
instantiate: false,
|
||||
});
|
||||
|
||||
const message = fabricators.message({ user: currentUser });
|
||||
const context = "channel";
|
||||
const interactor = new ChatMessageInteractor(
|
||||
getOwner(this),
|
||||
message,
|
||||
context
|
||||
);
|
||||
|
||||
// assert that the initial secondary actions are present
|
||||
const secondaryActions = interactor.secondaryActions;
|
||||
assert.ok(secondaryActions.length > 0);
|
||||
|
||||
try {
|
||||
// remove the first secondary action listed
|
||||
api.removeChatComposerSecondaryActions(secondaryActions[0].id);
|
||||
|
||||
const updatedSecondaryActions = interactor.secondaryActions;
|
||||
|
||||
// assert that the secondary action was removed
|
||||
assert.ok(
|
||||
updatedSecondaryActions.length < secondaryActions.length,
|
||||
"the updated secondary actions must contain less items than the original"
|
||||
);
|
||||
assert.notOk(
|
||||
updatedSecondaryActions
|
||||
.map((v) => v.id)
|
||||
.includes(secondaryActions[0]),
|
||||
"the updated secondary actions must not include the removed action"
|
||||
);
|
||||
} finally {
|
||||
// reset the secondary actions removed to prevent leakage to other tests
|
||||
resetRemovedChatComposerSecondaryActions();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user