Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: mobile push notifications #13006

Draft
wants to merge 36 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b6471fc
feat: use reusable utilities to create push notification messages
Prithpal-Sooriya Jan 14, 2025
fbea0e4
feat: add metametric events for push notifications
Prithpal-Sooriya Jan 14, 2025
f2b8cac
refactor: notification services and manager cleanup
Prithpal-Sooriya Jan 14, 2025
764e051
feat: use preview build
Prithpal-Sooriya Jan 14, 2025
d8525a4
refactor: remove UI push initialisation hook
Prithpal-Sooriya Jan 14, 2025
a9e2ad6
fix: fix type issues
Prithpal-Sooriya Jan 14, 2025
350367b
refactor: clean up example env files
Prithpal-Sooriya Jan 15, 2025
8663d91
feat: bump preview package
Prithpal-Sooriya Jan 20, 2025
e6395ca
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 20, 2025
d6bbb57
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 20, 2025
4883a35
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 22, 2025
07b0886
feat: add push click effect subscriptions
Prithpal-Sooriya Jan 22, 2025
5ab1c22
chore: add TODO comment to remove duplicate code that is available in…
Prithpal-Sooriya Jan 22, 2025
9501f3d
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 23, 2025
4047bb1
feat: add guard for push subscription effect
Prithpal-Sooriya Jan 23, 2025
01624eb
feat: add logic to turn off notifications if push notifications are n…
Prithpal-Sooriya Jan 23, 2025
944b69e
feat: more cleanup work
Prithpal-Sooriya Jan 23, 2025
3f5d8b0
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 23, 2025
6579cfa
feat: update preview package
Prithpal-Sooriya Jan 24, 2025
8157803
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 24, 2025
c37f677
refactor: clean up FCM service
Prithpal-Sooriya Jan 24, 2025
541a754
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 24, 2025
7b6934f
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 27, 2025
108075a
fix: update notifee data prop error
Prithpal-Sooriya Jan 28, 2025
39417e6
fix: fix engine not loading bug
Prithpal-Sooriya Jan 28, 2025
172ffd2
feat: add background notifications headless check
Prithpal-Sooriya Jan 28, 2025
dc4e8d5
feat: remove app config change
Prithpal-Sooriya Jan 28, 2025
b35578f
refactor: FCM cleanup
Prithpal-Sooriya Jan 28, 2025
b4fa86a
feat: notification service - add id when displaying a notification
Prithpal-Sooriya Jan 28, 2025
e5dacc3
feat: add android default notification icon and color
Prithpal-Sooriya Jan 29, 2025
dec9945
fix: add android tag to prevent duplicate notifications
Prithpal-Sooriya Jan 29, 2025
c728ad5
refactor: FCM service cleanup
Prithpal-Sooriya Jan 29, 2025
f87de99
Merge branch 'main' of github.com:MetaMask/metamask-mobile into feat/…
Prithpal-Sooriya Jan 29, 2025
84ec599
revert: remove app.config.js changes
Prithpal-Sooriya Jan 29, 2025
d2236f7
feat: remove background message subscriptions
Prithpal-Sooriya Jan 29, 2025
a5cf8a7
ci: update notification codeowners
Prithpal-Sooriya Jan 29, 2025
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
14 changes: 1 addition & 13 deletions .android.env.example
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
export MM_FOX_CODE="EXAMPLE_FOX_CODE"
export MM_BRANCH_KEY_TEST=
export MM_BRANCH_KEY_LIVE=
export METAMASK_BUILD_TYPE=
# Firebase
export FCM_CONFIG_API_KEY=
export FCM_CONFIG_AUTH_DOMAIN=
export FCM_CONFIG_PROJECT_ID=
export FCM_CONFIG_STORAGE_BUCKET=
export FCM_CONFIG_MESSAGING_SENDER_ID=
export FCM_CONFIG_APP_ID=
export GOOGLE_SERVICES_B64_ANDROID=
#Notifications Feature Announcements
export FEATURES_ANNOUNCEMENTS_ACCESS_TOKEN=
export FEATURES_ANNOUNCEMENTS_SPACE_ID=

export METAMASK_BUILD_TYPE=
8 changes: 2 additions & 6 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,8 @@ app/components/UI/Swaps @MetaMask/swaps-engineers
# Notifications Team
app/components/Views/Notifications @MetaMask/notifications
app/components/Views/Settings/NotificationsSettings @MetaMask/notifications
app/components/UI/Notifications @MetaMask/notifications
app/reducers/notification @MetaMask/notifications
app/actions/notification @MetaMask/notifications
app/selectors/notification @MetaMask/notifications
app/util/notifications @MetaMask/notifications
app/store/util/notifications @MetaMask/notifications
**/notifications/** @MetaMask/notifications
**/notification/** @MetaMask/notifications

# Identity Team
app/actions/identity @MetaMask/identity
Expand Down
11 changes: 0 additions & 11 deletions .ios.env.example
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
MM_FOX_CODE = EXAMPLE_FOX_CODE
MM_BRANCH_KEY_TEST =
MM_BRANCH_KEY_LIVE =
# Firebase
FCM_CONFIG_API_KEY=
FCM_CONFIG_AUTH_DOMAIN=
FCM_CONFIG_PROJECT_ID=
FCM_CONFIG_STORAGE_BUCKET=
FCM_CONFIG_MESSAGING_SENDER_ID=
FCM_CONFIG_APP_ID=
GOOGLE_SERVICES_B64_IOS=
#Notifications Feature Announcements
FEATURES_ANNOUNCEMENTS_ACCESS_TOKEN=
FEATURES_ANNOUNCEMENTS_SPACE_ID=
6 changes: 0 additions & 6 deletions .js.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,6 @@ export PORTFOLIO_VIEW="true"
# Temporary mechanism to enable security alerts API prior to release.
export MM_SECURITY_ALERTS_API_ENABLED="true"
# Firebase
export FCM_CONFIG_API_KEY=""
export FCM_CONFIG_AUTH_DOMAIN=""
export FCM_CONFIG_PROJECT_ID=""
export FCM_CONFIG_STORAGE_BUCKET=""
export FCM_CONFIG_MESSAGING_SENDER_ID=""
export FCM_CONFIG_APP_ID=""
export GOOGLE_SERVICES_B64_ANDROID=""
export GOOGLE_SERVICES_B64_IOS=""
# Notifications Feature Announcements
Expand Down
7 changes: 6 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description"
android:value="io.metamask"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_color"
android:resource="@color/lightgray"/>
android:resource="@color/notificationColor"/>
<meta-data android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/notificationColor"
tools:replace="android:resource"/>
<meta-data android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_notification_small"/>

<provider
android:name="androidx.core.content.FileProvider"
Expand Down
3 changes: 2 additions & 1 deletion android/app/src/main/res/values-night/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<color name="navBar">#000000</color>
<color name="lightgray">#EBEBED</color>
<color name="alertTextColor">#000000</color>
<color name="alertBackground">#FFFFFF</color>
<color name="alertBackground">#FFFFFF</color>
<color name="notificationColor">#2A4174</color>
</resources>
3 changes: 2 additions & 1 deletion android/app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<color name="navBar">#000000</color>
<color name="lightgray">#EBEBED</color>
<color name="alertTextColor">#000000</color>
<color name="alertBackground">#FFFFFF</color>
<color name="alertBackground">#FFFFFF</color>
<color name="notificationColor">#2A4174</color>
</resources>
3 changes: 2 additions & 1 deletion android/app/src/qa/res/values-night/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<color name="navBar">#000000</color>
<color name="lightgray">#EBEBED</color>
<color name="alertTextColor">#000000</color>
<color name="alertBackground">#FFFFFF</color>
<color name="alertBackground">#FFFFFF</color>
<color name="notificationColor">#2A4174</color>
</resources>
3 changes: 2 additions & 1 deletion android/app/src/qa/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<color name="navBar">#000000</color>
<color name="lightgray">#EBEBED</color>
<color name="alertTextColor">#000000</color>
<color name="alertBackground">#FFFFFF</color>
<color name="alertBackground">#FFFFFF</color>
<color name="notificationColor">#2A4174</color>
</resources>
2 changes: 1 addition & 1 deletion app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@
}
]
]
};
};

Check warning on line 23 in app.config.js

View workflow job for this annotation

GitHub Actions / scripts (lint)

Newline required at end of file but not found
46 changes: 1 addition & 45 deletions app/actions/notification/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ import { getErrorMessage } from '@metamask/utils';

import { notificationsErrors } from '../constants';
import Engine from '../../../core/Engine';
import {
Notification,
mmStorage,
getAllUUIDs,
} from '../../../util/notifications';
import type { UserStorage } from '@metamask/notification-services-controller/notification-services';
import { Notification, mmStorage } from '../../../util/notifications';

export type MarkAsReadNotificationsParam = Pick<
Notification,
Expand Down Expand Up @@ -155,42 +150,3 @@ export const performDeleteStorage = async (): Promise<string | undefined> => {
return getErrorMessage(error);
}
};

export const enablePushNotifications = async (
userStorage: UserStorage,
fcmToken?: string,
) => {
try {
const uuids = getAllUUIDs(userStorage);
await Engine.context.NotificationServicesPushController.enablePushNotifications(
uuids,
fcmToken,
);
} catch (error) {
return getErrorMessage(error);
}
};

export const disablePushNotifications = async (userStorage: UserStorage) => {
try {
const uuids = getAllUUIDs(userStorage);
await Engine.context.NotificationServicesPushController.disablePushNotifications(
uuids,
);
} catch (error) {
return getErrorMessage(error);
}
};

export const updateTriggerPushNotifications = async (
userStorage: UserStorage,
) => {
try {
const uuids = getAllUUIDs(userStorage);
await Engine.context.NotificationServicesPushController.updateTriggerPushNotifications(
uuids,
);
} catch (error) {
return getErrorMessage(error);
}
};
5 changes: 3 additions & 2 deletions app/components/Nav/Main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ import {
} from '../../../selectors/networkInfos';
import { selectShowIncomingTransactionNetworks } from '../../../selectors/preferencesController';

import useNotificationHandler from '../../../util/notifications/hooks';
import {
DEPRECATED_NETWORKS,
NETWORKS_CHAIN_ID,
Expand All @@ -85,6 +84,7 @@ import isNetworkUiRedesignEnabled from '../../../util/networks/isNetworkUiRedesi
import { useConnectionHandler } from '../../../util/navigation/useConnectionHandler';
import { AssetPollingProvider } from '../../hooks/AssetPolling/AssetPollingProvider';
import { getGlobalEthQuery } from '../../../util/networks/global-network';
import { useRegisterPushNotificationsEffect } from '../../../util/notifications/hooks/useRegisterPushNotificationsEffect';

const Stack = createStackNavigator();

Expand Down Expand Up @@ -114,8 +114,9 @@ const Main = (props) => {

const { connectionChangeHandler } = useConnectionHandler(props.navigation);

useRegisterPushNotificationsEffect();

const removeNotVisibleNotifications = props.removeNotVisibleNotifications;
useNotificationHandler(props.navigation);
useEnableAutomaticSecurityChecks();
useMinimumVersions();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const BasicFunctionalityModal = ({ route }: Props) => {
selectIsMetamaskNotificationsEnabled,
);

// TODO - should we add notification logic when basic functionality is toggled?
const { enableNotifications } = useEnableNotifications();

const enableNotificationsFromModal = useCallback(async () => {
Expand Down
2 changes: 0 additions & 2 deletions app/components/UI/Notification/BaseNotification/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ const getTitle = (status, { nonce, amount, assetType }) => {
return strings('notifications.cancelled_title');
case 'error':
return strings('notifications.error_title');
case 'eth_received':
return strings('notifications.eth_received_title');
}
};

Expand Down
1 change: 0 additions & 1 deletion app/components/Views/Notifications/OptIn/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ const OptIn = () => {
});
} else {
const { permission } = await NotificationsService.getAllPermissions();

if (permission !== 'authorized') {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function useToggleNotifications({
setUiNotificationStatus,
}: Props) {
const { trackEvent, createEventBuilder } = useMetrics();
// Check logic here
const toggleNotificationsEnabled = useCallback(async () => {
if (!basicFunctionalityEnabled) {
navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
Expand Down
8 changes: 8 additions & 0 deletions app/core/Analytics/MetaMetrics.events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ enum EVENT_NAME {
NOTIFICATIONS_MARKED_ALL_AS_READ = 'Notifications Marked All as Read',
NOTIFICATION_DETAIL_CLICKED = 'Notification Detail Clicked',
NOTIFICATION_STORAGE_KEY_DELETED = 'Notification Storage Key Deleted',
PUSH_NOTIFICATIONS_RECEIVED = 'Push Notification Received',
PUSH_NOTIFICATIONS_CLICKED = 'Push Notification Clicked',

// Smart transactions
SMART_TRANSACTION_OPT_IN = 'Smart Transaction Opt In',
Expand Down Expand Up @@ -880,6 +882,12 @@ const events = {
NOTIFICATION_STORAGE_KEY_DELETED: generateOpt(
EVENT_NAME.NOTIFICATION_STORAGE_KEY_DELETED,
),
PUSH_NOTIFICATIONS_RECEIVED: generateOpt(
EVENT_NAME.PUSH_NOTIFICATIONS_RECEIVED,
),
PUSH_NOTIFICATIONS_CLICKED: generateOpt(
EVENT_NAME.PUSH_NOTIFICATIONS_CLICKED,
),
Comment on lines +885 to +890
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm removing these events for mobile, they are not feasible.

Context:
Mobile background and killed push notifications currently will not run headless JS for us to then intercept and send events for receive and clicks

// Simulations
INCOMPLETE_ASSET_DISPLAYED: generateOpt(
EVENT_NAME.INCOMPLETE_ASSET_DISPLAYED,
Expand Down
Loading
Loading