Chat UI fixes (#6046)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-07-10 19:27:44 +04:00 committed by GitHub
parent bf0991d76a
commit b14cc90039
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 33 deletions

View File

@ -645,8 +645,17 @@ export function createModel (builder: Builder): void {
indexes: []
}
)
builder.mixin<Class<DocNotifyContext>, IndexingConfiguration<DocNotifyContext>>(
notification.class.ActivityInboxNotification,
builder.mixin<Class<InboxNotification>, IndexingConfiguration<InboxNotification>>(
notification.class.InboxNotification,
core.class.Class,
core.mixin.IndexConfiguration,
{
searchDisabled: true,
indexes: []
}
)
builder.mixin<Class<BrowserNotification>, IndexingConfiguration<BrowserNotification>>(
notification.class.BrowserNotification,
core.class.Class,
core.mixin.IndexConfiguration,
{

View File

@ -254,6 +254,8 @@
}
.text-input {
max-height: 18.75rem;
overflow: auto;
min-height: 2.75rem;
padding: 0.125rem 0.75rem;
}

View File

@ -32,6 +32,7 @@ import { combineActivityMessages } from '@hcengineering/activity-resources'
import chunter from './plugin'
import { type ChatMessage } from '@hcengineering/chunter'
import notification, { type DocNotifyContext, type InboxNotification } from '@hcengineering/notification'
export type LoadMode = 'forward' | 'backward'
@ -71,7 +72,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
private readonly tailQuery = createQuery(true)
private chatId: Ref<Doc> | undefined = undefined
private readonly lastViewedTimestamp: Timestamp | undefined = undefined
private readonly context: DocNotifyContext | undefined = undefined
private readonly msgClass: Ref<Class<ActivityMessage>>
private selectedMsgId: Ref<ActivityMessage> | undefined = undefined
private tailStart: Timestamp | undefined = undefined
@ -101,15 +102,15 @@ export class ChannelDataProvider implements IChannelDataProvider {
constructor (
chatId: Ref<Doc>,
_class: Ref<Class<ActivityMessage>>,
lastViewedTimestamp?: Timestamp,
context: DocNotifyContext | undefined,
selectedMsgId?: Ref<ActivityMessage>,
loadAll = false
) {
this.chatId = chatId
this.lastViewedTimestamp = lastViewedTimestamp
this.context = context
this.msgClass = _class
this.selectedMsgId = selectedMsgId
this.loadData(loadAll)
void this.loadData(loadAll)
}
public destroy (): void {
@ -154,7 +155,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
this.selectedMsgId = undefined
}
private loadData (loadAll = false): void {
private async loadData (loadAll = false): Promise<void> {
if (this.chatId === undefined) {
return
}
@ -182,10 +183,25 @@ export class ChannelDataProvider implements IChannelDataProvider {
return
}
const client = getClient()
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 firstNewMsgIndex = this.getFirstNewMsgIndex(this.lastViewedTimestamp)
const firstNewMsgIndex = this.getFirstNewMsgIndex(firstNotification)
if (get(this.newTimestampStore) === undefined) {
this.newTimestampStore.set(firstNewMsgIndex !== undefined ? metadata[firstNewMsgIndex]?.createdOn : undefined)
@ -335,19 +351,33 @@ export class ChannelDataProvider implements IChannelDataProvider {
return firsNewMsgIndex
}
private getFirstNewMsgIndex (lastViewedTimestamp?: Timestamp): number | undefined {
private getFirstNewMsgIndex (firstNotification: InboxNotification | undefined): number | undefined {
const metadata = get(this.metadataStore)
if (metadata.length === 0) {
return undefined
}
if (lastViewedTimestamp === undefined) {
if (this.context === undefined) {
return -1
}
const lastViewedTimestamp = this.context.lastViewedTimestamp
if (lastViewedTimestamp === undefined && firstNotification === undefined) {
return -1
}
const me = getCurrentAccount()._id
let newTimestamp = 0
if (lastViewedTimestamp !== undefined && firstNotification !== undefined) {
newTimestamp = Math.min(lastViewedTimestamp ?? 0, firstNotification?.createdOn ?? 0)
} else {
newTimestamp = lastViewedTimestamp ?? firstNotification?.createdOn ?? 0
}
return metadata.findIndex((message) => {
if (message.createdBy === me) {
return false
@ -355,7 +385,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
const createdOn = message.createdOn ?? 0
return lastViewedTimestamp < createdOn
return newTimestamp < createdOn
})
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { Class, Doc, getCurrentAccount, Ref, Timestamp } from '@hcengineering/core'
import { Class, Doc, getCurrentAccount, Ref } from '@hcengineering/core'
import notification, { DocNotifyContext } from '@hcengineering/notification'
import activity, { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
import { getClient } from '@hcengineering/presentation'
@ -61,29 +61,25 @@
$: _class = isDocChannel ? activity.class.ActivityMessage : chunter.class.ChatMessage
$: collection = isDocChannel ? 'comments' : 'messages'
$: updateDataProvider(object._id, _class, context?.lastViewedTimestamp, selectedMessageId)
$: void updateDataProvider(object._id, _class, selectedMessageId)
async function updateDataProvider (
attachedTo: Ref<Doc>,
_class: Ref<Class<ActivityMessage>>,
lastViewedTimestamp?: Timestamp,
selectedMessageId?: Ref<ActivityMessage>
): Promise<void> {
if (dataProvider === undefined) {
// For now loading all messages for documents with activity. Need to correct handle aggregation with pagination.
// Perhaps we should load all activity messages once, and keep loading in chunks only for ChatMessages then merge them correctly with activity messages
const loadAll = isDocChannel
const timestamp =
lastViewedTimestamp ??
(
await client.findOne(
notification.class.DocNotifyContext,
{ attachedTo: object._id, user: getCurrentAccount()._id },
{ projection: { lastViewedTimestamp: 1 } }
)
)?.lastViewedTimestamp
const ctx =
context ??
(await client.findOne(notification.class.DocNotifyContext, {
attachedTo: object._id,
user: getCurrentAccount()._id
}))
dataProvider = new ChannelDataProvider(attachedTo, _class, timestamp, selectedMessageId, loadAll)
dataProvider = new ChannelDataProvider(attachedTo, _class, ctx, selectedMessageId, loadAll)
}
}
</script>

View File

@ -15,7 +15,6 @@
//
import activity, { ActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
import { Analytics } from '@hcengineering/analytics'
import chunter, { ChatMessage } from '@hcengineering/chunter'
import contact, {
type AvatarInfo,
@ -467,12 +466,6 @@ async function activityInboxNotificationToText (doc: Data<ActivityInboxNotificat
body = await translate(doc.body, params)
}
// TODO: temporary log to understand problem. Remove it later.
if (body === 'chunter:string:MessageNotificationBody') {
console.error('Cannot translate chunter notification: ', { doc, params })
Analytics.handleError(new Error('Cannot translate chunter notification'))
}
return [title, body]
}
@ -1299,7 +1292,7 @@ async function applyUserTxes (
cache.set(account._id, account)
await control.apply(txs)
const m1 = toIdMap(txes)
const m1 = toIdMap(txs)
control.operationContext.derived.targets.docNotifyContext = (it) => {
if (m1.has(it._id)) {
return [account.email]

View File

@ -414,7 +414,7 @@ export async function getNotificationContent (
export async function getUsersInfo (ids: Ref<PersonAccount>[], control: TriggerControl): Promise<UserInfo[]> {
const accounts = await control.modelDb.findAll(contact.class.PersonAccount, { _id: { $in: ids } })
const persons = await control.findAll(contact.class.Person, { _id: { $in: accounts.map(({ person }) => person) } })
const persons = await control.queryFind(contact.class.Person, {})
return accounts.map((account) => ({
_id: account._id,