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: []
|
indexes: []
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
builder.mixin<Class<DocNotifyContext>, IndexingConfiguration<DocNotifyContext>>(
|
builder.mixin<Class<InboxNotification>, IndexingConfiguration<InboxNotification>>(
|
||||||
notification.class.ActivityInboxNotification,
|
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.class.Class,
|
||||||
core.mixin.IndexConfiguration,
|
core.mixin.IndexConfiguration,
|
||||||
{
|
{
|
||||||
|
@ -254,6 +254,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.text-input {
|
.text-input {
|
||||||
|
max-height: 18.75rem;
|
||||||
|
overflow: auto;
|
||||||
min-height: 2.75rem;
|
min-height: 2.75rem;
|
||||||
padding: 0.125rem 0.75rem;
|
padding: 0.125rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import { combineActivityMessages } from '@hcengineering/activity-resources'
|
|||||||
|
|
||||||
import chunter from './plugin'
|
import chunter from './plugin'
|
||||||
import { type ChatMessage } from '@hcengineering/chunter'
|
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'
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
private readonly tailQuery = createQuery(true)
|
private readonly tailQuery = createQuery(true)
|
||||||
|
|
||||||
private chatId: Ref<Doc> | undefined = undefined
|
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 readonly msgClass: Ref<Class<ActivityMessage>>
|
||||||
private selectedMsgId: Ref<ActivityMessage> | undefined = undefined
|
private selectedMsgId: Ref<ActivityMessage> | undefined = undefined
|
||||||
private tailStart: Timestamp | undefined = undefined
|
private tailStart: Timestamp | undefined = undefined
|
||||||
@ -101,15 +102,15 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
constructor (
|
constructor (
|
||||||
chatId: Ref<Doc>,
|
chatId: Ref<Doc>,
|
||||||
_class: Ref<Class<ActivityMessage>>,
|
_class: Ref<Class<ActivityMessage>>,
|
||||||
lastViewedTimestamp?: Timestamp,
|
context: DocNotifyContext | undefined,
|
||||||
selectedMsgId?: Ref<ActivityMessage>,
|
selectedMsgId?: Ref<ActivityMessage>,
|
||||||
loadAll = false
|
loadAll = false
|
||||||
) {
|
) {
|
||||||
this.chatId = chatId
|
this.chatId = chatId
|
||||||
this.lastViewedTimestamp = lastViewedTimestamp
|
this.context = context
|
||||||
this.msgClass = _class
|
this.msgClass = _class
|
||||||
this.selectedMsgId = selectedMsgId
|
this.selectedMsgId = selectedMsgId
|
||||||
this.loadData(loadAll)
|
void this.loadData(loadAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy (): void {
|
public destroy (): void {
|
||||||
@ -154,7 +155,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
this.selectedMsgId = undefined
|
this.selectedMsgId = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadData (loadAll = false): void {
|
private async loadData (loadAll = false): Promise<void> {
|
||||||
if (this.chatId === undefined) {
|
if (this.chatId === undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -182,10 +183,25 @@ 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(this.lastViewedTimestamp)
|
const firstNewMsgIndex = this.getFirstNewMsgIndex(firstNotification)
|
||||||
|
|
||||||
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)
|
||||||
@ -335,19 +351,33 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
return firsNewMsgIndex
|
return firsNewMsgIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFirstNewMsgIndex (lastViewedTimestamp?: Timestamp): number | undefined {
|
private getFirstNewMsgIndex (firstNotification: InboxNotification | undefined): number | undefined {
|
||||||
const metadata = get(this.metadataStore)
|
const metadata = get(this.metadataStore)
|
||||||
|
|
||||||
if (metadata.length === 0) {
|
if (metadata.length === 0) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastViewedTimestamp === undefined) {
|
if (this.context === undefined) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastViewedTimestamp = this.context.lastViewedTimestamp
|
||||||
|
|
||||||
|
if (lastViewedTimestamp === undefined && firstNotification === undefined) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
const me = getCurrentAccount()._id
|
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) => {
|
return metadata.findIndex((message) => {
|
||||||
if (message.createdBy === me) {
|
if (message.createdBy === me) {
|
||||||
return false
|
return false
|
||||||
@ -355,7 +385,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
|
|||||||
|
|
||||||
const createdOn = message.createdOn ?? 0
|
const createdOn = message.createdOn ?? 0
|
||||||
|
|
||||||
return lastViewedTimestamp < createdOn
|
return newTimestamp < createdOn
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<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 notification, { DocNotifyContext } from '@hcengineering/notification'
|
||||||
import activity, { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
|
import activity, { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
@ -61,29 +61,25 @@
|
|||||||
$: _class = isDocChannel ? activity.class.ActivityMessage : chunter.class.ChatMessage
|
$: _class = isDocChannel ? activity.class.ActivityMessage : chunter.class.ChatMessage
|
||||||
$: collection = isDocChannel ? 'comments' : 'messages'
|
$: collection = isDocChannel ? 'comments' : 'messages'
|
||||||
|
|
||||||
$: updateDataProvider(object._id, _class, context?.lastViewedTimestamp, selectedMessageId)
|
$: void updateDataProvider(object._id, _class, selectedMessageId)
|
||||||
|
|
||||||
async function updateDataProvider (
|
async function updateDataProvider (
|
||||||
attachedTo: Ref<Doc>,
|
attachedTo: Ref<Doc>,
|
||||||
_class: Ref<Class<ActivityMessage>>,
|
_class: Ref<Class<ActivityMessage>>,
|
||||||
lastViewedTimestamp?: Timestamp,
|
|
||||||
selectedMessageId?: Ref<ActivityMessage>
|
selectedMessageId?: Ref<ActivityMessage>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (dataProvider === undefined) {
|
if (dataProvider === undefined) {
|
||||||
// For now loading all messages for documents with activity. Need to correct handle aggregation with pagination.
|
// 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
|
// 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 loadAll = isDocChannel
|
||||||
const timestamp =
|
const ctx =
|
||||||
lastViewedTimestamp ??
|
context ??
|
||||||
(
|
(await client.findOne(notification.class.DocNotifyContext, {
|
||||||
await client.findOne(
|
attachedTo: object._id,
|
||||||
notification.class.DocNotifyContext,
|
user: getCurrentAccount()._id
|
||||||
{ attachedTo: object._id, user: getCurrentAccount()._id },
|
}))
|
||||||
{ projection: { lastViewedTimestamp: 1 } }
|
|
||||||
)
|
|
||||||
)?.lastViewedTimestamp
|
|
||||||
|
|
||||||
dataProvider = new ChannelDataProvider(attachedTo, _class, timestamp, selectedMessageId, loadAll)
|
dataProvider = new ChannelDataProvider(attachedTo, _class, ctx, selectedMessageId, loadAll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import activity, { ActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
|
import activity, { ActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
|
||||||
import { Analytics } from '@hcengineering/analytics'
|
|
||||||
import chunter, { ChatMessage } from '@hcengineering/chunter'
|
import chunter, { ChatMessage } from '@hcengineering/chunter'
|
||||||
import contact, {
|
import contact, {
|
||||||
type AvatarInfo,
|
type AvatarInfo,
|
||||||
@ -467,12 +466,6 @@ async function activityInboxNotificationToText (doc: Data<ActivityInboxNotificat
|
|||||||
body = await translate(doc.body, params)
|
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]
|
return [title, body]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1299,7 +1292,7 @@ async function applyUserTxes (
|
|||||||
cache.set(account._id, account)
|
cache.set(account._id, account)
|
||||||
await control.apply(txs)
|
await control.apply(txs)
|
||||||
|
|
||||||
const m1 = toIdMap(txes)
|
const m1 = toIdMap(txs)
|
||||||
control.operationContext.derived.targets.docNotifyContext = (it) => {
|
control.operationContext.derived.targets.docNotifyContext = (it) => {
|
||||||
if (m1.has(it._id)) {
|
if (m1.has(it._id)) {
|
||||||
return [account.email]
|
return [account.email]
|
||||||
|
@ -414,7 +414,7 @@ export async function getNotificationContent (
|
|||||||
|
|
||||||
export async function getUsersInfo (ids: Ref<PersonAccount>[], control: TriggerControl): Promise<UserInfo[]> {
|
export async function getUsersInfo (ids: Ref<PersonAccount>[], control: TriggerControl): Promise<UserInfo[]> {
|
||||||
const accounts = await control.modelDb.findAll(contact.class.PersonAccount, { _id: { $in: ids } })
|
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) => ({
|
return accounts.map((account) => ({
|
||||||
_id: account._id,
|
_id: account._id,
|
||||||
|
Loading…
Reference in New Issue
Block a user