UX: resets active message when scrolling (#21305)
This will avoid the messages actions floating around while scrolling. Note it's not testing the thread counterpart yet as I have a plan in mind to tests channels and threads in a clean way in the near future.
This commit is contained in:
parent
6c90747dea
commit
69a72015f0
|
@ -504,6 +504,8 @@ export default class ChatLivePane extends Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.chat.activeMessage = null;
|
||||||
|
|
||||||
if (this.#isAtTop()) {
|
if (this.#isAtTop()) {
|
||||||
this.fetchMoreMessages({ direction: PAST });
|
this.fetchMoreMessages({ direction: PAST });
|
||||||
this.onScrollEnded();
|
this.onScrollEnded();
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
{{on "touchend" this.handleTouchEnd passive=true}}
|
{{on "touchend" this.handleTouchEnd passive=true}}
|
||||||
{{on "mouseenter" this.onMouseEnter}}
|
{{on "mouseenter" this.onMouseEnter}}
|
||||||
{{on "mouseleave" this.onMouseLeave}}
|
{{on "mouseleave" this.onMouseLeave}}
|
||||||
|
{{on "mousemove" this.onMouseMove}}
|
||||||
class={{concat-class
|
class={{concat-class
|
||||||
"chat-message-container"
|
"chat-message-container"
|
||||||
(if this.pane.selectingMessages "selecting-messages")
|
(if this.pane.selectingMessages "selecting-messages")
|
||||||
|
|
|
@ -127,15 +127,30 @@ export default class ChatMessage extends Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._onHoverMessageDebouncedHandler = discourseDebounce(
|
this._onMouseEnterMessageDebouncedHandler = discourseDebounce(
|
||||||
this,
|
this,
|
||||||
this._debouncedOnHoverMessage,
|
this._debouncedOnHoverMessage,
|
||||||
250
|
250
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onMouseMove() {
|
||||||
|
if (this.site.mobileView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.chat.activeMessage?.model?.id === this.args.message.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setActiveMessage();
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
onMouseLeave(event) {
|
onMouseLeave(event) {
|
||||||
|
cancel(this._onMouseEnterMessageDebouncedHandler);
|
||||||
|
|
||||||
if (this.site.mobileView) {
|
if (this.site.mobileView) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -148,20 +163,21 @@ export default class ChatMessage extends Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(this._onHoverMessageDebouncedHandler);
|
|
||||||
|
|
||||||
this.chat.activeMessage = null;
|
this.chat.activeMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
_debouncedOnHoverMessage() {
|
_debouncedOnHoverMessage() {
|
||||||
if (!this.chat.userCanInteractWithChat) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._setActiveMessage();
|
this._setActiveMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
_setActiveMessage() {
|
_setActiveMessage() {
|
||||||
|
cancel(this._onMouseEnterMessageDebouncedHandler);
|
||||||
|
|
||||||
|
if (!this.chat.userCanInteractWithChat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.chat.activeMessage = {
|
this.chat.activeMessage = {
|
||||||
model: this.args.message,
|
model: this.args.message,
|
||||||
context: this.args.context,
|
context: this.args.context,
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
<div
|
<div
|
||||||
class="chat-thread__body popper-viewport"
|
class="chat-thread__body popper-viewport"
|
||||||
{{did-insert this.setScrollable}}
|
{{did-insert this.setScrollable}}
|
||||||
|
{{on "scroll" this.resetActiveMessage passive=true}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="chat-thread__messages chat-messages-container"
|
class="chat-thread__messages chat-messages-container"
|
||||||
|
|
|
@ -193,6 +193,11 @@ export default class ChatThreadPanel extends Component {
|
||||||
this.chatChannelThreadComposer.reset(this.channel);
|
this.chatChannelThreadComposer.reset(this.channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
resetActiveMessage() {
|
||||||
|
this.chat.activeMessage = null;
|
||||||
|
}
|
||||||
|
|
||||||
#sendNewMessage(message) {
|
#sendNewMessage(message) {
|
||||||
// TODO (martin) For desktop notifications
|
// TODO (martin) For desktop notifications
|
||||||
// resetIdle()
|
// resetIdle()
|
||||||
|
|
|
@ -250,4 +250,28 @@ RSpec.describe "Chat channel", type: :system, js: true do
|
||||||
expect(page).to have_selector("code.lang-ruby")
|
expect(page).to have_selector("code.lang-ruby")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "when scrolling" do
|
||||||
|
before do
|
||||||
|
channel_1.add(current_user)
|
||||||
|
50.times { Fabricate(:chat_message, chat_channel: channel_1) }
|
||||||
|
sign_in(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "resets the active message" do
|
||||||
|
chat.visit_channel(channel_1)
|
||||||
|
last_message = find(".chat-message-container:last-child")
|
||||||
|
last_message.hover
|
||||||
|
|
||||||
|
expect(page).to have_css(
|
||||||
|
".chat-message-actions-container[data-id='#{last_message["data-id"]}']",
|
||||||
|
)
|
||||||
|
|
||||||
|
find(".chat-messages-scroll").scroll_to(0, -1000)
|
||||||
|
|
||||||
|
expect(page).to have_no_css(
|
||||||
|
".chat-message-actions-container[data-id='#{last_message["data-id"]}']",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue