mirror of
https://github.com/discourse/discourse.git
synced 2026-08-14 13:58:53 +08:00
This allows links in pinned chat messages — now that these are more prominent they can be used to link to important information near the chat header. This also updates the use of pinned messages in livestream chat to utilize the links to refer to the livestream topic. The mechanism for hiding the first pin in the livestream topic docked chat needed to be updated. When viewing a livestream chat while not in the topic you see the topic reference pin: <img width="450" alt="image" src="https://github.com/user-attachments/assets/ed16b592-05a9-4450-95b0-0843a653e55b" /> This automatically pinned message is hidden when using the docked livestream chat, as you're already in the topic: <img width="1000" alt="image" src="https://github.com/user-attachments/assets/5c562154-b847-4d98-9075-afd563012673" />
276 lines
10 KiB
Ruby
Vendored
276 lines
10 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe "Chat pinned messages" do
|
|
fab!(:admin)
|
|
fab!(:channel, :chat_channel)
|
|
fab!(:message) { Fabricate(:chat_message, chat_channel: channel, message: "Important message") }
|
|
|
|
let(:chat_page) { PageObjects::Pages::Chat.new }
|
|
let(:channel_page) { PageObjects::Pages::ChatChannel.new }
|
|
|
|
before do
|
|
chat_system_bootstrap
|
|
SiteSetting.chat_pinned_messages = true
|
|
channel.add(admin)
|
|
sign_in(admin)
|
|
end
|
|
|
|
it "allows staff to pin and unpin messages" do
|
|
chat_page.visit_channel(channel)
|
|
|
|
channel_page.messages.find(id: message.id).secondary_action("pin")
|
|
|
|
expect(page).to have_css(".chat-message-info__pinned")
|
|
expect(page).to have_css(".chat-pinned-bar__see-all")
|
|
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
expect(page).to have_content("Important message")
|
|
|
|
find(".c-navbar__close-pins-button").click
|
|
channel_page.messages.find(id: message.id).secondary_action("unpin")
|
|
|
|
expect(page).to have_no_css(".chat-message-info__pinned")
|
|
end
|
|
|
|
it "shows unread indicator for unseen pins" do
|
|
chat_page.visit_channel(channel)
|
|
|
|
# Another user pins the message while admin is viewing
|
|
pin =
|
|
Chat::PinnedMessage.create!(
|
|
chat_message: message,
|
|
chat_channel: channel,
|
|
user: Fabricate(:admin),
|
|
)
|
|
Chat::Publisher.publish_pin!(channel, message, pin)
|
|
|
|
expect(page).to have_css(".chat-pinned-bar__unread-indicator")
|
|
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
|
|
find(".c-navbar__close-pins-button").click
|
|
|
|
expect(page).to have_no_css(".chat-pinned-bar__unread-indicator")
|
|
end
|
|
|
|
it "marks pins as read when viewing the panel" do
|
|
Chat::PinnedMessage.create!(
|
|
chat_message: message,
|
|
chat_channel: channel,
|
|
user: Fabricate(:admin),
|
|
)
|
|
|
|
chat_page.visit_channel(channel)
|
|
expect(page).to have_css(".chat-pinned-bar__unread-indicator")
|
|
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
|
|
# Reload while panel is open — pins should stay marked as read
|
|
page.refresh
|
|
|
|
chat_page.visit_channel(channel)
|
|
expect(page).to have_no_css(".chat-pinned-bar__unread-indicator")
|
|
end
|
|
|
|
it "shows unseen pin icon in the panel for pins not yet viewed" do
|
|
other_user = Fabricate(:admin)
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: other_user)
|
|
|
|
chat_page.visit_channel(channel)
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
expect(page).to have_css(".chat-pinned-message__pinned-by-icon")
|
|
|
|
find(".c-navbar__close-pins-button").click
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
expect(page).to have_no_css(".chat-pinned-message__pinned-by-icon")
|
|
end
|
|
|
|
it "keeps the sticky bar in sync as messages are pinned and unpinned" do
|
|
other_message = Fabricate(:chat_message, chat_channel: channel, message: "Second message")
|
|
|
|
chat_page.visit_channel(channel)
|
|
|
|
# first pin: bar appears, no position indicator for a single pin
|
|
channel_page.messages.find(id: message.id).secondary_action("pin")
|
|
expect(page).to have_css(".chat-pinned-bar")
|
|
expect(page).to have_no_css(".chat-pinned-bar__indicator")
|
|
|
|
# second pin: position indicator appears with a segment per pin
|
|
channel_page.messages.find(id: other_message.id).secondary_action("pin")
|
|
expect(page).to have_css(".chat-pinned-bar__indicator-segment", count: 2)
|
|
|
|
# unpin one: bar stays, back to a single pin
|
|
channel_page.messages.find(id: other_message.id).secondary_action("unpin")
|
|
expect(page).to have_css(".chat-pinned-bar")
|
|
expect(page).to have_no_css(".chat-pinned-bar__indicator")
|
|
|
|
# unpin the last one: bar disappears
|
|
channel_page.messages.find(id: message.id).secondary_action("unpin")
|
|
expect(page).to have_no_css(".chat-pinned-bar")
|
|
end
|
|
|
|
it "cycles through pins when clicking the sticky bar" do
|
|
other_message = Fabricate(:chat_message, chat_channel: channel, message: "Second message")
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
Chat::PinnedMessage.create!(chat_message: other_message, chat_channel: channel, user: admin)
|
|
|
|
chat_page.visit_channel(channel)
|
|
|
|
# newest pin is shown first
|
|
expect(page).to have_css(".chat-pinned-bar__excerpt", text: "Second message")
|
|
|
|
find(".chat-pinned-bar__jump").click
|
|
expect(page).to have_css(".chat-pinned-bar__excerpt", text: "Important message")
|
|
|
|
find(".chat-pinned-bar__jump").click
|
|
expect(page).to have_css(".chat-pinned-bar__excerpt", text: "Second message")
|
|
end
|
|
|
|
it "shows the visited pin in the sticky bar when clicking a pin in the panel" do
|
|
other_message = Fabricate(:chat_message, chat_channel: channel, message: "Second message")
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
Chat::PinnedMessage.create!(chat_message: other_message, chat_channel: channel, user: admin)
|
|
|
|
chat_page.visit_channel(channel)
|
|
expect(page).to have_css(".chat-pinned-bar__excerpt", text: "Second message")
|
|
|
|
find(".chat-pinned-bar__see-all").click
|
|
find(".chat-pinned-message", text: "Important message").click
|
|
|
|
expect(page).to have_css(".chat-pinned-bar__excerpt", text: "Important message")
|
|
end
|
|
|
|
it "lists pins oldest-first in the panel (channel timeline order)" do
|
|
other_message = Fabricate(:chat_message, chat_channel: channel, message: "Second message")
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
Chat::PinnedMessage.create!(chat_message: other_message, chat_channel: channel, user: admin)
|
|
|
|
chat_page.visit_channel(channel)
|
|
find(".chat-pinned-bar__see-all").click
|
|
|
|
expect(page).to have_css(".chat-pinned-message:first-child", text: "Important message")
|
|
expect(page).to have_css(".chat-pinned-message:last-child", text: "Second message")
|
|
end
|
|
|
|
it "removes a pinned message from the bar when it is deleted" do
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
|
|
chat_page.visit_channel(channel)
|
|
expect(page).to have_css(".chat-pinned-bar")
|
|
|
|
# deleting unpins server-side and broadcasts an unpin event
|
|
channel_page.messages.delete(message)
|
|
|
|
expect(page).to have_no_css(".chat-pinned-bar")
|
|
end
|
|
|
|
it "toggles the pinned messages panel from the bar's see-all button" do
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
|
|
chat_page.visit_channel(channel)
|
|
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
|
|
# clicking again closes the panel
|
|
find(".chat-pinned-bar__see-all").click
|
|
expect(page).to have_no_css(".c-routes.--channel-pins")
|
|
end
|
|
|
|
it "lets a user without pin permissions hide the bar from the pins panel" do
|
|
user = Fabricate(:user)
|
|
channel.add(user)
|
|
other_message = Fabricate(:chat_message, chat_channel: channel, message: "Second message")
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
Chat::PinnedMessage.create!(chat_message: other_message, chat_channel: channel, user: admin)
|
|
|
|
sign_in(user)
|
|
chat_page.visit_channel(channel)
|
|
expect(page).to have_css(".chat-pinned-bar")
|
|
|
|
find(".chat-pinned-bar__see-all").click
|
|
find(".chat-pinned-messages-list__dismiss").click
|
|
|
|
# the panel closes and the bar is dismissed (hidden) until a newer pin
|
|
expect(page).to have_no_css(".c-routes.--channel-pins")
|
|
expect(page).to have_no_css(".chat-pinned-bar")
|
|
end
|
|
|
|
it "lets a user without pin permissions dismiss a single pin from the bar and show it again" do
|
|
user = Fabricate(:user)
|
|
channel.add(user)
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
|
|
sign_in(user)
|
|
chat_page.visit_channel(channel)
|
|
|
|
# a single pin offers an inline dismiss instead of the see-all button
|
|
expect(page).to have_no_css(".chat-pinned-bar__see-all")
|
|
find(".chat-pinned-bar__dismiss").click
|
|
expect(page).to have_no_css(".chat-pinned-bar")
|
|
|
|
# the navbar button reappears as the way back to the pins panel
|
|
find(".c-navbar__pinned-messages-btn").click
|
|
find(".chat-pinned-messages-list__show").click
|
|
|
|
expect(page).to have_no_css(".c-routes.--channel-pins")
|
|
expect(page).to have_css(".chat-pinned-bar")
|
|
expect(page).to have_no_css(".c-navbar__pinned-messages-btn")
|
|
end
|
|
|
|
it "does not offer the dismiss button to users who can manage pins" do
|
|
Chat::PinnedMessage.create!(chat_message: message, chat_channel: channel, user: admin)
|
|
|
|
chat_page.visit_channel(channel)
|
|
find(".chat-pinned-bar__see-all").click
|
|
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
expect(page).to have_content("Important message")
|
|
expect(page).to have_no_css(".chat-pinned-messages-list__dismiss")
|
|
end
|
|
|
|
context "when viewing pinned messages attribution" do
|
|
it "shows 'Pinned by you' when current user pinned the message" do
|
|
chat_page.visit_channel(channel)
|
|
channel_page.messages.find(id: message.id).secondary_action("pin")
|
|
|
|
expect(page).to have_css(".chat-message-info__pinned")
|
|
find(".chat-pinned-bar__see-all").click
|
|
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
expect(page).to have_css(
|
|
".chat-pinned-message__pinned-by",
|
|
text: I18n.t("js.chat.pinned_messages.pinned_by_you"),
|
|
)
|
|
end
|
|
|
|
context "when another user pinned the message" do
|
|
fab!(:other_user, :user)
|
|
|
|
before do
|
|
channel.add(other_user)
|
|
Chat::PinnedMessage.create!(
|
|
chat_message: message,
|
|
chat_channel: channel,
|
|
pinned_by_id: other_user.id,
|
|
)
|
|
end
|
|
|
|
it "shows 'Pinned by [username]'" do
|
|
chat_page.visit_channel(channel)
|
|
find(".chat-pinned-bar__see-all").click
|
|
|
|
expect(page).to have_css(".c-routes.--channel-pins")
|
|
expect(page).to have_css(
|
|
".chat-pinned-message__pinned-by",
|
|
text: I18n.t("js.chat.pinned_messages.pinned_by_user", username: other_user.username),
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|