Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/notification-services-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add `updateNotificationPreferences` method and `NotificationServicesController:updateNotificationPreferences` action, which save a change to notification preferences in Authenticated User Storage ([#10821](https://github.com/MetaMask/core/pull/10821))
- Takes a `NotificationPreferencesUpdate`: any sections, and any fields within a section. Fields left out keep their stored value; arrays and maps are replaced whole.
- Merges over a fresh read of the stored preferences, runs updates one at a time, and returns the saved preferences.
- Rejects updates that turn a marketing channel on without marketing consent with `MarketingConsentRequiredError`. Marketing channels already on in storage don't block other updates.
- Throws if notification preferences have not been set up yet, instead of creating them.
- Add `MarketingConsentRequiredError` and its `code`, `MARKETING_CONSENT_REQUIRED_ERROR_CODE` ([#10821](https://github.com/MetaMask/core/pull/10821))

### Changed

- **BREAKING:** `NotificationServicesControllerMessenger` requires `AnalyticsController:getState` and `AuthenticatedUserStorageService:invalidateQueries` in its allowed actions ([#10821](https://github.com/MetaMask/core/pull/10821))
- **BREAKING:** When notification preferences are created for the first time, both marketing channels (push, and in-app feature announcements) now follow `AnalyticsController` marketing consent; the `hasMarketingConsent` and `productAnnouncementEnabled` options of `createOnChainTriggers` and `enableMetamaskNotifications` are ignored. Users without marketing consent no longer start with feature announcements on ([#10821](https://github.com/MetaMask/core/pull/10821))
- Bump `@metamask/profile-sync-controller` from `^34.0.0` to `^34.0.3` ([#10752](https://github.com/MetaMask/core/pull/10752), [#10756](https://github.com/MetaMask/core/pull/10756), [#10761](https://github.com/MetaMask/core/pull/10761))
- Bump `loglevel` from `^1.8.1` to `^1.9.2` ([#10724](https://github.com/MetaMask/core/pull/10724))
- Bump `firebase` from `^11.10.0` to `^12.19.0` ([#10600](https://github.com/MetaMask/core/pull/10600))
- Bump `@contentful/rich-text-html-renderer` from `^16.5.2` to `^16.6.10` ([#10712](https://github.com/MetaMask/core/pull/10712))
- Bump `@metamask/keyring-controller` from `^28.1.0` to `^28.2.0` ([#10851](https://github.com/MetaMask/core/pull/10851))

### Deprecated

- Deprecate the `isFeatureAnnouncementsEnabled` state property, the `setFeatureAnnouncementsEnabled` method and its `NotificationServicesController:setFeatureAnnouncementsEnabled` action, and the `hasMarketingConsent` and `productAnnouncementEnabled` options. Feature announcements follow marketing consent through the Authenticated User Storage `marketing.inAppNotificationsEnabled` preference ([#10821](https://github.com/MetaMask/core/pull/10821))

## [29.0.3]

### Changed
Expand Down
1 change: 1 addition & 0 deletions packages/notification-services-controller/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
},
"dependencies": {
"@contentful/rich-text-html-renderer": "^16.6.10",
"@metamask/analytics-controller": "^4.0.0",
"@metamask/authenticated-user-storage": "^4.1.0",
"@metamask/base-controller": "^10.0.0",
"@metamask/controller-utils": "^13.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export type NotificationServicesControllerCheckAccountsPresenceAction = {
*
* **Action** - used in the notification settings to enable/disable feature announcements.
*
* @deprecated Feature announcements follow marketing consent (the AUS
* `marketing.inAppNotificationsEnabled` preference). Nothing in this
* controller reads the flag this sets, and it will be removed.
*
* @param featureAnnouncementsEnabled - A boolean value indicating the desired enabled state of the feature announcements.
* @async
* @throws {Error} If fails to update
Expand All @@ -55,11 +59,13 @@ export type NotificationServicesControllerSetFeatureAnnouncementsEnabledAction =
* {@link AuthenticatedUserStorageService} has no stored preferences yet.
* Existing preferences are left as-is.
*
* When preferences are initialized, both marketing channels (push, and
* in-app feature announcements) follow `AnalyticsController` marketing
* consent.
*
* @param opts - optional options to mutate this functionality
* @param opts.hasMarketingConsent - The user's marketing-consent flag.
* Used only during initialization to seed marketing push notifications.
* @param opts.productAnnouncementEnabled - The user's product-announcement flag.
* Used only during initialization to seed marketing in-app notifications.
* @param opts.hasMarketingConsent - Deprecated and ignored.
* @param opts.productAnnouncementEnabled - Deprecated and ignored.
* @param opts.registerPushNotifications - Whether to attempt FCM/device push registration.
* @returns The updated or newly created user storage.
* @throws {Error} Throws an error if unauthenticated or from other operations.
Expand Down Expand Up @@ -217,6 +223,35 @@ export type NotificationServicesControllerSendPerpPlaceOrderNotificationAction =
handler: NotificationServicesController['sendPerpPlaceOrderNotification'];
};

/**
* Saves a change to the user's notification preferences in Authenticated
* User Storage. Sections and fields left out keep their stored value, so
* callers send only what they change.
*
* Marketing notifications require marketing consent, so an update that
* turns a marketing channel on while the user has not consented is
* rejected. Only the fields in the update are checked: a marketing channel
* already on in storage doesn't block updates to other preferences. Turning
* consent off turns marketing channels off on its own (see
* `MarketingConsentController`).
*
* Read preferences from `AuthenticatedUserStorageService:getNotificationPreferences`
* (e.g. through `@metamask/react-data-query`), whose cache keeps UIs up to
* date; write them through this method so the consent rule is enforced.
*
* @param update - The sections and fields to change.
* @returns The saved preferences.
* @throws {MarketingConsentRequiredError} If the update turns a marketing
* channel on without marketing consent.
* @throws If notification preferences have not been set up yet; they are
* created when notifications are first enabled.
*/
export type NotificationServicesControllerUpdateNotificationPreferencesAction =
{
type: `NotificationServicesController:updateNotificationPreferences`;
handler: NotificationServicesController['updateNotificationPreferences'];
};

/**
* Union of all NotificationServicesController action types.
*/
Expand All @@ -237,4 +272,5 @@ export type NotificationServicesControllerMethodActions =
| NotificationServicesControllerDeleteNotificationsByIdAction
| NotificationServicesControllerMarkMetamaskNotificationsAsReadAction
| NotificationServicesControllerUpdateMetamaskNotificationsListAction
| NotificationServicesControllerSendPerpPlaceOrderNotificationAction;
| NotificationServicesControllerSendPerpPlaceOrderNotificationAction
| NotificationServicesControllerUpdateNotificationPreferencesAction;
Loading
Loading