diff --git a/web/helpers/apollo-cache/index.ts b/web/helpers/apollo-cache/index.ts index 588b41c79..fa8ad4b47 100644 --- a/web/helpers/apollo-cache/index.ts +++ b/web/helpers/apollo-cache/index.ts @@ -1,5 +1,8 @@ import { InMemoryCache, type InMemoryCacheConfig } from '@apollo/client/core/index.js'; -import { getNotifications } from '~/components/Notifications/graphql/notification.query'; +import { + getNotifications, + notificationsOverview, +} from '~/components/Notifications/graphql/notification.query'; import { NotificationType, type NotificationOverview } from '~/composables/gql/graphql'; import { NotificationType as NotificationCacheType } from '~/composables/gql/typename'; import { mergeAndDedup } from './merge'; @@ -109,6 +112,7 @@ const defaultCacheConfig: InMemoryCacheConfig = { }, archiveNotification: { /** + * Optimistically decrements unread total from overview & * Ensures newly archived notifications appear in the archive list without a page reload. * * When a notification is archived, we need to evict the cached archive list to force a refetch. @@ -119,11 +123,13 @@ const defaultCacheConfig: InMemoryCacheConfig = { * Note: This may cause temporary jitter with infinite scroll. * * This function: - * 1. Checks if the cache has an archive list. If not, this function is a no-op. - * 2. If the list has items, evicts just the archive list - * 3. If it is empty, evicts the entire notifications cache - * 4. Runs garbage collection to clean up orphaned references - * 5. Returns the original mutation result + * + * 1. Optimistically updates notification overview + * 2. Checks if the cache has an archive list. If not, this function is a no-op. + * 3. If the list has items, evicts just the archive list + * 4. If it is empty, evicts the entire notifications cache + * 5. Runs garbage collection to clean up orphaned references + * 6. Returns the original mutation result * * @param _ - Existing cache value (unused) * @param incoming - Result (i.e. the archived notification) from the server after archiving @@ -131,6 +137,13 @@ const defaultCacheConfig: InMemoryCacheConfig = { * @returns The incoming result to be cached */ merge(_, incoming, { cache }) { + cache.updateQuery({ query: notificationsOverview }, (data) => { + if (!data) return; + const update = structuredClone(data); + update.notifications.overview.unread.total--; + return update; + }); + const archiveQuery = cache.readQuery({ query: getNotifications, // @ts-expect-error the cache only uses the filter type; the limit & offset are superfluous. @@ -147,7 +160,6 @@ const defaultCacheConfig: InMemoryCacheConfig = { args: { filter: { type: NotificationType.Archive } }, }); } - cache.gc(); return incoming; },