Fix channels hide and return autohide (#6529)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina
2024-09-11 22:35:18 +07:00
committed by GitHub
parent 4e44f73314
commit 682e4b3011
16 changed files with 129 additions and 196 deletions
+64 -132
View File
@@ -14,15 +14,8 @@
//
import activity, { ActivityMessage, ActivityReference } from '@hcengineering/activity'
import chunter, {
Channel,
ChannelInfo,
ChatMessage,
chunterId,
ChunterSpace,
ThreadMessage
} from '@hcengineering/chunter'
import { Person, PersonAccount } from '@hcengineering/contact'
import chunter, { Channel, ChatMessage, chunterId, ChunterSpace, ThreadMessage } from '@hcengineering/chunter'
import contact, { Person, PersonAccount } from '@hcengineering/contact'
import core, {
Account,
AttachedDoc,
@@ -39,7 +32,6 @@ import core, {
TxCollectionCUD,
TxCreateDoc,
TxCUD,
TxMixin,
TxProcessor,
TxRemoveDoc,
TxUpdateDoc,
@@ -391,94 +383,55 @@ function combineAttributes (attributes: any[], key: string, operator: string, ar
).filter((v) => v != null)
}
async function hideOldDirects (
directs: DocNotifyContext[],
control: TriggerControl,
date: Timestamp
): Promise<TxMixin<DocNotifyContext, ChannelInfo>[]> {
const visibleDirects = directs.filter((context) => {
const hasMixin = control.hierarchy.hasMixin(context, chunter.mixin.ChannelInfo)
if (!hasMixin) return true
const info = control.hierarchy.as(context, chunter.mixin.ChannelInfo)
return !info.hidden
})
function getDirectsToHide (directs: DocNotifyContext[], date: Timestamp): DocNotifyContext[] {
const minVisibleDirects = 10
if (visibleDirects.length <= minVisibleDirects) return []
const canHide = visibleDirects.length - minVisibleDirects
if (directs.length <= minVisibleDirects) return []
const hideCount = directs.length - minVisibleDirects
let toHide: DocNotifyContext[] = []
const toHide: DocNotifyContext[] = []
for (const context of directs) {
const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context
if (lastViewedTimestamp === 0) continue
if (lastUpdateTimestamp > lastViewedTimestamp) continue
if (date - lastUpdateTimestamp < hideChannelDelay) continue
toHide.push(context)
if (date - lastUpdateTimestamp > hideChannelDelay) {
toHide.push(context)
}
}
if (toHide.length > canHide) {
toHide = toHide.splice(0, toHide.length - canHide)
}
toHide.sort((a, b) => (a.lastUpdateTimestamp ?? 0) - (b.lastUpdateTimestamp ?? 0))
return await hideOldChannels(toHide, control)
return toHide.slice(0, hideCount)
}
async function hideOldActivityChannels (
contexts: DocNotifyContext[],
control: TriggerControl,
date: Timestamp
): Promise<TxMixin<DocNotifyContext, ChannelInfo>[]> {
function getActivityToHide (contexts: DocNotifyContext[], date: Timestamp): DocNotifyContext[] {
if (contexts.length === 0) return []
const { hierarchy } = control
const toHide: DocNotifyContext[] = []
for (const context of contexts) {
const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context
if (lastViewedTimestamp === 0) continue
if (lastUpdateTimestamp > lastViewedTimestamp) continue
if (date - lastUpdateTimestamp < hideChannelDelay) continue
const params = hierarchy.as(context, chunter.mixin.ChannelInfo)
if (params.hidden) continue
toHide.push(context)
if (date - lastUpdateTimestamp > hideChannelDelay) {
toHide.push(context)
}
}
return await hideOldChannels(toHide, control)
return toHide
}
async function hideOldChannels (
contexts: DocNotifyContext[],
control: TriggerControl
): Promise<TxMixin<DocNotifyContext, ChannelInfo>[]> {
const res: TxMixin<DocNotifyContext, ChannelInfo>[] = []
for (const context of contexts) {
const tx = control.txFactory.createTxMixin(context._id, context._class, context.space, chunter.mixin.ChannelInfo, {
hidden: true
})
res.push(tx)
}
return res
}
export async function updateChatInfo (control: TriggerControl, status: UserStatus, date: Timestamp): Promise<void> {
export async function syncChat (control: TriggerControl, status: UserStatus, date: Timestamp): Promise<void> {
const account = getPersonAccountById(status.user as Ref<PersonAccount>, control)
if (account === undefined) return
const update = (await control.findAll(control.ctx, chunter.class.ChatInfo, { user: account.person })).shift()
const shouldUpdate = update === undefined || date - update.timestamp > updateChatInfoDelay
if (!shouldUpdate) return
const syncInfo = (await control.findAll(control.ctx, chunter.class.ChatSyncInfo, { user: account.person })).shift()
const shouldSync = syncInfo === undefined || date - syncInfo.timestamp > updateChatInfoDelay
if (!shouldSync) return
const contexts = await control.findAll(control.ctx, notification.class.DocNotifyContext, {
user: account._id,
hidden: false,
isPinned: false
})
@@ -492,83 +445,63 @@ export async function updateChatInfo (control: TriggerControl, status: UserStatu
)
const activityContexts = contexts.filter(
({ objectClass }) =>
!hierarchy.isDerived(objectClass, chunter.class.DirectMessage) &&
!hierarchy.isDerived(objectClass, chunter.class.Channel) &&
!hierarchy.isDerived(objectClass, chunter.class.ChunterSpace) &&
!hierarchy.isDerived(objectClass, activity.class.ActivityMessage)
)
const directTxes = await hideOldDirects(directContexts, control, date)
const activityTxes = await hideOldActivityChannels(activityContexts, control, date)
const mixinTxes = directTxes.concat(activityTxes)
const hidden: Ref<DocNotifyContext>[] = mixinTxes.map((tx) => tx.objectId)
const directsToHide = getDirectsToHide(directContexts, date)
const activityToHide = getActivityToHide(activityContexts, date)
const contextsToHide = directsToHide.concat(activityToHide)
res.push(...mixinTxes)
if (update === undefined) {
for (const context of contextsToHide) {
res.push(
control.txFactory.createTxCreateDoc(chunter.class.ChatInfo, core.space.Workspace, {
user: account.person,
hidden,
timestamp: date
control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
hidden: true
})
)
}
if (syncInfo === undefined) {
const personSpace = (
await control.findAll(control.ctx, contact.class.PersonSpace, { person: account.person })
).shift()
if (personSpace !== undefined) {
res.push(
control.txFactory.createTxCreateDoc(chunter.class.ChatSyncInfo, personSpace._id, {
user: account.person,
timestamp: date
})
)
}
} else {
res.push(
control.txFactory.createTxUpdateDoc(update._class, update.space, update._id, {
hidden: Array.from(new Set(update.hidden.concat(hidden))),
control.txFactory.createTxUpdateDoc(syncInfo._class, syncInfo.space, syncInfo._id, {
timestamp: date
})
)
}
const txIds = res.map((tx) => tx._id)
await control.apply(control.ctx, res)
control.ctx.contextData.broadcast.targets.docNotifyContext = (it) => {
if (txIds.includes(it._id)) {
return [account.email]
}
}
await control.apply(control.ctx, res, true)
}
async function OnUserStatus (originTx: TxCUD<UserStatus>, control: TriggerControl): Promise<Tx[]> {
// const tx = TxProcessor.extractTx(originTx) as TxCUD<UserStatus>
// if (tx.objectClass !== core.class.UserStatus) return []
// if (tx._class === core.class.TxCreateDoc) {
// const createTx = tx as TxCreateDoc<UserStatus>
// const { online } = createTx.attributes
// if (online) {
// const status = TxProcessor.createDoc2Doc(createTx)
// await updateChatInfo(control, status, originTx.modifiedOn)
// }
// } else if (tx._class === core.class.TxUpdateDoc) {
// const updateTx = tx as TxUpdateDoc<UserStatus>
// const { online } = updateTx.operations
// if (online === true) {
// const status = (await control.findAll(core.class.UserStatus, { _id: updateTx.objectId }))[0]
// await updateChatInfo(control, status, originTx.modifiedOn)
// }
// }
return []
}
async function OnContextUpdate (tx: TxUpdateDoc<DocNotifyContext>, control: TriggerControl): Promise<Tx[]> {
const hasUpdate = 'lastUpdateTimestamp' in tx.operations && tx.operations.lastUpdateTimestamp !== undefined
if (!hasUpdate) return []
// const update = (await control.findAll(notification.class.DocNotifyContext, { _id: tx.objectId }, { limit: 1 })).shift()
// if (update !== undefined) {
// const as = control.hierarchy.as(update, chunter.mixin.ChannelInfo)
// if (as.hidden) {
// return [
// control.txFactory.createTxMixin(tx.objectId, tx.objectClass, tx.objectSpace, chunter.mixin.ChannelInfo, {
// hidden: false
// })
// ]
// }
// }
const tx = TxProcessor.extractTx(originTx) as TxCUD<UserStatus>
if (tx.objectClass !== core.class.UserStatus) return []
if (tx._class === core.class.TxCreateDoc) {
const createTx = tx as TxCreateDoc<UserStatus>
const { online } = createTx.attributes
if (online) {
const status = TxProcessor.createDoc2Doc(createTx)
await syncChat(control, status, originTx.modifiedOn)
}
} else if (tx._class === core.class.TxUpdateDoc) {
const updateTx = tx as TxUpdateDoc<UserStatus>
const { online } = updateTx.operations
if (online === true) {
const status = (await control.findAll(control.ctx, core.class.UserStatus, { _id: updateTx.objectId }))[0]
await syncChat(control, status, originTx.modifiedOn)
}
}
return []
}
@@ -589,8 +522,7 @@ export default async () => ({
ChunterTrigger,
OnChatMessageRemoved,
ChatNotificationsHandler,
OnUserStatus,
OnContextUpdate
OnUserStatus
},
function: {
CommentRemove,
+1 -2
View File
@@ -31,8 +31,7 @@ export default plugin(serverChunterId, {
ChunterTrigger: '' as Resource<TriggerFunc>,
OnChatMessageRemoved: '' as Resource<TriggerFunc>,
ChatNotificationsHandler: '' as Resource<TriggerFunc>,
OnUserStatus: '' as Resource<TriggerFunc>,
OnContextUpdate: '' as Resource<TriggerFunc>
OnUserStatus: '' as Resource<TriggerFunc>
},
function: {
CommentRemove: '' as Resource<ObjectDDParticipantFunc>,
@@ -716,6 +716,7 @@ async function createNotifyContext (
objectClass,
objectSpace,
isPinned: false,
hidden: false,
tx: tx?._id,
lastUpdateTimestamp: updateTimestamp,
lastViewedTimestamp: sender === receiver._id ? updateTimestamp : undefined
@@ -828,10 +829,11 @@ async function updateContextsTimestamp (
const res: Tx[] = []
for (const context of contexts) {
const account = getPersonAccountById(context.user, control) // accounts.find(({ _id }) => _id === context.user)
const account = getPersonAccountById(context.user, control)
const isViewed =
context.lastViewedTimestamp !== undefined && (context.lastUpdateTimestamp ?? 0) <= context.lastViewedTimestamp
const updateTx = control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
hidden: false,
lastUpdateTimestamp: timestamp,
...(isViewed && modifiedBy === context.user
? {
@@ -1680,7 +1682,11 @@ async function updateCollaborators (
const info = toReceiverInfo(hierarchy, addedUser)
if (info === undefined) continue
const context = getDocNotifyContext(control, contexts, objectId, info._id)
if (context !== undefined) continue
if (context !== undefined) {
if (context.hidden) {
res.push(control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, { hidden: false }))
}
}
await createNotifyContext(ctx, control, objectId, objectClass, objectSpace, info, tx.modifiedBy, undefined, tx)
}