mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-04 23:04:47 +00:00
UBERF-7638: Add scroll to latest message button (#6119)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
c443cc60bd
commit
4962367182
@ -40,6 +40,7 @@
|
|||||||
export let inheritFont: boolean = false
|
export let inheritFont: boolean = false
|
||||||
export let tooltip: LabelAndProps | undefined = undefined
|
export let tooltip: LabelAndProps | undefined = undefined
|
||||||
export let element: HTMLButtonElement | undefined = undefined
|
export let element: HTMLButtonElement | undefined = undefined
|
||||||
|
export let shape: 'rectangle' | 'round' = 'rectangle'
|
||||||
export let id: string | undefined = undefined
|
export let id: string | undefined = undefined
|
||||||
|
|
||||||
let actualIconSize: IconSize = 'small'
|
let actualIconSize: IconSize = 'small'
|
||||||
@ -89,7 +90,7 @@
|
|||||||
<button
|
<button
|
||||||
{id}
|
{id}
|
||||||
bind:this={element}
|
bind:this={element}
|
||||||
class="font-medium-14 {kind} {size} {type}"
|
class="font-medium-14 {kind} {size} {type} {shape}"
|
||||||
class:loading
|
class:loading
|
||||||
class:pressed
|
class:pressed
|
||||||
class:inheritColor
|
class:inheritColor
|
||||||
@ -155,6 +156,10 @@
|
|||||||
height: var(--global-large-Size);
|
height: var(--global-large-Size);
|
||||||
border-radius: var(--medium-BorderRadius);
|
border-radius: var(--medium-BorderRadius);
|
||||||
|
|
||||||
|
&.round {
|
||||||
|
border-radius: var(--large-BorderRadius);
|
||||||
|
}
|
||||||
|
|
||||||
&.type-button:not(.iconOnly) {
|
&.type-button:not(.iconOnly) {
|
||||||
padding: 0 var(--spacing-2);
|
padding: 0 var(--spacing-2);
|
||||||
}
|
}
|
||||||
@ -167,6 +172,9 @@
|
|||||||
height: var(--global-medium-Size);
|
height: var(--global-medium-Size);
|
||||||
border-radius: var(--medium-BorderRadius);
|
border-radius: var(--medium-BorderRadius);
|
||||||
|
|
||||||
|
&.round {
|
||||||
|
border-radius: var(--large-BorderRadius);
|
||||||
|
}
|
||||||
&.type-button:not(.iconOnly) {
|
&.type-button:not(.iconOnly) {
|
||||||
padding: 0 var(--spacing-2);
|
padding: 0 var(--spacing-2);
|
||||||
}
|
}
|
||||||
@ -180,6 +188,9 @@
|
|||||||
gap: var(--spacing-0_5);
|
gap: var(--spacing-0_5);
|
||||||
border-radius: var(--small-BorderRadius);
|
border-radius: var(--small-BorderRadius);
|
||||||
|
|
||||||
|
&.round {
|
||||||
|
border-radius: var(--large-BorderRadius);
|
||||||
|
}
|
||||||
&.type-button:not(.iconOnly) {
|
&.type-button:not(.iconOnly) {
|
||||||
padding: 0 var(--spacing-1);
|
padding: 0 var(--spacing-1);
|
||||||
}
|
}
|
||||||
@ -192,6 +203,9 @@
|
|||||||
height: var(--global-extra-small-Size);
|
height: var(--global-extra-small-Size);
|
||||||
border-radius: var(--extra-small-BorderRadius);
|
border-radius: var(--extra-small-BorderRadius);
|
||||||
|
|
||||||
|
&.round {
|
||||||
|
border-radius: var(--large-BorderRadius);
|
||||||
|
}
|
||||||
&.type-button:not(.iconOnly) {
|
&.type-button:not(.iconOnly) {
|
||||||
padding: 0 var(--spacing-1);
|
padding: 0 var(--spacing-1);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
export let labelParams: Record<string, any> = {}
|
export let labelParams: Record<string, any> = {}
|
||||||
export let kind: 'primary' | 'secondary' | 'tertiary' | 'negative' = 'secondary'
|
export let kind: 'primary' | 'secondary' | 'tertiary' | 'negative' = 'secondary'
|
||||||
export let size: ButtonBaseSize = 'large'
|
export let size: ButtonBaseSize = 'large'
|
||||||
|
export let shape: 'rectangle' | 'round' = 'rectangle'
|
||||||
export let icon: Asset | AnySvelteComponent | ComponentType | undefined = undefined
|
export let icon: Asset | AnySvelteComponent | ComponentType | undefined = undefined
|
||||||
export let iconSize: IconSize | undefined = undefined
|
export let iconSize: IconSize | undefined = undefined
|
||||||
export let disabled: boolean = false
|
export let disabled: boolean = false
|
||||||
@ -29,6 +30,7 @@
|
|||||||
<ButtonBase
|
<ButtonBase
|
||||||
type={'type-button'}
|
type={'type-button'}
|
||||||
{title}
|
{title}
|
||||||
|
{shape}
|
||||||
{label}
|
{label}
|
||||||
{labelParams}
|
{labelParams}
|
||||||
{kind}
|
{kind}
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
"JoinChannelHeader": "Click \"Join\" to get started.",
|
"JoinChannelHeader": "Click \"Join\" to get started.",
|
||||||
"JoinChannelText": "Once you've joined, you'll be able to read all messages and contribute to the discussion.",
|
"JoinChannelText": "Once you've joined, you'll be able to read all messages and contribute to the discussion.",
|
||||||
"NoMessagesInChannel": "Currently there are no messages",
|
"NoMessagesInChannel": "Currently there are no messages",
|
||||||
"SendMessagesInChannel": "Send the first message to start the conversation"
|
"SendMessagesInChannel": "Send the first message to start the conversation",
|
||||||
|
"LatestMessages": "↓ Latest messages"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,6 +110,7 @@
|
|||||||
"JoinChannelHeader": "Haga clic en \"Unirse\" para comenzar.",
|
"JoinChannelHeader": "Haga clic en \"Unirse\" para comenzar.",
|
||||||
"JoinChannelText": "Una vez que se haya unido, podrá leer todos los mensajes y contribuir a la discusión.",
|
"JoinChannelText": "Una vez que se haya unido, podrá leer todos los mensajes y contribuir a la discusión.",
|
||||||
"NoMessagesInChannel": "No hay mensajes en este canal todavía.",
|
"NoMessagesInChannel": "No hay mensajes en este canal todavía.",
|
||||||
"SendMessagesInChannel": "Envíe mensajes en este canal para comenzar la conversación."
|
"SendMessagesInChannel": "Envíe mensajes en este canal para comenzar la conversación.",
|
||||||
|
"LatestMessages": "↓ Últimos mensajes"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,6 +110,7 @@
|
|||||||
"JoinChannelHeader": "Cliquez sur \"Rejoindre\" pour commencer.",
|
"JoinChannelHeader": "Cliquez sur \"Rejoindre\" pour commencer.",
|
||||||
"JoinChannelText": "Une fois que vous avez rejoint, vous pourrez lire tous les messages et participer à la discussion.",
|
"JoinChannelText": "Une fois que vous avez rejoint, vous pourrez lire tous les messages et participer à la discussion.",
|
||||||
"NoMessagesInChannel": "Il n'y a pas encore de messages dans ce canal.",
|
"NoMessagesInChannel": "Il n'y a pas encore de messages dans ce canal.",
|
||||||
"SendMessagesInChannel": "Envoyez des messages pour commencer la conversation."
|
"SendMessagesInChannel": "Envoyez des messages pour commencer la conversation.",
|
||||||
|
"LatestMessages": "↓ Derniers messages"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,6 +110,7 @@
|
|||||||
"JoinChannelHeader": "Clique em \"Participar\" para começar.",
|
"JoinChannelHeader": "Clique em \"Participar\" para começar.",
|
||||||
"JoinChannelText": "Depois de entrar, você poderá ler todas as mensagens e contribuir na discussão.",
|
"JoinChannelText": "Depois de entrar, você poderá ler todas as mensagens e contribuir na discussão.",
|
||||||
"NoMessagesInChannel": "Ainda não existem mensagens neste canal.",
|
"NoMessagesInChannel": "Ainda não existem mensagens neste canal.",
|
||||||
"SendMessagesInChannel": "Envie a sua primeira mensagem!"
|
"SendMessagesInChannel": "Envie a sua primeira mensagem!",
|
||||||
|
"LatestMessages": "↓ Últimas mensagens"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,6 +110,7 @@
|
|||||||
"JoinChannelHeader": "Нажмите \"Присоединиться\", чтобы начать.",
|
"JoinChannelHeader": "Нажмите \"Присоединиться\", чтобы начать.",
|
||||||
"JoinChannelText": "Присоединившись, вы сможете читать все сообщения и участвовать в обсуждении.",
|
"JoinChannelText": "Присоединившись, вы сможете читать все сообщения и участвовать в обсуждении.",
|
||||||
"NoMessagesInChannel": "В этом канале пока нет сообщений",
|
"NoMessagesInChannel": "В этом канале пока нет сообщений",
|
||||||
"SendMessagesInChannel": "Отправьте первое сообщение, чтобы начать общение"
|
"SendMessagesInChannel": "Отправьте первое сообщение, чтобы начать общение",
|
||||||
|
"LatestMessages": "↓ Последние сообщения"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -110,6 +110,7 @@
|
|||||||
"JoinChannelHeader": "点击“加入”开始。",
|
"JoinChannelHeader": "点击“加入”开始。",
|
||||||
"JoinChannelText": "加入后,你将能够阅读所有消息并参与讨论。",
|
"JoinChannelText": "加入后,你将能够阅读所有消息并参与讨论。",
|
||||||
"NoMessagesInChannel": "此频道中没有消息。",
|
"NoMessagesInChannel": "此频道中没有消息。",
|
||||||
"SendMessagesInChannel": "在此频道中发送消息。"
|
"SendMessagesInChannel": "在此频道中发送消息。",
|
||||||
|
"LatestMessages": "↓ 最新消息"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,10 @@ import { derived, get, type Readable, writable } from 'svelte/store'
|
|||||||
import { type ActivityMessage } from '@hcengineering/activity'
|
import { type ActivityMessage } from '@hcengineering/activity'
|
||||||
import attachment from '@hcengineering/attachment'
|
import attachment from '@hcengineering/attachment'
|
||||||
import { combineActivityMessages } from '@hcengineering/activity-resources'
|
import { combineActivityMessages } from '@hcengineering/activity-resources'
|
||||||
|
import { type ChatMessage } from '@hcengineering/chunter'
|
||||||
|
import notification, { type DocNotifyContext } from '@hcengineering/notification'
|
||||||
|
|
||||||
import chunter from './plugin'
|
import chunter from './plugin'
|
||||||
import { type ChatMessage } from '@hcengineering/chunter'
|
|
||||||
import notification, { type DocNotifyContext, type InboxNotification } from '@hcengineering/notification'
|
|
||||||
|
|
||||||
export type LoadMode = 'forward' | 'backward'
|
export type LoadMode = 'forward' | 'backward'
|
||||||
|
|
||||||
@ -175,7 +175,11 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadInitialMessages (selectedMsg?: Ref<ActivityMessage>, loadAll = false): Promise<void> {
|
private async loadInitialMessages (
|
||||||
|
selectedMsg?: Ref<ActivityMessage>,
|
||||||
|
loadAll = false,
|
||||||
|
ignoreNew = false
|
||||||
|
): Promise<void> {
|
||||||
const isLoading = get(this.isInitialLoadingStore)
|
const isLoading = get(this.isInitialLoadingStore)
|
||||||
const isLoaded = get(this.isInitialLoadedStore)
|
const isLoaded = get(this.isInitialLoadedStore)
|
||||||
|
|
||||||
@ -183,28 +187,15 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
this.isInitialLoadingStore.set(true)
|
this.isInitialLoadingStore.set(true)
|
||||||
const firstNotification =
|
|
||||||
this.context !== undefined
|
|
||||||
? await client.findOne(
|
|
||||||
notification.class.InboxNotification,
|
|
||||||
{
|
|
||||||
_class: {
|
|
||||||
$in: [notification.class.MentionInboxNotification, notification.class.ActivityInboxNotification]
|
|
||||||
},
|
|
||||||
docNotifyContext: this.context._id,
|
|
||||||
isViewed: false
|
|
||||||
},
|
|
||||||
{ sort: { createdOn: SortingOrder.Ascending } }
|
|
||||||
)
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
const metadata = get(this.metadataStore)
|
const metadata = get(this.metadataStore)
|
||||||
const firstNewMsgIndex = this.getFirstNewMsgIndex(firstNotification)
|
const firstNewMsgIndex = ignoreNew ? undefined : await this.getFirstNewMsgIndex()
|
||||||
|
|
||||||
if (get(this.newTimestampStore) === undefined) {
|
if (get(this.newTimestampStore) === undefined) {
|
||||||
this.newTimestampStore.set(firstNewMsgIndex !== undefined ? metadata[firstNewMsgIndex]?.createdOn : undefined)
|
this.newTimestampStore.set(firstNewMsgIndex !== undefined ? metadata[firstNewMsgIndex]?.createdOn : undefined)
|
||||||
|
} else if (ignoreNew) {
|
||||||
|
this.newTimestampStore.set(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
const startPosition = this.getStartPosition(selectedMsg ?? this.selectedMsgId, firstNewMsgIndex)
|
const startPosition = this.getStartPosition(selectedMsg ?? this.selectedMsgId, firstNewMsgIndex)
|
||||||
@ -351,7 +342,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
return firsNewMsgIndex
|
return firsNewMsgIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFirstNewMsgIndex (firstNotification: InboxNotification | undefined): number | undefined {
|
private async getFirstNewMsgIndex (): Promise<number | undefined> {
|
||||||
const metadata = get(this.metadataStore)
|
const metadata = get(this.metadataStore)
|
||||||
|
|
||||||
if (metadata.length === 0) {
|
if (metadata.length === 0) {
|
||||||
@ -363,6 +354,18 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const lastViewedTimestamp = this.context.lastViewedTimestamp
|
const lastViewedTimestamp = this.context.lastViewedTimestamp
|
||||||
|
const client = getClient()
|
||||||
|
const firstNotification = await client.findOne(
|
||||||
|
notification.class.InboxNotification,
|
||||||
|
{
|
||||||
|
_class: {
|
||||||
|
$in: [notification.class.MentionInboxNotification, notification.class.ActivityInboxNotification]
|
||||||
|
},
|
||||||
|
docNotifyContext: this.context._id,
|
||||||
|
isViewed: false
|
||||||
|
},
|
||||||
|
{ sort: { createdOn: SortingOrder.Ascending } }
|
||||||
|
)
|
||||||
|
|
||||||
if (lastViewedTimestamp === undefined && firstNotification === undefined) {
|
if (lastViewedTimestamp === undefined && firstNotification === undefined) {
|
||||||
return -1
|
return -1
|
||||||
@ -436,7 +439,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
await this.loadInitialMessages(msg._id)
|
await this.loadInitialMessages(msg._id)
|
||||||
}
|
}
|
||||||
|
|
||||||
public jumpToMessage (message: ActivityMessage): boolean {
|
public jumpToMessage (message: MessageMetadata): boolean {
|
||||||
const metadata = get(this.metadataStore).find(({ _id }) => _id === message._id)
|
const metadata = get(this.metadataStore).find(({ _id }) => _id === message._id)
|
||||||
|
|
||||||
if (metadata === undefined) {
|
if (metadata === undefined) {
|
||||||
@ -455,7 +458,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
public jumpToEnd (): boolean {
|
public jumpToEnd (ignoreNew = false): boolean {
|
||||||
const last = get(this.metadataStore)[get(this.metadataStore).length - 1]
|
const last = get(this.metadataStore)[get(this.metadataStore).length - 1]
|
||||||
|
|
||||||
if (last === undefined) {
|
if (last === undefined) {
|
||||||
@ -468,8 +471,9 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.selectedMsgId = undefined
|
||||||
this.clearMessages()
|
this.clearMessages()
|
||||||
void this.loadInitialMessages()
|
void this.loadInitialMessages(this.selectedMsgId, false, ignoreNew)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,14 @@
|
|||||||
import {
|
import {
|
||||||
ActivityExtension as ActivityExtensionComponent,
|
ActivityExtension as ActivityExtensionComponent,
|
||||||
ActivityMessagePresenter,
|
ActivityMessagePresenter,
|
||||||
canGroupMessages
|
canGroupMessages,
|
||||||
|
messageInFocus
|
||||||
} from '@hcengineering/activity-resources'
|
} from '@hcengineering/activity-resources'
|
||||||
import { Class, Doc, getDay, Ref, Timestamp } from '@hcengineering/core'
|
import { Class, Doc, getDay, Ref, Timestamp } from '@hcengineering/core'
|
||||||
import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources'
|
import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources'
|
||||||
import { getResource } from '@hcengineering/platform'
|
import { getResource } from '@hcengineering/platform'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { Loading, Scroller, ScrollParams } from '@hcengineering/ui'
|
import { Loading, ModernButton, Scroller, ScrollParams } from '@hcengineering/ui'
|
||||||
import { afterUpdate, beforeUpdate, onDestroy, onMount, tick } from 'svelte'
|
import { afterUpdate, beforeUpdate, onDestroy, onMount, tick } from 'svelte'
|
||||||
import { get } from 'svelte/store'
|
import { get } from 'svelte/store'
|
||||||
|
|
||||||
@ -101,6 +102,9 @@
|
|||||||
let selectedDate: Timestamp | undefined = undefined
|
let selectedDate: Timestamp | undefined = undefined
|
||||||
let dateToJump: Timestamp | undefined = undefined
|
let dateToJump: Timestamp | undefined = undefined
|
||||||
|
|
||||||
|
let prevScrollHeight = 0
|
||||||
|
let isScrollAtBottom = false
|
||||||
|
|
||||||
let messagesCount = 0
|
let messagesCount = 0
|
||||||
|
|
||||||
let wasAsideOpened = isAsideOpened
|
let wasAsideOpened = isAsideOpened
|
||||||
@ -277,6 +281,7 @@
|
|||||||
|
|
||||||
function handleScroll ({ autoScrolling }: ScrollParams): void {
|
function handleScroll ({ autoScrolling }: ScrollParams): void {
|
||||||
saveScrollPosition()
|
saveScrollPosition()
|
||||||
|
updateDownButtonVisibility($metadataStore, displayMessages, scrollElement)
|
||||||
if (autoScrolling) {
|
if (autoScrolling) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -450,6 +455,8 @@
|
|||||||
isScrollInitialized = true
|
isScrollInitialized = true
|
||||||
isInitialScrolling = false
|
isInitialScrolling = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateDownButtonVisibility($metadataStore, displayMessages, scrollElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
function reinitializeScroll (): void {
|
function reinitializeScroll (): void {
|
||||||
@ -557,9 +564,6 @@
|
|||||||
loadMore()
|
loadMore()
|
||||||
}
|
}
|
||||||
|
|
||||||
let prevScrollHeight = 0
|
|
||||||
let isScrollAtBottom = false
|
|
||||||
|
|
||||||
function saveScrollPosition (): void {
|
function saveScrollPosition (): void {
|
||||||
if (!scrollElement) {
|
if (!scrollElement) {
|
||||||
return
|
return
|
||||||
@ -588,7 +592,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
async function compensateAside (isOpened: boolean) {
|
async function compensateAside (isOpened: boolean): Promise<void> {
|
||||||
if (!isInitialScrolling && isScrollAtBottom && !wasAsideOpened && isOpened) {
|
if (!isInitialScrolling && isScrollAtBottom && !wasAsideOpened && isOpened) {
|
||||||
await wait()
|
await wait()
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
@ -599,7 +603,7 @@
|
|||||||
|
|
||||||
$: void compensateAside(isAsideOpened)
|
$: void compensateAside(isAsideOpened)
|
||||||
|
|
||||||
function canGroupChatMessages (message: ActivityMessage, prevMessage?: ActivityMessage) {
|
function canGroupChatMessages (message: ActivityMessage, prevMessage?: ActivityMessage): boolean {
|
||||||
let prevMetadata: MessageMetadata | undefined = undefined
|
let prevMetadata: MessageMetadata | undefined = undefined
|
||||||
|
|
||||||
if (prevMessage === undefined) {
|
if (prevMessage === undefined) {
|
||||||
@ -617,6 +621,53 @@
|
|||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let showScrollDownButton = false
|
||||||
|
|
||||||
|
$: updateDownButtonVisibility($metadataStore, displayMessages, scrollElement)
|
||||||
|
|
||||||
|
function updateDownButtonVisibility (
|
||||||
|
metadata: MessageMetadata[],
|
||||||
|
displayMessages: DisplayActivityMessage[],
|
||||||
|
element?: HTMLDivElement
|
||||||
|
): void {
|
||||||
|
if (metadata.length === 0 || displayMessages.length === 0) {
|
||||||
|
showScrollDownButton = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastMetadata = metadata[metadata.length - 1]
|
||||||
|
const lastMessage = displayMessages[displayMessages.length - 1]
|
||||||
|
|
||||||
|
if (lastMetadata._id !== lastMessage._id) {
|
||||||
|
showScrollDownButton = true
|
||||||
|
} else if (element != null) {
|
||||||
|
const { scrollHeight, scrollTop, offsetHeight } = element
|
||||||
|
|
||||||
|
showScrollDownButton = scrollHeight > offsetHeight + scrollTop + 300
|
||||||
|
} else {
|
||||||
|
showScrollDownButton = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleScrollDown (): void {
|
||||||
|
selectedMessageId = undefined
|
||||||
|
messageInFocus.set(undefined)
|
||||||
|
|
||||||
|
const metadata = $metadataStore
|
||||||
|
const lastMetadata = metadata[metadata.length - 1]
|
||||||
|
const lastMessage = displayMessages[displayMessages.length - 1]
|
||||||
|
|
||||||
|
void inboxClient.readDoc(client, objectId)
|
||||||
|
|
||||||
|
if (lastMetadata._id !== lastMessage._id) {
|
||||||
|
separatorIndex = -1
|
||||||
|
provider.jumpToEnd(true)
|
||||||
|
reinitializeScroll()
|
||||||
|
} else {
|
||||||
|
scrollToBottom()
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
@ -689,6 +740,18 @@
|
|||||||
<HistoryLoading isLoading={$isLoadingMoreStore} />
|
<HistoryLoading isLoading={$isLoadingMoreStore} />
|
||||||
{/if}
|
{/if}
|
||||||
</Scroller>
|
</Scroller>
|
||||||
|
|
||||||
|
{#if showScrollDownButton}
|
||||||
|
<div class="down-button absolute">
|
||||||
|
<ModernButton
|
||||||
|
label={chunter.string.LatestMessages}
|
||||||
|
shape="round"
|
||||||
|
size="small"
|
||||||
|
kind="primary"
|
||||||
|
on:click={handleScrollDown}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if object}
|
{#if object}
|
||||||
<div class="ref-input">
|
<div class="ref-input">
|
||||||
@ -728,4 +791,11 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.down-button {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
bottom: -0.75rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -108,6 +108,7 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
ArchiveActivityConfirmationTitle: '' as IntlString,
|
ArchiveActivityConfirmationTitle: '' as IntlString,
|
||||||
ArchiveActivityConfirmationMessage: '' as IntlString,
|
ArchiveActivityConfirmationMessage: '' as IntlString,
|
||||||
JoinChannelHeader: '' as IntlString,
|
JoinChannelHeader: '' as IntlString,
|
||||||
JoinChannelText: '' as IntlString
|
JoinChannelText: '' as IntlString,
|
||||||
|
LatestMessages: '' as IntlString
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user