mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 03:14:40 +03:00
Fix channels hide and return autohide (#6529)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
4e44f73314
commit
682e4b3011
@ -23,8 +23,7 @@ import {
|
|||||||
type ChunterSpace,
|
type ChunterSpace,
|
||||||
type ObjectChatPanel,
|
type ObjectChatPanel,
|
||||||
type ThreadMessage,
|
type ThreadMessage,
|
||||||
type ChatInfo,
|
type ChatSyncInfo,
|
||||||
type ChannelInfo,
|
|
||||||
type InlineButton,
|
type InlineButton,
|
||||||
type TypingInfo,
|
type TypingInfo,
|
||||||
type InlineButtonAction
|
type InlineButtonAction
|
||||||
@ -52,12 +51,10 @@ import {
|
|||||||
TypeRef,
|
TypeRef,
|
||||||
TypeString,
|
TypeString,
|
||||||
TypeTimestamp,
|
TypeTimestamp,
|
||||||
UX,
|
UX
|
||||||
Hidden
|
|
||||||
} from '@hcengineering/model'
|
} from '@hcengineering/model'
|
||||||
import attachment from '@hcengineering/model-attachment'
|
import attachment from '@hcengineering/model-attachment'
|
||||||
import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@hcengineering/model-core'
|
import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@hcengineering/model-core'
|
||||||
import notification, { TDocNotifyContext } from '@hcengineering/model-notification'
|
|
||||||
import view from '@hcengineering/model-view'
|
import view from '@hcengineering/model-view'
|
||||||
import workbench from '@hcengineering/model-workbench'
|
import workbench from '@hcengineering/model-workbench'
|
||||||
import { type IntlString, type Resource } from '@hcengineering/platform'
|
import { type IntlString, type Resource } from '@hcengineering/platform'
|
||||||
@ -152,14 +149,8 @@ export class TObjectChatPanel extends TClass implements ObjectChatPanel {
|
|||||||
ignoreKeys!: string[]
|
ignoreKeys!: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mixin(chunter.mixin.ChannelInfo, notification.class.DocNotifyContext)
|
@Model(chunter.class.ChatSyncInfo, core.class.Doc, DOMAIN_CHUNTER)
|
||||||
export class TChannelInfo extends TDocNotifyContext implements ChannelInfo {
|
export class TChatSyncInfo extends TDoc implements ChatSyncInfo {
|
||||||
@Hidden()
|
|
||||||
hidden!: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
@Model(chunter.class.ChatInfo, core.class.Doc, DOMAIN_CHUNTER)
|
|
||||||
export class TChatInfo extends TDoc implements ChatInfo {
|
|
||||||
user!: Ref<Person>
|
user!: Ref<Person>
|
||||||
hidden!: Ref<DocNotifyContext>[]
|
hidden!: Ref<DocNotifyContext>[]
|
||||||
timestamp!: Timestamp
|
timestamp!: Timestamp
|
||||||
@ -190,8 +181,7 @@ export function createModel (builder: Builder): void {
|
|||||||
TThreadMessage,
|
TThreadMessage,
|
||||||
TChatMessageViewlet,
|
TChatMessageViewlet,
|
||||||
TObjectChatPanel,
|
TObjectChatPanel,
|
||||||
TChatInfo,
|
TChatSyncInfo,
|
||||||
TChannelInfo,
|
|
||||||
TInlineButton,
|
TInlineButton,
|
||||||
TTypingInfo
|
TTypingInfo
|
||||||
)
|
)
|
||||||
|
@ -67,6 +67,7 @@ export async function createDocNotifyContexts (
|
|||||||
objectId,
|
objectId,
|
||||||
objectClass,
|
objectClass,
|
||||||
objectSpace,
|
objectSpace,
|
||||||
|
hidden: false,
|
||||||
isPinned: false
|
isPinned: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -332,6 +333,19 @@ export const chunterOperation: MigrateOperation = {
|
|||||||
await removeWrongActivity(client)
|
await removeWrongActivity(client)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
state: 'remove-chat-info-v1',
|
||||||
|
func: async (client) => {
|
||||||
|
await client.deleteMany(DOMAIN_CHUNTER, { _class: 'chunter:class:ChatInfo' as Ref<Class<Doc>> })
|
||||||
|
await client.deleteMany(DOMAIN_TX, { objectClass: 'chunter:class:ChatInfo' })
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_DOC_NOTIFY,
|
||||||
|
{ 'chunter:mixin:ChannelInfo': { $exists: true } },
|
||||||
|
{ $unset: { 'chunter:mixin:ChannelInfo': true } }
|
||||||
|
)
|
||||||
|
await client.deleteMany(DOMAIN_TX, { mixin: 'chunter:mixin:ChannelInfo' })
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
state: 'remove-duplicated-directs-v1',
|
state: 'remove-duplicated-directs-v1',
|
||||||
func: async (client) => {
|
func: async (client) => {
|
||||||
|
@ -218,6 +218,9 @@ export class TDocNotifyContext extends TDoc implements DocNotifyContext {
|
|||||||
@Prop(TypeBoolean(), notification.string.Pinned)
|
@Prop(TypeBoolean(), notification.string.Pinned)
|
||||||
isPinned!: boolean
|
isPinned!: boolean
|
||||||
|
|
||||||
|
@Prop(TypeBoolean(), view.string.Hide)
|
||||||
|
hidden!: boolean
|
||||||
|
|
||||||
tx?: Ref<TxCUD<Doc>>
|
tx?: Ref<TxCUD<Doc>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +383,16 @@ export const notificationOperation: MigrateOperation = {
|
|||||||
{
|
{
|
||||||
state: 'migrate-duplicated-contexts-v1',
|
state: 'migrate-duplicated-contexts-v1',
|
||||||
func: migrateDuplicateContexts
|
func: migrateDuplicateContexts
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: 'set-default-hidden',
|
||||||
|
func: async () => {
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_DOC_NOTIFY,
|
||||||
|
{ _class: notification.class.DocNotifyContext, hidden: { $exists: false } },
|
||||||
|
{ hidden: false }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -75,14 +75,6 @@ export function createModel (builder: Builder): void {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
|
||||||
trigger: serverChunter.trigger.OnContextUpdate,
|
|
||||||
txMatch: {
|
|
||||||
_class: core.class.TxUpdateDoc,
|
|
||||||
objectClass: notification.class.DocNotifyContext
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||||
trigger: serverChunter.trigger.OnChatMessageRemoved,
|
trigger: serverChunter.trigger.OnChatMessageRemoved,
|
||||||
txMatch: {
|
txMatch: {
|
||||||
|
@ -97,9 +97,12 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (context !== undefined) {
|
if (context !== undefined) {
|
||||||
|
if (context.hidden) {
|
||||||
|
await client.updateDoc(context._class, context.space, context._id, { hidden: false })
|
||||||
|
}
|
||||||
|
|
||||||
dispatch('close')
|
dispatch('close')
|
||||||
openChannel(dmId, chunter.class.DirectMessage)
|
openChannel(dmId, chunter.class.DirectMessage)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +113,7 @@
|
|||||||
objectId: dmId,
|
objectId: dmId,
|
||||||
objectClass: chunter.class.DirectMessage,
|
objectClass: chunter.class.DirectMessage,
|
||||||
objectSpace: core.space.Space,
|
objectSpace: core.space.Space,
|
||||||
|
hidden: false,
|
||||||
isPinned: false
|
isPinned: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -50,7 +50,9 @@
|
|||||||
|
|
||||||
let sections: Section[] = []
|
let sections: Section[] = []
|
||||||
|
|
||||||
$: contexts = $contextsStore.filter(({ objectClass, isPinned }) => {
|
$: contexts = $contextsStore.filter((it) => {
|
||||||
|
const { objectClass, isPinned, hidden } = it
|
||||||
|
if (hidden) return false
|
||||||
if (model.isPinned !== isPinned) return false
|
if (model.isPinned !== isPinned) return false
|
||||||
if (model._class !== undefined && model._class !== objectClass) return false
|
if (model._class !== undefined && model._class !== objectClass) return false
|
||||||
if (model.skipClasses !== undefined && model.skipClasses.includes(objectClass)) return false
|
if (model.skipClasses !== undefined && model.skipClasses.includes(objectClass)) return false
|
||||||
|
@ -357,7 +357,7 @@ function archiveActivityChannels (contexts: DocNotifyContext[]): void {
|
|||||||
label: chunter.string.ArchiveActivityConfirmationTitle,
|
label: chunter.string.ArchiveActivityConfirmationTitle,
|
||||||
message: chunter.string.ArchiveActivityConfirmationMessage,
|
message: chunter.string.ArchiveActivityConfirmationMessage,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
await removeActivityChannels(contexts)
|
await hideActivityChannels(contexts)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'top'
|
'top'
|
||||||
@ -385,19 +385,12 @@ export function loadSavedAttachments (): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeActivityChannels (contexts: DocNotifyContext[]): Promise<void> {
|
export async function hideActivityChannels (contexts: DocNotifyContext[]): Promise<void> {
|
||||||
const ops = getClient().apply(undefined, 'removeActivityChannels')
|
const ops = getClient().apply(undefined, 'hideActivityChannels')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const context of contexts) {
|
for (const context of contexts) {
|
||||||
await ops.createMixin(context._id, context._class, context.space, chunter.mixin.ChannelInfo, { hidden: true })
|
await ops.update(context, { hidden: true })
|
||||||
}
|
|
||||||
const hidden = contexts.map(({ _id }) => _id)
|
|
||||||
const account = getCurrentAccount() as PersonAccount
|
|
||||||
const chatInfo = await ops.findOne(chunter.class.ChatInfo, { user: account.person })
|
|
||||||
|
|
||||||
if (chatInfo !== undefined) {
|
|
||||||
await ops.update(chatInfo, { hidden: chatInfo.hidden.concat(hidden) })
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
await ops.commit()
|
await ops.commit()
|
||||||
@ -412,7 +405,7 @@ export async function readActivityChannels (contexts: DocNotifyContext[]): Promi
|
|||||||
try {
|
try {
|
||||||
for (const context of contexts) {
|
for (const context of contexts) {
|
||||||
const notifications = notificationsByContext.get(context._id) ?? []
|
const notifications = notificationsByContext.get(context._id) ?? []
|
||||||
await client.archiveNotifications(
|
await client.readNotifications(
|
||||||
ops,
|
ops,
|
||||||
notifications
|
notifications
|
||||||
.filter(({ _class }) => _class === notification.class.ActivityInboxNotification)
|
.filter(({ _class }) => _class === notification.class.ActivityInboxNotification)
|
||||||
|
@ -513,21 +513,12 @@ export async function removeChannelAction (context?: DocNotifyContext, _?: Event
|
|||||||
if (hierarchy.isDerived(objectClass, chunter.class.Channel)) {
|
if (hierarchy.isDerived(objectClass, chunter.class.Channel)) {
|
||||||
const channel = await client.findOne(chunter.class.Channel, { _id: objectId as Ref<Channel>, space: objectSpace })
|
const channel = await client.findOne(chunter.class.Channel, { _id: objectId as Ref<Channel>, space: objectSpace })
|
||||||
await leaveChannel(channel, getCurrentAccount()._id)
|
await leaveChannel(channel, getCurrentAccount()._id)
|
||||||
|
await client.remove(context)
|
||||||
} else {
|
} else {
|
||||||
const object = await client.findOne(objectClass, { _id: objectId, space: objectSpace })
|
const object = await client.findOne(objectClass, { _id: objectId, space: objectSpace })
|
||||||
// const account = getCurrentAccount() as PersonAccount
|
await client.update(context, { hidden: true })
|
||||||
|
|
||||||
// await client.createMixin(context._id, context._class, context.space, chunter.mixin.ChannelInfo, { hidden: true })
|
|
||||||
//
|
|
||||||
// const chatInfo = await client.findOne(chunter.class.ChatInfo, { user: account.person })
|
|
||||||
//
|
|
||||||
// if (chatInfo !== undefined) {
|
|
||||||
// await client.update(chatInfo, { hidden: chatInfo.hidden.concat([context._id]) })
|
|
||||||
// }
|
|
||||||
await resetChunterLocIfEqual(objectId, objectClass, object)
|
await resetChunterLocIfEqual(objectId, objectClass, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.remove(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isThreadMessage (message: ActivityMessage): message is ThreadMessage {
|
export function isThreadMessage (message: ActivityMessage): message is ThreadMessage {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import { ActivityMessage, ActivityMessageViewlet } from '@hcengineering/activity'
|
import { ActivityMessage, ActivityMessageViewlet } from '@hcengineering/activity'
|
||||||
import type { AttachedDoc, Class, Doc, Markup, Mixin, Ref, Space, Timestamp } from '@hcengineering/core'
|
import type { AttachedDoc, Class, Doc, Markup, Mixin, Ref, Space, Timestamp } from '@hcengineering/core'
|
||||||
import { DocNotifyContext, NotificationType } from '@hcengineering/notification'
|
import { NotificationType } from '@hcengineering/notification'
|
||||||
import type { Asset, Plugin, Resource } from '@hcengineering/platform'
|
import type { Asset, Plugin, Resource } from '@hcengineering/platform'
|
||||||
import { IntlString, plugin } from '@hcengineering/platform'
|
import { IntlString, plugin } from '@hcengineering/platform'
|
||||||
import { AnyComponent } from '@hcengineering/ui'
|
import { AnyComponent } from '@hcengineering/ui'
|
||||||
@ -77,9 +77,8 @@ export interface ChatMessageViewlet extends ActivityMessageViewlet {
|
|||||||
label?: IntlString
|
label?: IntlString
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChatInfo extends Doc {
|
export interface ChatSyncInfo extends Doc {
|
||||||
user: Ref<Person>
|
user: Ref<Person>
|
||||||
hidden: Ref<DocNotifyContext>[]
|
|
||||||
timestamp: Timestamp
|
timestamp: Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,10 +89,6 @@ export interface TypingInfo extends Doc {
|
|||||||
lastTyping: Timestamp
|
lastTyping: Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChannelInfo extends DocNotifyContext {
|
|
||||||
hidden: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export type InlineButtonAction = (button: InlineButton, message: Ref<ChatMessage>, channel: Ref<Doc>) => Promise<void>
|
export type InlineButtonAction = (button: InlineButton, message: Ref<ChatMessage>, channel: Ref<Doc>) => Promise<void>
|
||||||
|
|
||||||
export interface InlineButton extends AttachedDoc {
|
export interface InlineButton extends AttachedDoc {
|
||||||
@ -146,13 +141,12 @@ export default plugin(chunterId, {
|
|||||||
DirectMessage: '' as Ref<Class<DirectMessage>>,
|
DirectMessage: '' as Ref<Class<DirectMessage>>,
|
||||||
ChatMessage: '' as Ref<Class<ChatMessage>>,
|
ChatMessage: '' as Ref<Class<ChatMessage>>,
|
||||||
ChatMessageViewlet: '' as Ref<Class<ChatMessageViewlet>>,
|
ChatMessageViewlet: '' as Ref<Class<ChatMessageViewlet>>,
|
||||||
ChatInfo: '' as Ref<Class<ChatInfo>>,
|
ChatSyncInfo: '' as Ref<Class<ChatSyncInfo>>,
|
||||||
InlineButton: '' as Ref<Class<InlineButton>>,
|
InlineButton: '' as Ref<Class<InlineButton>>,
|
||||||
TypingInfo: '' as Ref<Class<TypingInfo>>
|
TypingInfo: '' as Ref<Class<TypingInfo>>
|
||||||
},
|
},
|
||||||
mixin: {
|
mixin: {
|
||||||
ObjectChatPanel: '' as Ref<Mixin<ObjectChatPanel>>,
|
ObjectChatPanel: '' as Ref<Mixin<ObjectChatPanel>>
|
||||||
ChannelInfo: '' as Ref<Mixin<ChannelInfo>>
|
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
Reactions: '' as IntlString,
|
Reactions: '' as IntlString,
|
||||||
|
@ -285,6 +285,7 @@ export interface DocNotifyContext extends Doc<PersonSpace> {
|
|||||||
objectSpace: Ref<Space>
|
objectSpace: Ref<Space>
|
||||||
|
|
||||||
isPinned: boolean
|
isPinned: boolean
|
||||||
|
hidden: boolean
|
||||||
lastViewedTimestamp?: Timestamp
|
lastViewedTimestamp?: Timestamp
|
||||||
lastUpdateTimestamp?: Timestamp
|
lastUpdateTimestamp?: Timestamp
|
||||||
|
|
||||||
|
@ -14,15 +14,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import activity, { ActivityMessage, ActivityReference } from '@hcengineering/activity'
|
import activity, { ActivityMessage, ActivityReference } from '@hcengineering/activity'
|
||||||
import chunter, {
|
import chunter, { Channel, ChatMessage, chunterId, ChunterSpace, ThreadMessage } from '@hcengineering/chunter'
|
||||||
Channel,
|
import contact, { Person, PersonAccount } from '@hcengineering/contact'
|
||||||
ChannelInfo,
|
|
||||||
ChatMessage,
|
|
||||||
chunterId,
|
|
||||||
ChunterSpace,
|
|
||||||
ThreadMessage
|
|
||||||
} from '@hcengineering/chunter'
|
|
||||||
import { Person, PersonAccount } from '@hcengineering/contact'
|
|
||||||
import core, {
|
import core, {
|
||||||
Account,
|
Account,
|
||||||
AttachedDoc,
|
AttachedDoc,
|
||||||
@ -39,7 +32,6 @@ import core, {
|
|||||||
TxCollectionCUD,
|
TxCollectionCUD,
|
||||||
TxCreateDoc,
|
TxCreateDoc,
|
||||||
TxCUD,
|
TxCUD,
|
||||||
TxMixin,
|
|
||||||
TxProcessor,
|
TxProcessor,
|
||||||
TxRemoveDoc,
|
TxRemoveDoc,
|
||||||
TxUpdateDoc,
|
TxUpdateDoc,
|
||||||
@ -391,94 +383,55 @@ function combineAttributes (attributes: any[], key: string, operator: string, ar
|
|||||||
).filter((v) => v != null)
|
).filter((v) => v != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hideOldDirects (
|
function getDirectsToHide (directs: DocNotifyContext[], date: Timestamp): DocNotifyContext[] {
|
||||||
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
|
|
||||||
})
|
|
||||||
|
|
||||||
const minVisibleDirects = 10
|
const minVisibleDirects = 10
|
||||||
|
|
||||||
if (visibleDirects.length <= minVisibleDirects) return []
|
if (directs.length <= minVisibleDirects) return []
|
||||||
const canHide = visibleDirects.length - minVisibleDirects
|
const hideCount = directs.length - minVisibleDirects
|
||||||
|
|
||||||
let toHide: DocNotifyContext[] = []
|
const toHide: DocNotifyContext[] = []
|
||||||
|
|
||||||
for (const context of directs) {
|
for (const context of directs) {
|
||||||
const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context
|
const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context
|
||||||
|
if (lastViewedTimestamp === 0) continue
|
||||||
if (lastUpdateTimestamp > lastViewedTimestamp) continue
|
if (lastUpdateTimestamp > lastViewedTimestamp) continue
|
||||||
if (date - lastUpdateTimestamp < hideChannelDelay) continue
|
if (date - lastUpdateTimestamp > hideChannelDelay) {
|
||||||
|
toHide.push(context)
|
||||||
toHide.push(context)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toHide.length > canHide) {
|
toHide.sort((a, b) => (a.lastUpdateTimestamp ?? 0) - (b.lastUpdateTimestamp ?? 0))
|
||||||
toHide = toHide.splice(0, toHide.length - canHide)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await hideOldChannels(toHide, control)
|
return toHide.slice(0, hideCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hideOldActivityChannels (
|
function getActivityToHide (contexts: DocNotifyContext[], date: Timestamp): DocNotifyContext[] {
|
||||||
contexts: DocNotifyContext[],
|
|
||||||
control: TriggerControl,
|
|
||||||
date: Timestamp
|
|
||||||
): Promise<TxMixin<DocNotifyContext, ChannelInfo>[]> {
|
|
||||||
if (contexts.length === 0) return []
|
if (contexts.length === 0) return []
|
||||||
|
|
||||||
const { hierarchy } = control
|
|
||||||
const toHide: DocNotifyContext[] = []
|
const toHide: DocNotifyContext[] = []
|
||||||
|
|
||||||
for (const context of contexts) {
|
for (const context of contexts) {
|
||||||
const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context
|
const { lastUpdateTimestamp = 0, lastViewedTimestamp = 0 } = context
|
||||||
|
if (lastViewedTimestamp === 0) continue
|
||||||
if (lastUpdateTimestamp > lastViewedTimestamp) continue
|
if (lastUpdateTimestamp > lastViewedTimestamp) continue
|
||||||
if (date - lastUpdateTimestamp < hideChannelDelay) continue
|
if (date - lastUpdateTimestamp > hideChannelDelay) {
|
||||||
|
toHide.push(context)
|
||||||
const params = hierarchy.as(context, chunter.mixin.ChannelInfo)
|
}
|
||||||
if (params.hidden) continue
|
|
||||||
|
|
||||||
toHide.push(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return await hideOldChannels(toHide, control)
|
return toHide
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hideOldChannels (
|
export async function syncChat (control: TriggerControl, status: UserStatus, date: Timestamp): Promise<void> {
|
||||||
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> {
|
|
||||||
const account = getPersonAccountById(status.user as Ref<PersonAccount>, control)
|
const account = getPersonAccountById(status.user as Ref<PersonAccount>, control)
|
||||||
if (account === undefined) return
|
if (account === undefined) return
|
||||||
|
|
||||||
const update = (await control.findAll(control.ctx, chunter.class.ChatInfo, { user: account.person })).shift()
|
const syncInfo = (await control.findAll(control.ctx, chunter.class.ChatSyncInfo, { user: account.person })).shift()
|
||||||
const shouldUpdate = update === undefined || date - update.timestamp > updateChatInfoDelay
|
const shouldSync = syncInfo === undefined || date - syncInfo.timestamp > updateChatInfoDelay
|
||||||
|
if (!shouldSync) return
|
||||||
if (!shouldUpdate) return
|
|
||||||
|
|
||||||
const contexts = await control.findAll(control.ctx, notification.class.DocNotifyContext, {
|
const contexts = await control.findAll(control.ctx, notification.class.DocNotifyContext, {
|
||||||
user: account._id,
|
user: account._id,
|
||||||
|
hidden: false,
|
||||||
isPinned: false
|
isPinned: false
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -492,83 +445,63 @@ export async function updateChatInfo (control: TriggerControl, status: UserStatu
|
|||||||
)
|
)
|
||||||
const activityContexts = contexts.filter(
|
const activityContexts = contexts.filter(
|
||||||
({ objectClass }) =>
|
({ objectClass }) =>
|
||||||
!hierarchy.isDerived(objectClass, chunter.class.DirectMessage) &&
|
!hierarchy.isDerived(objectClass, chunter.class.ChunterSpace) &&
|
||||||
!hierarchy.isDerived(objectClass, chunter.class.Channel) &&
|
|
||||||
!hierarchy.isDerived(objectClass, activity.class.ActivityMessage)
|
!hierarchy.isDerived(objectClass, activity.class.ActivityMessage)
|
||||||
)
|
)
|
||||||
|
|
||||||
const directTxes = await hideOldDirects(directContexts, control, date)
|
const directsToHide = getDirectsToHide(directContexts, date)
|
||||||
const activityTxes = await hideOldActivityChannels(activityContexts, control, date)
|
const activityToHide = getActivityToHide(activityContexts, date)
|
||||||
const mixinTxes = directTxes.concat(activityTxes)
|
const contextsToHide = directsToHide.concat(activityToHide)
|
||||||
const hidden: Ref<DocNotifyContext>[] = mixinTxes.map((tx) => tx.objectId)
|
|
||||||
|
|
||||||
res.push(...mixinTxes)
|
for (const context of contextsToHide) {
|
||||||
|
|
||||||
if (update === undefined) {
|
|
||||||
res.push(
|
res.push(
|
||||||
control.txFactory.createTxCreateDoc(chunter.class.ChatInfo, core.space.Workspace, {
|
control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
|
||||||
user: account.person,
|
hidden: true
|
||||||
hidden,
|
|
||||||
timestamp: date
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
res.push(
|
res.push(
|
||||||
control.txFactory.createTxUpdateDoc(update._class, update.space, update._id, {
|
control.txFactory.createTxUpdateDoc(syncInfo._class, syncInfo.space, syncInfo._id, {
|
||||||
hidden: Array.from(new Set(update.hidden.concat(hidden))),
|
|
||||||
timestamp: date
|
timestamp: date
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const txIds = res.map((tx) => tx._id)
|
await control.apply(control.ctx, res, true)
|
||||||
|
|
||||||
await control.apply(control.ctx, res)
|
|
||||||
|
|
||||||
control.ctx.contextData.broadcast.targets.docNotifyContext = (it) => {
|
|
||||||
if (txIds.includes(it._id)) {
|
|
||||||
return [account.email]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function OnUserStatus (originTx: TxCUD<UserStatus>, control: TriggerControl): Promise<Tx[]> {
|
async function OnUserStatus (originTx: TxCUD<UserStatus>, control: TriggerControl): Promise<Tx[]> {
|
||||||
// const tx = TxProcessor.extractTx(originTx) as TxCUD<UserStatus>
|
const tx = TxProcessor.extractTx(originTx) as TxCUD<UserStatus>
|
||||||
// if (tx.objectClass !== core.class.UserStatus) return []
|
if (tx.objectClass !== core.class.UserStatus) return []
|
||||||
// if (tx._class === core.class.TxCreateDoc) {
|
if (tx._class === core.class.TxCreateDoc) {
|
||||||
// const createTx = tx as TxCreateDoc<UserStatus>
|
const createTx = tx as TxCreateDoc<UserStatus>
|
||||||
// const { online } = createTx.attributes
|
const { online } = createTx.attributes
|
||||||
// if (online) {
|
if (online) {
|
||||||
// const status = TxProcessor.createDoc2Doc(createTx)
|
const status = TxProcessor.createDoc2Doc(createTx)
|
||||||
// await updateChatInfo(control, status, originTx.modifiedOn)
|
await syncChat(control, status, originTx.modifiedOn)
|
||||||
// }
|
}
|
||||||
// } else if (tx._class === core.class.TxUpdateDoc) {
|
} else if (tx._class === core.class.TxUpdateDoc) {
|
||||||
// const updateTx = tx as TxUpdateDoc<UserStatus>
|
const updateTx = tx as TxUpdateDoc<UserStatus>
|
||||||
// const { online } = updateTx.operations
|
const { online } = updateTx.operations
|
||||||
// if (online === true) {
|
if (online === true) {
|
||||||
// const status = (await control.findAll(core.class.UserStatus, { _id: updateTx.objectId }))[0]
|
const status = (await control.findAll(control.ctx, core.class.UserStatus, { _id: updateTx.objectId }))[0]
|
||||||
// await updateChatInfo(control, status, originTx.modifiedOn)
|
await syncChat(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
|
|
||||||
// })
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -589,8 +522,7 @@ export default async () => ({
|
|||||||
ChunterTrigger,
|
ChunterTrigger,
|
||||||
OnChatMessageRemoved,
|
OnChatMessageRemoved,
|
||||||
ChatNotificationsHandler,
|
ChatNotificationsHandler,
|
||||||
OnUserStatus,
|
OnUserStatus
|
||||||
OnContextUpdate
|
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
CommentRemove,
|
CommentRemove,
|
||||||
|
@ -31,8 +31,7 @@ export default plugin(serverChunterId, {
|
|||||||
ChunterTrigger: '' as Resource<TriggerFunc>,
|
ChunterTrigger: '' as Resource<TriggerFunc>,
|
||||||
OnChatMessageRemoved: '' as Resource<TriggerFunc>,
|
OnChatMessageRemoved: '' as Resource<TriggerFunc>,
|
||||||
ChatNotificationsHandler: '' as Resource<TriggerFunc>,
|
ChatNotificationsHandler: '' as Resource<TriggerFunc>,
|
||||||
OnUserStatus: '' as Resource<TriggerFunc>,
|
OnUserStatus: '' as Resource<TriggerFunc>
|
||||||
OnContextUpdate: '' as Resource<TriggerFunc>
|
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
CommentRemove: '' as Resource<ObjectDDParticipantFunc>,
|
CommentRemove: '' as Resource<ObjectDDParticipantFunc>,
|
||||||
|
@ -716,6 +716,7 @@ async function createNotifyContext (
|
|||||||
objectClass,
|
objectClass,
|
||||||
objectSpace,
|
objectSpace,
|
||||||
isPinned: false,
|
isPinned: false,
|
||||||
|
hidden: false,
|
||||||
tx: tx?._id,
|
tx: tx?._id,
|
||||||
lastUpdateTimestamp: updateTimestamp,
|
lastUpdateTimestamp: updateTimestamp,
|
||||||
lastViewedTimestamp: sender === receiver._id ? updateTimestamp : undefined
|
lastViewedTimestamp: sender === receiver._id ? updateTimestamp : undefined
|
||||||
@ -828,10 +829,11 @@ async function updateContextsTimestamp (
|
|||||||
const res: Tx[] = []
|
const res: Tx[] = []
|
||||||
|
|
||||||
for (const context of contexts) {
|
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 =
|
const isViewed =
|
||||||
context.lastViewedTimestamp !== undefined && (context.lastUpdateTimestamp ?? 0) <= context.lastViewedTimestamp
|
context.lastViewedTimestamp !== undefined && (context.lastUpdateTimestamp ?? 0) <= context.lastViewedTimestamp
|
||||||
const updateTx = control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
|
const updateTx = control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
|
||||||
|
hidden: false,
|
||||||
lastUpdateTimestamp: timestamp,
|
lastUpdateTimestamp: timestamp,
|
||||||
...(isViewed && modifiedBy === context.user
|
...(isViewed && modifiedBy === context.user
|
||||||
? {
|
? {
|
||||||
@ -1680,7 +1682,11 @@ async function updateCollaborators (
|
|||||||
const info = toReceiverInfo(hierarchy, addedUser)
|
const info = toReceiverInfo(hierarchy, addedUser)
|
||||||
if (info === undefined) continue
|
if (info === undefined) continue
|
||||||
const context = getDocNotifyContext(control, contexts, objectId, info._id)
|
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)
|
await createNotifyContext(ctx, control, objectId, objectClass, objectSpace, info, tx.modifiedBy, undefined, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,8 @@ export async function getDirect (
|
|||||||
objectId: dmId,
|
objectId: dmId,
|
||||||
objectClass: chunter.class.DirectMessage,
|
objectClass: chunter.class.DirectMessage,
|
||||||
objectSpace: core.space.Space,
|
objectSpace: core.space.Space,
|
||||||
isPinned: false
|
isPinned: false,
|
||||||
|
hidden: false
|
||||||
})
|
})
|
||||||
|
|
||||||
return dmId
|
return dmId
|
||||||
|
@ -17,7 +17,8 @@ export async function createNotification (
|
|||||||
objectClass: forDoc._class,
|
objectClass: forDoc._class,
|
||||||
objectSpace: forDoc.space,
|
objectSpace: forDoc.space,
|
||||||
user: data.user,
|
user: data.user,
|
||||||
isPinned: false
|
isPinned: false,
|
||||||
|
hidden: false
|
||||||
})
|
})
|
||||||
docNotifyContext = await client.findOne(notification.class.DocNotifyContext, { _id: docNotifyContextId })
|
docNotifyContext = await client.findOne(notification.class.DocNotifyContext, { _id: docNotifyContextId })
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user