mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
Chat UI fixes (#6046)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
bf0991d76a
commit
b14cc90039
@ -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,
|
||||
{
|
||||
|
@ -254,6 +254,8 @@
|
||||
}
|
||||
|
||||
.text-input {
|
||||
max-height: 18.75rem;
|
||||
overflow: auto;
|
||||
min-height: 2.75rem;
|
||||
padding: 0.125rem 0.75rem;
|
||||
}
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user