From a2fac160efe956186075634234c7bb78e00b7c7d Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Thu, 28 Apr 2022 11:20:16 -0400 Subject: [PATCH] set badge count on cancel notifications (#6189) --- app/actions/local/channel.ts | 3 +++ app/database/subscription/unreads.ts | 40 +++++++++++++++++++++++++--- app/init/push_notifications.ts | 16 +++++------ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/app/actions/local/channel.ts b/app/actions/local/channel.ts index f20867968..c7b4ffbde 100644 --- a/app/actions/local/channel.ts +++ b/app/actions/local/channel.ts @@ -9,6 +9,7 @@ import {CHANNELS_CATEGORY, DMS_CATEGORY} from '@constants/categories'; import DatabaseManager from '@database/manager'; import {getTeammateNameDisplaySetting} from '@helpers/api/preference'; import {extractChannelDisplayName} from '@helpers/database'; +import PushNotifications from '@init/push_notifications'; import {prepareDeleteChannel, prepareMyChannelsForTeam, queryAllMyChannel, getMyChannel, getChannelById, queryUsersOnChannel} from '@queries/servers/channel'; import {queryPreferencesByCategoryAndName} from '@queries/servers/preference'; import {prepareCommonSystemValues, PrepareCommonSystemValuesArgs, getCommonSystemValues, getCurrentTeamId, setCurrentChannelId, getCurrentUserId} from '@queries/servers/system'; @@ -89,6 +90,8 @@ export async function switchToChannel(serverUrl: string, channelId: string, team await operator.batchRecords(models); } + PushNotifications.cancelChannelNotifications(channelId); + if (!EphemeralStore.theme) { // When opening the app from a push notification the theme may not be set in the EphemeralStore // causing the goToScreen to use the Appearance theme instead and that causes the screen background color to potentially diff --git a/app/database/subscription/unreads.ts b/app/database/subscription/unreads.ts index 0c0a897df..af0709817 100644 --- a/app/database/subscription/unreads.ts +++ b/app/database/subscription/unreads.ts @@ -7,9 +7,9 @@ import {combineLatestWith} from 'rxjs/operators'; import {MM_TABLES} from '@constants/database'; import DatabaseManager from '@database/manager'; -import {observeThreadMentionCount} from '@queries/servers/thread'; - -import type MyChannelModel from '@typings/database/models/servers/my_channel'; +import {queryMyTeams} from '@queries/servers/team'; +import {getIsCRTEnabled, observeThreadMentionCount, queryThreads} from '@queries/servers/thread'; +import MyChannelModel from '@typings/database/models/servers/my_channel'; const {SERVER: {CHANNEL, MY_CHANNEL}} = MM_TABLES; @@ -72,3 +72,37 @@ export const subscribeUnreadAndMentionsByServer = (serverUrl: string, observer: return subscription; }; + +export const getTotalMentionsForServer = async (serverUrl: string) => { + const server = DatabaseManager.serverDatabases[serverUrl]; + let count = 0; + if (server?.database) { + const {database} = server; + const myChannels = await database.get(MY_CHANNEL). + query( + Q.on(CHANNEL, Q.where('delete_at', Q.eq(0))), + Q.where('mentions_count', Q.gt(0)), + ).fetch(); + + for (const mc of myChannels) { + count += mc.mentionsCount; + } + + const isCRTEnabled = await getIsCRTEnabled(database); + if (isCRTEnabled) { + let includeDmGm = true; + const myTeamIds = await queryMyTeams(database).fetchIds(); + for await (const teamId of myTeamIds) { + const threads = await queryThreads(database, teamId, false, includeDmGm).extend( + Q.where('unread_mentions', Q.gt(0)), + ).fetch(); + includeDmGm = false; + for (const t of threads) { + count += t.unreadMentions; + } + } + } + } + + return count; +}; diff --git a/app/init/push_notifications.ts b/app/init/push_notifications.ts index a6dc8aa9d..8a64e4bbb 100644 --- a/app/init/push_notifications.ts +++ b/app/init/push_notifications.ts @@ -19,6 +19,7 @@ import {markChannelAsViewed} from '@actions/local/channel'; import {backgroundNotification, openNotification} from '@actions/remote/notifications'; import {Device, Events, Navigation, Screens} from '@constants'; import DatabaseManager from '@database/manager'; +import {getTotalMentionsForServer} from '@database/subscription/unreads'; import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n'; import NativeNotifications from '@notifications'; import {queryServerName} from '@queries/app/servers'; @@ -68,26 +69,24 @@ class PushNotifications { NativeNotifications.removeDeliveredNotifications(channelId); } else { const ids: string[] = []; - let badgeCount = notifications.length; for (const notification of notifications) { if (notification.channel_id === channelId) { ids.push(notification.identifier); - badgeCount--; } } - // TODO: Set the badgeCount with databases mention count aggregate ?? - // or should we use the badge count from the icon? - if (ids.length) { NativeNotifications.removeDeliveredNotifications(ids); } - if (Platform.OS === 'ios') { + const serversUrl = Object.keys(DatabaseManager.serverDatabases); + const mentionPromises = serversUrl.map((url) => getTotalMentionsForServer(url)); + Promise.all(mentionPromises).then((result) => { + let badgeCount = result.reduce((acc, count) => (acc + count), 0); badgeCount = badgeCount <= 0 ? 0 : badgeCount; Notifications.ios.setBadgeCount(badgeCount); - } + }); } }; @@ -121,6 +120,7 @@ class PushNotifications { if (serverUrl && payload?.channel_id) { markChannelAsViewed(serverUrl, payload?.channel_id, false); + this.cancelChannelNotifications(payload.channel_id); } }; @@ -254,7 +254,7 @@ class PushNotifications { prefix = Device.PUSH_NOTIFY_ANDROID_REACT_NATIVE; } - storeDeviceToken(`${prefix}:${deviceToken}`); + storeDeviceToken(`${prefix}-v2:${deviceToken}`); // Store the device token in the default database this.requestNotificationReplyPermissions();