From 6142d2d86e2e64f16440ec2055cac3747ee8df74 Mon Sep 17 00:00:00 2001 From: Kristina Date: Tue, 1 Jul 2025 09:57:53 +0400 Subject: [PATCH] Add desktop pushes for new inbox (#9414) * Add desktop pushes for new inbox Signed-off-by: Kristina Fefelova * fix auto-merge Signed-off-by: Kristina Fefelova --------- Signed-off-by: Kristina Fefelova --- communication | 2 +- desktop/package.json | 1 + desktop/src/main/start.ts | 2 +- desktop/src/ui/index.ts | 4 +- desktop/src/ui/notifications.ts | 73 +++++++++++++++---- desktop/src/ui/preload.ts | 4 +- desktop/src/ui/types.ts | 4 +- .../CreateCardFromMessagePopup.svelte | 12 ++- 8 files changed, 78 insertions(+), 24 deletions(-) diff --git a/communication b/communication index 74ae6fd435..de20669d03 160000 --- a/communication +++ b/communication @@ -1 +1 @@ -Subproject commit 74ae6fd435311b225fa4241965d48657d6e87dae +Subproject commit de20669d03856d5ae400e843f5eb2be5ee0f2624 diff --git a/desktop/package.json b/desktop/package.json index 3dd75aee22..766b42017b 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -258,6 +258,7 @@ "electron-updater": "^6.3.4", "livekit-client": "^2.13.3", "@hcengineering/server-backup": "^0.6.0", + "@hcengineering/communication-types": "^0.1.0", "ws": "^8.18.2" }, "productName": "Huly Desktop", diff --git a/desktop/src/main/start.ts b/desktop/src/main/start.ts index d9ea7cd2e2..b70284c197 100644 --- a/desktop/src/main/start.ts +++ b/desktop/src/main/start.ts @@ -267,7 +267,7 @@ ipcMain.on('send-notification', (event, notificationParams: NotificationParams) notification.on('click', () => { mainWindow?.show() - mainWindow?.webContents.send('handle-notification-navigation') + mainWindow?.webContents.send('handle-notification-navigation', notificationParams.application) }) notification.show() diff --git a/desktop/src/ui/index.ts b/desktop/src/ui/index.ts index 25befc08ea..134ac42d07 100644 --- a/desktop/src/ui/index.ts +++ b/desktop/src/ui/index.ts @@ -66,11 +66,11 @@ window.addEventListener('DOMContentLoaded', () => { navigate(parseLocation(urlObject)) }) - ipcMain.handleNotificationNavigation(() => { + ipcMain.handleNotificationNavigation((application) => { // For now navigate only to Inbox const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin const location = getCurrentResolvedLocation() - const urlString = `${frontUrl}/${workbenchId}/${location.path[1]}/${notificationId}` + const urlString = `${frontUrl}/${workbenchId}/${location.path[1]}/${application ?? notificationId}` const urlObject = new URL(urlString) navigate(parseLocation(urlObject)) }) diff --git a/desktop/src/ui/notifications.ts b/desktop/src/ui/notifications.ts index d32ef6cf80..4f2fd2b6de 100644 --- a/desktop/src/ui/notifications.ts +++ b/desktop/src/ui/notifications.ts @@ -1,13 +1,21 @@ -import { getPersonByPersonId, formatName } from '@hcengineering/contact' -import { Ref, TxOperations } from '@hcengineering/core' -import notification, { DocNotifyContext, CommonInboxNotification, ActivityInboxNotification, InboxNotification } from '@hcengineering/notification' -import { IntlString, addEventListener, translate } from '@hcengineering/platform' +import { formatName, getPersonByPersonId } from '@hcengineering/contact' +import { Ref, SortingOrder, TxOperations } from '@hcengineering/core' +import notification, { + notificationId, + ActivityInboxNotification, + CommonInboxNotification, + DocNotifyContext, + InboxNotification +} from '@hcengineering/notification' +import { addEventListener, getMetadata, IntlString, translate } from '@hcengineering/platform' import { createNotificationsQuery, getClient } from '@hcengineering/presentation' import { location } from '@hcengineering/ui' import workbench, { workbenchId } from '@hcengineering/workbench' import desktopPreferences, { defaultNotificationPreference } from '@hcengineering/desktop-preferences' import { activePreferences } from '@hcengineering/desktop-preferences-resources' -import { InboxNotificationsClientImpl, getDisplayInboxData } from '@hcengineering/notification-resources' +import { getDisplayInboxData, InboxNotificationsClientImpl } from '@hcengineering/notification-resources' +import { inboxId } from '@hcengineering/inbox' +import communication from '@hcengineering/communication' import { IPCMainExposed } from './types' @@ -123,17 +131,49 @@ export function configureNotifications (): void { const inboxClient = InboxNotificationsClientImpl.getClient() const notificationsQuery = createNotificationsQuery(true) - notificationsQuery.query({ read: false, limit: 1000 }, res => { - newUnreadNotifications = res.getResult().length + const isCommunicationEnabled = getMetadata(communication.metadata.Enabled) ?? false - if (preferences.showUnreadCounter) { - electronAPI.setBadge(prevUnViewdNotificationsCount + newUnreadNotifications) - } + if (isCommunicationEnabled) { + notificationsQuery.query({ read: false, limit: 1000 }, res => { + newUnreadNotifications = res.getResult().length - if (preferences.bounceAppIcon) { - electronAPI.dockBounce() - } - }) + if (preferences.showUnreadCounter) { + electronAPI.setBadge(prevUnViewdNotificationsCount + newUnreadNotifications) + } + + if (preferences.bounceAppIcon) { + electronAPI.dockBounce() + } + }) + } + + function startNotificationQuery (): void { + if (!isCommunicationEnabled) return + notificationsQuery.query({ + read: false, + limit: 1, + strict: true, + order: SortingOrder.Descending, + created: { + greaterOrEqual: new Date() + } + }, (res) => { + if (!preferences.showNotifications) return + const notification = res.getResult()[0] + if (notification !== undefined) { + electronAPI.sendNotification({ + silent: !preferences.playSound, + application: inboxId, + title: notification.content.title, + body: `${notification.content.senderName}: ${notification.content.shortText}` + }) + } + }) + } + + if (preferences.showNotifications) { + startNotificationQuery() + } async function handleNotifications (notificationsByContext: Map, InboxNotification[]>): Promise { const inboxData = await getDisplayInboxData(notificationsByContext) @@ -174,6 +214,7 @@ export function configureNotifications (): void { electronAPI.sendNotification({ silent: !preferences.playSound, + application: notificationId, ...notificationData }) } @@ -195,6 +236,10 @@ export function configureNotifications (): void { if (!preferences.showUnreadCounter && newPreferences.showUnreadCounter) { electronAPI.setBadge(prevUnViewdNotificationsCount + newUnreadNotifications) } + + if (newPreferences.showNotifications && !preferences.showNotifications) { + startNotificationQuery() + } preferences = newPreferences }) }) diff --git a/desktop/src/ui/preload.ts b/desktop/src/ui/preload.ts index c406608311..540e33914a 100644 --- a/desktop/src/ui/preload.ts +++ b/desktop/src/ui/preload.ts @@ -121,8 +121,8 @@ const expose: IPCMainExposed = { }, handleNotificationNavigation: (callback) => { - ipcRenderer.on('handle-notification-navigation', (event) => { - callback() + ipcRenderer.on('handle-notification-navigation', (event, application) => { + callback(application) }) }, diff --git a/desktop/src/ui/types.ts b/desktop/src/ui/types.ts index 6200336cfc..09b62180ff 100644 --- a/desktop/src/ui/types.ts +++ b/desktop/src/ui/types.ts @@ -1,4 +1,5 @@ import { ScreenSource } from '@hcengineering/love' +import { Plugin } from '@hcengineering/platform' /** * @public @@ -75,6 +76,7 @@ export interface NotificationParams { title: string body: string silent: boolean + application: Plugin } /** @@ -87,7 +89,7 @@ export interface IPCMainExposed { branding: () => Promise on: (event: string, op: (channel: any, args: any[]) => void) => void handleDeepLink: (callback: (url: string) => void) => void - handleNotificationNavigation: (callback: () => void) => void + handleNotificationNavigation: (callback: (application: Plugin) => void) => void handleUpdateDownloadProgress: (callback: (progress: number) => void) => void setFrontCookie: (host: string, name: string, value: string) => Promise dockBounce: () => void diff --git a/plugins/communication-resources/src/components/CreateCardFromMessagePopup.svelte b/plugins/communication-resources/src/components/CreateCardFromMessagePopup.svelte index 12f4477cad..3965c8b1b7 100644 --- a/plugins/communication-resources/src/components/CreateCardFromMessagePopup.svelte +++ b/plugins/communication-resources/src/components/CreateCardFromMessagePopup.svelte @@ -40,6 +40,7 @@ $: _message = $threadCreateMessageStore ?? message let title = getDefaultTitle(message) let selectedType: Ref | undefined + let inProgress = false function getDefaultTitle (message: Message): string { const markup = toMarkup(message.content) @@ -50,8 +51,13 @@ async function attachCard (): Promise { if (selectedType === undefined || title.trim() === '') return - await attachCardToMessage(_message, card, title, selectedType) - dispatch('close') + try { + inProgress = true + await attachCardToMessage(_message, card, title, selectedType) + dispatch('close') + } finally { + inProgress = false + } } function filterClasses (): [DropdownIntlItem, DropdownIntlItem[]][] { @@ -129,7 +135,7 @@ /> - {#if _message.thread != null} + {#if _message.thread != null && !inProgress}