diff --git a/plugins/chat/app/queries/chat/messages_query.rb b/plugins/chat/app/queries/chat/messages_query.rb index 55b34889faf..b96b2be24cd 100644 --- a/plugins/chat/app/queries/chat/messages_query.rb +++ b/plugins/chat/app/queries/chat/messages_query.rb @@ -161,14 +161,14 @@ module Chat def self.query_by_date(target_date, channel, messages) past_messages = messages - .where("created_at <= ?", target_date) + .where("created_at <= ?", target_date.to_time.utc) .order(created_at: :desc) .limit(PAST_MESSAGE_LIMIT) .to_a future_messages = messages - .where("created_at > ?", target_date) + .where("created_at > ?", target_date.to_time.utc) .order(created_at: :asc) .limit(FUTURE_MESSAGE_LIMIT) .to_a diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs index 5f583126460..44e7274c2fe 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs @@ -34,6 +34,7 @@ import { checkMessageBottomVisibility, checkMessageTopVisibility, } from "discourse/plugins/chat/discourse/lib/check-message-visibility"; +import DatesSeparatorsPositioner from "discourse/plugins/chat/discourse/lib/dates-separators-positioner"; import { scrollListToBottom, scrollListToMessage, @@ -111,7 +112,7 @@ export default class ChatChannel extends Component { @action didResizePane() { this.debounceFillPaneAttempt(); - this.computeDatesSeparators(); + DatesSeparatorsPositioner.apply(this.scrollable); } @action @@ -443,13 +444,14 @@ export default class ChatChannel extends Component { @action onScroll(state) { - bodyScrollFix(); - next(() => { if (this.#flushIgnoreNextScroll()) { return; } + bodyScrollFix(); + DatesSeparatorsPositioner.apply(this.scrollable); + this.needsArrow = (this.messagesLoader.fetchedOnce && this.messagesLoader.canLoadMoreFuture) || @@ -641,50 +643,6 @@ export default class ChatChannel extends Component { return; } - @bind - computeDatesSeparators() { - schedule("afterRender", () => { - const dates = [ - ...this.scrollable.querySelectorAll(".chat-message-separator-date"), - ].reverse(); - const height = this.scrollable.querySelector( - ".chat-messages-container" - ).clientHeight; - - dates - .map((date, index) => { - const item = { bottom: 0, date }; - const line = date.nextElementSibling; - - if (index > 0) { - const prevDate = dates[index - 1]; - const prevLine = prevDate.nextElementSibling; - item.bottom = height - prevLine.offsetTop; - } - - if (dates.length === 1) { - item.height = height; - } else { - if (index === 0) { - item.height = height - line.offsetTop; - } else { - const prevDate = dates[index - 1]; - const prevLine = prevDate.nextElementSibling; - item.height = - height - line.offsetTop - (height - prevLine.offsetTop); - } - } - - return item; - }) - // group all writes at the end - .forEach((item) => { - item.date.style.bottom = item.bottom + "px"; - item.date.style.height = item.height + "px"; - }); - }); - } - #cancelHandlers() { cancel(this._debouncedHighlightOrFetchMessageHandler); cancel(this._debouncedUpdateLastReadMessageHandler); diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-separator-date.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-message-separator-date.gjs deleted file mode 100644 index 1850c39b817..00000000000 --- a/plugins/chat/assets/javascripts/discourse/components/chat-message-separator-date.gjs +++ /dev/null @@ -1,50 +0,0 @@ -import Component from "@glimmer/component"; -import { on } from "@ember/modifier"; -import { action } from "@ember/object"; -import concatClass from "discourse/helpers/concat-class"; -import i18n from "discourse-common/helpers/i18n"; -import trackMessageSeparatorDate from "../modifiers/chat/track-message-separator-date"; - -export default class ChatMessageSeparatorDate extends Component { - @action - onDateClick() { - return this.args.fetchMessagesByDate?.( - this.args.message.firstMessageOfTheDayAt - ); - } - - -} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-separator-new.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-message-separator-new.gjs deleted file mode 100644 index 0ff7142457e..00000000000 --- a/plugins/chat/assets/javascripts/discourse/components/chat-message-separator-new.gjs +++ /dev/null @@ -1,21 +0,0 @@ -import i18n from "discourse-common/helpers/i18n"; -import and from "truth-helpers/helpers/and"; -import not from "truth-helpers/helpers/not"; - -const ChatMessageSeparatorNew = ; - -export default ChatMessageSeparatorNew; diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-separator.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-message-separator.gjs new file mode 100644 index 00000000000..04e4aa78b69 --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/components/chat-message-separator.gjs @@ -0,0 +1,130 @@ +import Component from "@glimmer/component"; +import { cached } from "@glimmer/tracking"; +import { on } from "@ember/modifier"; +import { action } from "@ember/object"; +import { modifier } from "ember-modifier"; +import concatClass from "discourse/helpers/concat-class"; +import i18n from "discourse-common/helpers/i18n"; +import I18n from "I18n"; + +const IS_PINNED_CLASS = "is-pinned"; + +export default class ChatMessageSeparator extends Component { + track = modifier((element) => { + const intersectionObserver = new IntersectionObserver( + ([entry]) => { + if ( + entry.isIntersecting && + entry.intersectionRatio < 1 && + entry.boundingClientRect.y < entry.intersectionRect.y + ) { + entry.target.classList.add(IS_PINNED_CLASS); + } else { + entry.target.classList.remove(IS_PINNED_CLASS); + } + }, + { threshold: [0, 1] } + ); + + intersectionObserver.observe(element); + + return () => { + intersectionObserver?.disconnect(); + }; + }); + + @action + onDateClick() { + return this.args.fetchMessagesByDate?.(this.firstMessageOfTheDayAt); + } + + @cached + get firstMessageOfTheDayAt() { + const message = this.args.message; + + if (!message.previousMessage) { + return this.#startOfDay(message.createdAt); + } + + if ( + !this.#areDatesOnSameDay( + message.previousMessage.createdAt, + message.createdAt + ) + ) { + return this.#startOfDay(message.createdAt); + } + } + + @cached + get formattedFirstMessageDate() { + if (this.firstMessageOfTheDayAt) { + return this.#calendarDate(this.firstMessageOfTheDayAt); + } + } + + #areDatesOnSameDay(a, b) { + return ( + a.getFullYear() === b.getFullYear() && + a.getMonth() === b.getMonth() && + a.getDate() === b.getDate() + ); + } + + #startOfDay(date) { + return moment(date).startOf("day").format(); + } + + #calendarDate(date) { + return moment(date).calendar(moment(), { + sameDay: `[${I18n.t("chat.chat_message_separator.today")}]`, + lastDay: `[${I18n.t("chat.chat_message_separator.yesterday")}]`, + lastWeek: "LL", + sameElse: "LL", + }); + } + + +} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-message.gjs index 8404d275af9..c2f0d4cbb67 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-message.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-message.gjs @@ -26,8 +26,7 @@ import ChatMessageInfo from "discourse/plugins/chat/discourse/components/chat/me import ChatMessageLeftGutter from "discourse/plugins/chat/discourse/components/chat/message/left-gutter"; import ChatMessageInReplyToIndicator from "discourse/plugins/chat/discourse/components/chat-message-in-reply-to-indicator"; import ChatMessageReaction from "discourse/plugins/chat/discourse/components/chat-message-reaction"; -import ChatMessageSeparatorDate from "discourse/plugins/chat/discourse/components/chat-message-separator-date"; -import ChatMessageSeparatorNew from "discourse/plugins/chat/discourse/components/chat-message-separator-new"; +import ChatMessageSeparator from "discourse/plugins/chat/discourse/components/chat-message-separator"; import ChatMessageText from "discourse/plugins/chat/discourse/components/chat-message-text"; import ChatMessageThreadIndicator from "discourse/plugins/chat/discourse/components/chat-message-thread-indicator"; import ChatMessageInteractor from "discourse/plugins/chat/discourse/lib/chat-message-interactor"; @@ -494,13 +493,10 @@ export default class ChatMessage extends Component {