Fix hidden notifications (#4436)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-01-25 10:00:30 +04:00 committed by GitHub
parent 8865bdd516
commit b15f94f885
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 13 deletions

View File

@ -44,7 +44,6 @@
import Filter from '../Filter.svelte' import Filter from '../Filter.svelte'
import { getDisplayInboxNotifications, resolveLocation } from '../../utils' import { getDisplayInboxNotifications, resolveLocation } from '../../utils'
import { InboxNotificationsFilter } from '../../types' import { InboxNotificationsFilter } from '../../types'
import { onDestroy } from 'svelte'
export let visibleNav: boolean = true export let visibleNav: boolean = true
export let navFloat: boolean = false export let navFloat: boolean = false
@ -91,7 +90,9 @@
viewlets = res viewlets = res
}) })
$: displayNotifications = getDisplayInboxNotifications($notificationsByContextStore, filter) $: getDisplayInboxNotifications($notificationsByContextStore, filter).then((res) => {
displayNotifications = res
})
$: displayContextsIds = new Set(displayNotifications.map(({ docNotifyContext }) => docNotifyContext)) $: displayContextsIds = new Set(displayNotifications.map(({ docNotifyContext }) => docNotifyContext))
$: filteredNotifications = filterNotifications(selectedTabId, displayNotifications, $notifyContextsStore) $: filteredNotifications = filterNotifications(selectedTabId, displayNotifications, $notifyContextsStore)

View File

@ -76,14 +76,14 @@
key.preventDefault() key.preventDefault()
key.stopPropagation() key.stopPropagation()
const context = $notifyContextsStore.find(({ _id }) => _id === displayData[listSelection][0]) const context = $notifyContextsStore.find(({ _id }) => _id === displayData[listSelection]?.[0])
deleteContextNotifications(context) deleteContextNotifications(context)
} }
if (key.code === 'Enter') { if (key.code === 'Enter') {
key.preventDefault() key.preventDefault()
key.stopPropagation() key.stopPropagation()
const context = $notifyContextsStore.find(({ _id }) => _id === displayData[listSelection][0]) const context = $notifyContextsStore.find(({ _id }) => _id === displayData[listSelection]?.[0])
dispatch('click', { context }) dispatch('click', { context })
} }
} }

View File

@ -44,6 +44,7 @@ import { activityMessagesComparator, combineActivityMessages } from '@hcengineer
import { type InboxNotificationsFilter } from './types' import { type InboxNotificationsFilter } from './types'
import { InboxNotificationsClientImpl } from './inboxNotificationsClient' import { InboxNotificationsClientImpl } from './inboxNotificationsClient'
import { checkIsObjectRemoved } from '@hcengineering/view-resources'
/** /**
* @public * @public
@ -355,11 +356,12 @@ async function generateLocation (
} }
} }
export function getDisplayInboxNotifications ( export async function getDisplayInboxNotifications (
notificationsByContext: Map<Ref<DocNotifyContext>, InboxNotification[]>, notificationsByContext: Map<Ref<DocNotifyContext>, InboxNotification[]>,
filter: InboxNotificationsFilter = 'all', filter: InboxNotificationsFilter = 'all',
objectClass?: Ref<Class<Doc>> objectClass?: Ref<Class<Doc>>
): DisplayInboxNotification[] { ): Promise<DisplayInboxNotification[]> {
const client = getClient()
const filteredNotifications = Array.from(notificationsByContext.values()) const filteredNotifications = Array.from(notificationsByContext.values())
.flat() .flat()
.filter(({ isViewed }) => { .filter(({ isViewed }) => {
@ -375,6 +377,10 @@ export function getDisplayInboxNotifications (
} }
}) })
const viewletsHideIfRemoved = client
.getModel()
.findAllSync(activity.class.DocUpdateMessageViewlet, { hideIfRemoved: true })
const activityNotifications = filteredNotifications.filter( const activityNotifications = filteredNotifications.filter(
(n): n is WithLookup<ActivityInboxNotification> => n._class === notification.class.ActivityInboxNotification (n): n is WithLookup<ActivityInboxNotification> => n._class === notification.class.ActivityInboxNotification
) )
@ -397,9 +403,31 @@ export function getDisplayInboxNotifications (
return (message as DocUpdateMessage).objectClass === objectClass return (message as DocUpdateMessage).objectClass === objectClass
}) })
.sort(activityMessagesComparator)
const combinedMessages = combineActivityMessages(messages, SortingOrder.Descending) for (const [index, message] of messages.entries()) {
if (message._class !== activity.class.DocUpdateMessage) {
continue
}
const docUpdateMessage = message as DocUpdateMessage
const hideIfRemoved = viewletsHideIfRemoved.some(
(viewlet) => viewlet.action === docUpdateMessage.action && viewlet.objectClass === docUpdateMessage.objectClass
)
if (!hideIfRemoved) {
continue
}
const isRemoved = await checkIsObjectRemoved(client, docUpdateMessage.objectId, docUpdateMessage.objectClass)
if (isRemoved) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete messages[index]
}
}
const combinedMessages = combineActivityMessages(messages.sort(activityMessagesComparator), SortingOrder.Descending)
for (const message of combinedMessages) { for (const message of combinedMessages) {
if (message._class === activity.class.DocUpdateMessage) { if (message._class === activity.class.DocUpdateMessage) {
@ -439,7 +467,7 @@ export function getDisplayInboxNotifications (
export async function hasInboxNotifications ( export async function hasInboxNotifications (
notificationsByContext: Map<Ref<DocNotifyContext>, InboxNotification[]> notificationsByContext: Map<Ref<DocNotifyContext>, InboxNotification[]>
): Promise<boolean> { ): Promise<boolean> {
const displayNotifications = getDisplayInboxNotifications(notificationsByContext) const displayNotifications = await getDisplayInboxNotifications(notificationsByContext)
return displayNotifications.some(({ isViewed }) => !isViewed) return displayNotifications.some(({ isViewed }) => !isViewed)
} }

View File

@ -44,7 +44,8 @@ import core, {
type TxCreateDoc, type TxCreateDoc,
type TxUpdateDoc, type TxUpdateDoc,
type TxMixin, type TxMixin,
ClassifierKind ClassifierKind,
type TypeAny
} from '@hcengineering/core' } from '@hcengineering/core'
import type { Asset, IntlString } from '@hcengineering/platform' import type { Asset, IntlString } from '@hcengineering/platform'
import { getResource, translate } from '@hcengineering/platform' import { getResource, translate } from '@hcengineering/platform'
@ -172,6 +173,7 @@ export async function getAttributePresenter (
const hierarchy = client.getHierarchy() const hierarchy = client.getHierarchy()
const attribute = hierarchy.getAttribute(_class, key) const attribute = hierarchy.getAttribute(_class, key)
const presenterClass = getAttributePresenterClass(hierarchy, attribute) const presenterClass = getAttributePresenterClass(hierarchy, attribute)
const isCollectionAttr = presenterClass.category === 'collection' const isCollectionAttr = presenterClass.category === 'collection'
const mixin = isCollectionAttr ? view.mixin.CollectionPresenter : actualMixinClass const mixin = isCollectionAttr ? view.mixin.CollectionPresenter : actualMixinClass
@ -181,7 +183,15 @@ export async function getAttributePresenter (
if (presenterMixin?.presenter === undefined && mixinClass != null && mixin === mixinClass) { if (presenterMixin?.presenter === undefined && mixinClass != null && mixin === mixinClass) {
presenterMixin = hierarchy.classHierarchyMixin(presenterClass.attrClass, view.mixin.AttributePresenter) presenterMixin = hierarchy.classHierarchyMixin(presenterClass.attrClass, view.mixin.AttributePresenter)
} }
if (presenterMixin?.presenter === undefined) {
let presenter: AnySvelteComponent
if (presenterMixin?.presenter !== undefined) {
presenter = await getResource(presenterMixin.presenter)
} else if (presenterClass.attrClass === core.class.TypeAny) {
const typeAny = attribute.type as TypeAny
presenter = await getResource(typeAny.presenter)
} else {
throw new Error('attribute presenter not found for ' + JSON.stringify(preserveKey)) throw new Error('attribute presenter not found for ' + JSON.stringify(preserveKey))
} }
@ -191,7 +201,6 @@ export async function getAttributePresenter (
: attribute.type._class === core.class.ArrOf : attribute.type._class === core.class.ArrOf
? resultKey + '.length' ? resultKey + '.length'
: resultKey : resultKey
const presenter = await getResource(presenterMixin.presenter)
return { return {
key: preserveKey.key, key: preserveKey.key,
@ -201,7 +210,7 @@ export async function getAttributePresenter (
presenter, presenter,
props: preserveKey.props, props: preserveKey.props,
displayProps: preserveKey.displayProps, displayProps: preserveKey.displayProps,
icon: presenterMixin.icon, icon: presenterMixin?.icon,
attribute, attribute,
collectionAttr: isCollectionAttr, collectionAttr: isCollectionAttr,
isLookup: false isLookup: false