mirror of
https://github.com/discourse/discourse.git
synced 2025-05-08 00:43:12 +08:00
UX: preloads a thread when hovering thread indicator (#21406)
When hovering a thread indicator in a channel we will now append two `<link rel="preload" ...>` to the `<head>` of the document. Clicking on it should be significantly faster. Co-authored-by: Martin Brennan <martin@discourse.org>
This commit is contained in:
parent
187b59d376
commit
028dba144d
@ -2,6 +2,7 @@
|
|||||||
@route="chat.channel.thread"
|
@route="chat.channel.thread"
|
||||||
@models={{@message.thread.routeModels}}
|
@models={{@message.thread.routeModels}}
|
||||||
class="chat-message-thread-indicator"
|
class="chat-message-thread-indicator"
|
||||||
|
{{on "mouseenter" this.preloadThread}}
|
||||||
>
|
>
|
||||||
<span class="chat-message-thread-indicator__replies-count">
|
<span class="chat-message-thread-indicator__replies-count">
|
||||||
{{i18n "chat.thread.replies" count=@message.threadReplyCount}}
|
{{i18n "chat.thread.replies" count=@message.threadReplyCount}}
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { addPreloadLink } from "../lib/chat-preload-link";
|
||||||
|
import { PAGE_SIZE } from "./chat-thread";
|
||||||
|
|
||||||
export default class ChatMessageThreadIndicator extends Component {}
|
export default class ChatMessageThreadIndicator extends Component {
|
||||||
|
@action
|
||||||
|
preloadThread() {
|
||||||
|
const channel = this.args.message.channel;
|
||||||
|
const thread = this.args.message.thread;
|
||||||
|
|
||||||
|
addPreloadLink(
|
||||||
|
`/chat/api/channels/${channel.id}/threads/${thread.id}.json`,
|
||||||
|
`thread-preload-${thread.id}`
|
||||||
|
);
|
||||||
|
addPreloadLink(
|
||||||
|
`/chat/${channel.id}/messages.json?page_size=${PAGE_SIZE}&thread_id=${thread.id}`,
|
||||||
|
`thread-preload-messages-${thread.id}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ import { schedule } from "@ember/runloop";
|
|||||||
import discourseLater from "discourse-common/lib/later";
|
import discourseLater from "discourse-common/lib/later";
|
||||||
import { resetIdle } from "discourse/lib/desktop-notifications";
|
import { resetIdle } from "discourse/lib/desktop-notifications";
|
||||||
|
|
||||||
const PAGE_SIZE = 50;
|
export const PAGE_SIZE = 50;
|
||||||
|
|
||||||
export default class ChatThreadPanel extends Component {
|
export default class ChatThreadPanel extends Component {
|
||||||
@service siteSettings;
|
@service siteSettings;
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
export function addPreloadLink(url, id) {
|
||||||
|
if (document.querySelector(`link[href="${url}"][rel="preload"]`)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const importNode = document.createElement("link");
|
||||||
|
importNode.id = id;
|
||||||
|
importNode.rel = "preload";
|
||||||
|
importNode.crossOrigin = "anonymous";
|
||||||
|
importNode.as = "fetch";
|
||||||
|
importNode.href = url;
|
||||||
|
importNode.onload = () => {
|
||||||
|
importNode?.classList?.add("is-preloaded");
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(importNode);
|
||||||
|
}
|
@ -39,8 +39,9 @@ export default class ChatApi extends Service {
|
|||||||
* this.chatApi.thread(5, 1).then(thread => { ... })
|
* this.chatApi.thread(5, 1).then(thread => { ... })
|
||||||
*/
|
*/
|
||||||
thread(channelId, threadId) {
|
thread(channelId, threadId) {
|
||||||
return this.#getRequest(`/channels/${channelId}/threads/${threadId}`).then(
|
return this.#getRequest(
|
||||||
(result) =>
|
`/channels/${channelId}/threads/${threadId}.json`
|
||||||
|
).then((result) =>
|
||||||
this.chat.activeChannel.threadsManager.store(
|
this.chat.activeChannel.threadsManager.store(
|
||||||
this.chat.activeChannel,
|
this.chat.activeChannel,
|
||||||
result.thread
|
result.thread
|
||||||
@ -266,7 +267,7 @@ export default class ChatApi extends Service {
|
|||||||
args.chat_channel_id = channelId;
|
args.chat_channel_id = channelId;
|
||||||
} else {
|
} else {
|
||||||
args.page_size = data.pageSize;
|
args.page_size = data.pageSize;
|
||||||
path = `/chat/${channelId}/messages`;
|
path = `/chat/${channelId}/messages.json`;
|
||||||
|
|
||||||
if (data.messageId) {
|
if (data.messageId) {
|
||||||
args.message_id = data.messageId;
|
args.message_id = data.messageId;
|
||||||
|
42
plugins/chat/spec/system/thread_preload_spec.rb
Normal file
42
plugins/chat/spec/system/thread_preload_spec.rb
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe "Thread preload", type: :system, js: true do
|
||||||
|
fab!(:current_user) { Fabricate(:user) }
|
||||||
|
fab!(:channel_1) { Fabricate(:chat_channel) }
|
||||||
|
|
||||||
|
let(:chat_page) { PageObjects::Pages::Chat.new }
|
||||||
|
let(:channel_page) { PageObjects::Pages::ChatChannel.new }
|
||||||
|
let(:thread_page) { PageObjects::Pages::ChatThread.new }
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.enable_experimental_chat_threaded_discussions = true
|
||||||
|
chat_system_bootstrap(current_user)
|
||||||
|
channel_1.add(current_user)
|
||||||
|
channel_1.update!(threading_enabled: true)
|
||||||
|
sign_in(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when hovering a thread indicator" do
|
||||||
|
it "preloads the thread" do
|
||||||
|
thread =
|
||||||
|
chat_thread_chain_bootstrap(channel: channel_1, users: [current_user, Fabricate(:user)])
|
||||||
|
chat_page.visit_channel(channel_1)
|
||||||
|
|
||||||
|
channel_page.message_thread_indicator(thread.original_message).hover
|
||||||
|
|
||||||
|
expect(page).to have_selector("link#thread-preload-#{thread.id}.is-preloaded", visible: false)
|
||||||
|
expect(page).to have_selector(
|
||||||
|
"link#thread-preload-messages-#{thread.id}.is-preloaded",
|
||||||
|
visible: false,
|
||||||
|
)
|
||||||
|
|
||||||
|
page.driver.browser.network_conditions = { offline: true }
|
||||||
|
|
||||||
|
channel_page.message_thread_indicator(thread.original_message).click
|
||||||
|
|
||||||
|
expect(thread_page).to have_message(text: thread.replies.last.message)
|
||||||
|
ensure
|
||||||
|
page.driver.browser.network_conditions = { offline: false }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user