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): add notifications opt-In screen #4837

Merged
merged 16 commits into from
Jan 31, 2025

Conversation

Jonathansoufer
Copy link
Contributor

@Jonathansoufer Jonathansoufer commented Jan 27, 2025

What it solves

This ticket implements the notifications onboarding screen, enabling users to toggle the feature ON or deciding to leave for later. Its important to mention though that after three rejected attempts the user will not be prompt again within a month.

P.S: Although out of the scope of this PR, it was implemented a reusable FloatingContainer which is intent to be used to group and stick elements on the bottom of the screen. It has also a awareness of keyboard elements on those cases when keyboard is necessary to proceed with an action.

Resolves #

How this PR fixes it

How to test it

Screenshots

Screenshot 2025-01-28 at 13 07 34

Checklist

  • I've tested the branch on mobile 📱
  • I've documented how it affects the analytics (if at all) 📊
  • I've written a unit/e2e test for it (if applicable) 🧑‍💻

@Jonathansoufer Jonathansoufer self-assigned this Jan 27, 2025
Copy link

github-actions bot commented Jan 27, 2025

Coverage (43%)
File% Stmts% Branch% Funcs% LinesUncovered Line #s
All files43.0440.2837.6943.5 
src0000 
   react-app-env.d.ts0000 
src/components/Alert10085.71100100 
   Alert.tsx10085.7110010057, 72
   index.ts0000 
src/components/Badge87.587.510087.5 
   Badge.tsx85.7187.510085.7149
   index.ts0000 
   theme.ts100100100100 
src/components/BlurredIdenticonBackground0000 
   BlurredIdenticonBackground.tsx000014–51
   index.tsx0000 
src/components/ChainsDisplay10084.61100100 
   ChainsDisplay.tsx10084.6110010015–18
   index.ts0000 
src/components/Container10075100100 
   Container.tsx1007510010032
   index.ts0000 
src/components/CopyButton25100025 
   CopyButton.tsx251000256–10
   index.ts0000 
src/components/DataRow100100100100 
   DataRow.tsx100100100100 
   index.ts0000 
src/components/Dropdown88.46607088 
   Dropdown.tsx81.256057.1481.2555, 63, 128
   index.ts0000 
   sheetComponents.tsx100100100100 
src/components/EthAddress10025100100 
   ETHAddress.tsx1002510010017
   index.ts0000 
src/components/Fiat100100100100 
   Fiat.tsx100100100100 
   index.ts0000 
src/components/FloatingContainer0000 
   FloatingContainer.tsx000016–49
   index.ts0000 
src/components/Identicon100100100100 
   Identicon.tsx100100100100 
   index.ts0000 
src/components/InnerShadow100100100100 
   InnerShadow.tsx100100100100 
   index.ts0000 
src/components/Logo100100100100 
   Logo.tsx100100100100 
   index.ts0000 
src/components/OptIn0000 
   OptIn.tsx000025–76
   index.ts0000 
src/components/SafeButton10066.66100100 
   SafeButton.tsx10066.6610010020
   index.ts0000 
src/components/SafeCard100100100100 
   SafeCard.tsx100100100100 
   index.ts0000 
src/components/SafeFontIcon87.585.7110087.5 
   SafeFontIcon.tsx87.585.7110087.528
   index.ts0000 
src/components/SafeListItem10070.58100100 
   SafeListItem.tsx10070.5810010074–88
   index.tsx0000 
src/components/SafeTab250026.31 
   SafeTab.tsx44.44100044.4413–25
   SafeTabBar.tsx9.09001018–38
   index.tsx0000 
   types.ts0000 
src/components/StatusBanners/PendingTransactions10050100100 
   PendingTransactions.tsx1005010010017
   index.tsx0000 
src/components/Tab0000 
   TabNameContext.tsx00003–10
src/components/Title66.660066.66 
   LargeHeaderTitle.tsx100100100100 
   NavBarTitle.tsx100100100100 
   SectionTitle.tsx000012
   index.ts0000 
src/components/TxInfo23.84.545023.8 
   TxInfo.tsx23.84.545023.845–96, 100
   index.tsx0000 
src/components/navigation100100100100 
   TabBarIcon.tsx100100100100 
   index.ts0000 
src/components/transactions-list/Card/AccountCard10075100100 
   AccountCard.tsx1007510010052
   index.ts0000 
src/components/transactions-list/Card/AssetsCard100100100100 
   AssetsCard.tsx100100100100 
   index.tsx0000 
src/components/transactions-list/Card/SignersCard100100100100 
   SignersCard.tsx100100100100 
   index.ts0000 
src/components/transactions-list/Card/TxBatchCard100100100100 
   TxBatchCard.tsx100100100100 
   index.tsx0000 
src/components/transactions-list/Card/TxConflictingCard010000 
   TxConflictingCard.tsx01000013–31
   index.tsx0000 
src/components/transactions-list/Card/TxContractInteractionCard100100100100 
   TxContractInteractionCard.tsx100100100100 
   index.tsx0000 
src/components/transactions-list/Card/TxCreationCard100100100100 
   TxCreationCard.tsx100100100100 
   index.ts0000 
src/components/transactions-list/Card/TxGroupedCard90.9757590.9 
   TxGroupedCard.tsx90.9757590.957
   index.tsx0000 
src/components/transactions-list/Card/TxRejectionCard100100100100 
   TxRejectionCard.tsx100100100100 
   index.tsx0000 
src/components/transactions-list/Card/TxSafeAppCard100100100100 
   TxSafeAppCard.tsx100100100100 
   index.tsx0000 
src/components/transactions-list/Card/TxSettingsCard10050100100 
   TxSettingsCard.tsx1005010010017
   index.tsx0000 
src/components/transactions-list/Card/TxSwapCard100100100100 
   TxSwapCard.tsx100100100100 
   index.tsx0000 
src/components/transactions-list/Card/TxTokenCard88.8880.5510088.88 
   TxTokenCard.tsx88.8880.5510088.8840, 70
   index.tsx0000 
src/config44.4483.33044.44 
   constants.ts10083.3310010015
   ethers.ts01000010–38
src/context0000 
   NotificationsContext.tsx000012–32
src/features/Assets0000 
   Assets.container.tsx000013–42
   index.tsx0000 
   styles.ts010010003
src/features/Assets/components/AccountItem91.6668.7510090.9 
   AccountItem.tsx91.6668.7510090.924
   index.ts0000 
src/features/Assets/components/AccountItem/hooks5002553.84 
   useEditAccountItem.ts5002553.8415–29
src/features/Assets/components/AssetsHeader0000 
   AssetsHeader.container.tsx0100006–13
   AssetsHeader.tsx000015
   index.tsx0000 
   styles.ts010010003
src/features/Assets/components/Balance0000 
   Balance.container.tsx01000014–36
   Balance.tsx000025–42
   ChainItems.tsx000017–28
   index.tsx0000 
src/features/Assets/components/Fallback10075100100 
   Fallback.tsx1007510010012
   index.ts0000 
src/features/Assets/components/MyAccounts88.2310066.66100 
   MyAccounts.container.tsx100100100100 
   MyAccountsFooter.tsx71.4210033.33100 
   index.ts0000 
src/features/Assets/components/MyAccounts/hooks43.7533.335044.82 
   useMyAccountsService.ts100100100100 
   useMyAccountsSortable.ts000012–38
src/features/Assets/components/NFTs10081.81100100 
   NFTItem.tsx100501001008
   NFTs.container.tsx10088.8810010026
   index.tsx0000 
src/features/Assets/components/Navbar0000 
   Navbar.tsx000020–80
   index.tsx0000 
src/features/Assets/components/NoFunds100100100100 
   EmptyToken.tsx100100100100 
   NoFunds.tsx100100100100 
   index.ts0000 
src/features/Assets/components/Tokens100100100100 
   Tokens.container.tsx100100100100 
   index.tsx0000 
src/features/Notifications010000 
   Notifications.container.tsx0100004–5
   index.tsx0000 
src/features/Onboarding100100100100 
   Onboarding.container.tsx100100100100 
   index.ts0000 
src/features/Onboarding/components/OnboardingCarousel95.6588.8888.8895.65 
   CarouselFeedback.tsx100100100100 
   CarouselItem.tsx1008010010026
   OnboardingCarousel.tsx88.8810083.3388.8824
   index.ts0000 
   items.tsx100100100100 
src/features/Onboarding/components/OnboardingHeader100100100100 
   OnboardingHeader.tsx100100100100 
   index.ts0000 
src/features/Onboarding/components/ParticlesLogo100100100100 
   ParticlesLogo.tsx100100100100 
   index.ts0000 
src/features/PendingTx0000 
   PendingTx.container.tsx0100006–8
   index.tsx0000 
   utils.tsx000021–133
src/features/PendingTx/components/PendingTxList0000 
   PendingTxList.container.tsx000033–63
   index.ts0000 
src/features/Settings0000 
   Settings.container.tsx00007–14
   Settings.tsx000020–137
   index.tsx0000 
src/features/Settings/components/AppSettings010000 
   AppSettings.container.tsx0100007–20
   AppSettings.tsx01000010–11
   index.ts0000 
src/features/Settings/components/IdenticonWithBadge10050100100 
   IdenticonWithBadge.tsx1005010010021–22
   index.ts0000 
src/features/Settings/components/Navbar0000 
   Navbar.tsx01000010–27
   SettingsButton.tsx0100006–15
   SettingsMenu.tsx000017–81
   index.ts0000 
src/features/Signers0000 
   Signers.container.tsx000011–27
   constants.ts010010003
   index.tsx0000 
src/features/Signers/components/SignersList0000 
   SignersList.tsx000020–61
   SignersListHeader.tsx000011
   SignersListItem.tsx000020–28
   index.ts0000 
src/features/Signers/components/SignersList/hooks010000 
   useSignersActions.ts0100005–32
src/features/Signers/hooks0000 
   useSignersGroupService.ts000010–36
src/features/TxHistory0000 
   TxHistory.container.tsx000011–37
   index.tsx0000 
   utils.tsx000018–58
src/features/TxHistory/components/TxHistoryList0000 
   TxHistoryList.tsx000018–33
   index.ts0000 
src/hooks0000 
   useNotifications.ts000023–61
src/hooks/useCopyAndDispatchToast100100100100 
   index.ts100100100100 
src/hooks/useInfiniteScroll75508073.33 
   index.ts0000 
   useInfiniteScroll.ts75508073.3330–35
src/hooks/usePendingTxs0000 
   index.ts000015–40
src/hooks/useSign805010080 
   index.ts0000 
   useSign.ts80501008034, 43, 55, 62, 67
src/hooks/useTransactionType91.6679.1610091.66 
   index.tsx91.6679.1610091.66116–124
src/navigation0000 
   useScrollableHeader.tsx000022–47
src/services/exceptions88.8810010088.88 
   utils.ts88.8810010088.8814
src/services/notifications0000 
   FCMService.ts000012–62
   NotificationService.ts000028–280
src/store48.333.8421.9550.46 
   activeSafeSlice.ts751005071.4219–22
   constants.ts64.280064.28321–334
   index.ts91.665010091.6648
   myAccountsSlice.ts83.33100508013
   notificationsSlice.ts39.130052.9418–36
   safesSlice.ts37.510012.538.4638–48, 57–58
   signersSlice.ts57.14100066.6613–15
   storage.ts7.14007.1412–67
   txHistorySlice.ts100100100100 
src/store/chains68.421004075 
   index.ts68.42100407517, 30–33
src/store/hooks100100100100 
   index.ts100100100100 
src/theme100100100100 
   navigation.ts100100100100 
   tamagui.config.ts100100100100 
   tokens.ts100100100100 
src/theme/helpers10081.81100100 
   utils.ts10081.8110010037, 41
src/theme/palettes100100100100 
   darkPalette.ts100100100100 
   lightPalette.ts100100100100 
src/theme/provider59.0927.776059.09 
   font.tsx90501009034
   safeTheme.tsx10037.510010019–34
   toastProvider.tsx000010–29
src/utils55.7631.558.4955.1 
   date.ts9666.6685.7110031, 35–39
   formatters.ts908010088.889
   gateway.ts100100100100 
   logger.ts000010–85
   transaction-guards.ts79.24606880.7651–57, 67, 99, 103, 117, 121
   transactions.tsx00004–29
src/utils/notifications010000 
   index.ts01000014–37

Comment on lines 6 to 15
jest.mock('@notifee/react-native', () => ({
AndroidImportance: {
NONE: 0,
MIN: 1,
LOW: 2,
DEFAULT: 3,
HIGH: 4,
},
}))

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess that we should move this to a global mock as you have it also in the Onboarding.container.test.tsx?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved.

@@ -17,6 +18,9 @@ const styles = StyleSheet.create({
signing: {
height: Math.abs(windowHeight * 0.3),
},
notifications: {
height: Math.abs(windowHeight * 0.32),
Copy link
Contributor

Choose a reason for hiding this comment

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

what's up with those magic contants here? For signing it is 0.3, here it is 0.32? Why are we multiplying with that? How does it look on a smaller/bigger device?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rolledback since the whole implementation wasn't supposed to be on onboarding flow.

@@ -55,6 +57,11 @@ const useNotifications = (): NotificationsProps => {
if (isAppNotificationEnabled) {
dispatch(toggleAppNotifications(false))
}

if (isOnboarding) {
router.navigate('/(tabs)')
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that we should be using replace instead of navigate. With navigate on devices with a hardware back button you would be able to go bath to the onboarding screeen. Where with replace you won't be.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch.

@katspaugh
Copy link
Member

@Jonathansoufer could you please adjust the PR title as per our guidelines?

@Jonathansoufer Jonathansoufer changed the title Feat/notifications onboarding UI Feat(Mobile): Implements notifications OptIn UI Jan 28, 2025
@Jonathansoufer Jonathansoufer changed the title Feat(Mobile): Implements notifications OptIn UI Feat(Mobile): add notifications opt-In screen Jan 29, 2025
Copy link
Contributor

@compojoom compojoom left a comment

Choose a reason for hiding this comment

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

What is the plan with this screen? When are we going to show it? Immediately after the user goes through the onboarding or at a later stage? After that if the user cancels are we prompting him every time?

Comment on lines +25 to +41
const { isAppNotificationEnabled, promptAttempts } = useNotifications()
const dispatch = useAppDispatch()
const router = useRouter()

/*
* If the user has not enabled notifications and has not been prompted to enable them,
* redirect to the opt-in screen
* */

const shouldShowOptIn = !isAppNotificationEnabled && !promptAttempts

useEffect(() => {
if (shouldShowOptIn) {
dispatch(updatePromptAttempts(1))
router.navigate('/notifications-opt-in')
}
}, [])
Copy link
Contributor

Choose a reason for hiding this comment

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

This is weird. The AssetsContainer should not care about notifications.
Get some inspiration from here:
https://docs.expo.dev/router/reference/authentication/
https://reactnavigation.org/docs/auth-flow
I think that the _layout.tsx should be the place where we decide what first screen we show to the user.

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 completely get your point here, but we don't wanna spam our users before the Onboarding, and if we use _layout, this takes place before anything. The other alternative would be calling it at HomeScreen, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

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

When the user clicks on "get started/continue" in the onboarding flow we should set a flag "onboarding_done": true. Next time the user starts we should not show the onboarding screens. So we will be deciding in the _layout.tsx which screen to show anyway.

@Jonathansoufer Jonathansoufer changed the title Feat(Mobile): add notifications opt-In screen feat(Mobile): add notifications opt-In screen Jan 31, 2025
Copy link
Contributor

@compojoom compojoom left a comment

Choose a reason for hiding this comment

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

Jonathan and I, agreed to merge this PR as is, but create a follow up Ticket that would move the logic of the first screen to the _layout or to a better place.

@Jonathansoufer Jonathansoufer merged commit 70f4db2 into dev Jan 31, 2025
6 checks passed
@Jonathansoufer Jonathansoufer deleted the feat/notifications-onboarding-ui branch January 31, 2025 11:13
@github-actions github-actions bot locked and limited conversation to collaborators Jan 31, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants