diff --git a/app/app.tsx b/app/app.tsx
index fa0198a9dd..dccd4424d3 100644
--- a/app/app.tsx
+++ b/app/app.tsx
@@ -32,6 +32,7 @@ import { ErrorScreen } from "./screens/error-screen"
import { PersistentStateProvider } from "./store/persistent-state"
import { detectDefaultLocale } from "./utils/locale-detector"
import "./utils/logs"
+import { ActionModals, ActionsProvider } from "./components/actions"
// FIXME should we only load the currently used local?
// this would help to make the app load faster
@@ -52,19 +53,22 @@ export const App = () => (
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/actions/index.tsx b/app/components/actions/index.tsx
new file mode 100644
index 0000000000..1baa94a705
--- /dev/null
+++ b/app/components/actions/index.tsx
@@ -0,0 +1,55 @@
+import React from "react"
+import { SetLightningAddressModal } from "../set-lightning-address-modal"
+import { SetDefaultAccountModal } from "../set-default-account-modal"
+import { UpgradeAccountModal } from "../upgrade-account-modal"
+
+export const Action = {
+ SetLnAddress: "SetLnAddress",
+ SetDefaultAccount: "SetDefaultAccount",
+ UpgradeAccount: "UpgradeAccount",
+} as const
+
+export type Action = (typeof Action)[keyof typeof Action]
+
+type ActionsContextType = {
+ setActiveAction: (action: Action | null) => void
+ activeAction: Action | null
+}
+
+const ActionsContext = React.createContext({
+ setActiveAction: () => {},
+ activeAction: null,
+})
+
+export const ActionsProvider: React.FC = ({ children }) => {
+ const [activeAction, setActiveAction] = React.useState(null)
+
+ return (
+
+ {children}
+
+ )
+}
+
+export const ActionModals: React.FC = () => {
+ const { activeAction, setActiveAction } = useActionsContext()
+ const closeModal = () => setActiveAction(null)
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export const useActionsContext = () => React.useContext(ActionsContext)
diff --git a/app/components/push-notification/push-notification.tsx b/app/components/push-notification/push-notification.tsx
index 9ecbdf2efc..19a167e7d3 100644
--- a/app/components/push-notification/push-notification.tsx
+++ b/app/components/push-notification/push-notification.tsx
@@ -2,62 +2,26 @@ import React, { useEffect } from "react"
import { useApolloClient } from "@apollo/client"
import { useIsAuthed } from "@app/graphql/is-authed-context"
-import { useAuthenticationContext } from "@app/navigation/navigation-container-wrapper"
import { addDeviceToken, hasNotificationPermission } from "@app/utils/notifications"
import messaging, { FirebaseMessagingTypes } from "@react-native-firebase/messaging"
-import { useLinkTo } from "@react-navigation/native"
-
-import { useNotifications } from "../notifications"
-
-const circlesNotificationTypes = [
- "InnerCircleGrew",
- "OuterCircleGrew",
- "InnerCircleThisMonthThresholdReached",
- "InnerCircleAllTimeThresholdReached",
- "OuterCircleThisMonthThresholdReached",
- "OuterCircleAllTimeThresholdReached",
- "LeaderboardThisMonthThresholdReached",
- "LeaderboardAllTimeThresholdReached",
-]
+import { Linking } from "react-native"
export const PushNotificationComponent = (): JSX.Element => {
const client = useApolloClient()
const isAuthed = useIsAuthed()
- const { notifyCard } = useNotifications()
-
- const linkTo = useLinkTo()
- const isAppLocked = useAuthenticationContext().isAppLocked
useEffect(() => {
- if (isAppLocked) {
- return
- }
-
- const showNotification = (remoteMessage: FirebaseMessagingTypes.RemoteMessage) => {
+ const followNotificationLink = (
+ remoteMessage: FirebaseMessagingTypes.RemoteMessage,
+ ) => {
try {
- if (remoteMessage.notification?.body) {
- // TODO: add notifee library to show local notifications
- console.log(
- remoteMessage.notification.title || "",
- remoteMessage.notification.body,
- )
- }
-
- const notificationType = remoteMessage.data?.notificationType ?? ""
- if (
- typeof notificationType === "string" &&
- circlesNotificationTypes.includes(notificationType)
- ) {
- linkTo("/people/circles")
- }
-
const linkToScreen = remoteMessage.data?.linkTo ?? ""
if (
typeof linkToScreen === "string" &&
linkToScreen &&
linkToScreen.startsWith("/")
) {
- linkTo(linkToScreen)
+ Linking.openURL("blink:" + linkToScreen)
}
// linkTo throws an error if the link is invalid
} catch (error) {
@@ -68,19 +32,13 @@ export const PushNotificationComponent = (): JSX.Element => {
// When the application is running, but in the background.
const unsubscribeBackground = messaging().onNotificationOpenedApp(
(remoteMessage: FirebaseMessagingTypes.RemoteMessage) => {
- showNotification(remoteMessage)
+ followNotificationLink(remoteMessage)
},
)
const unsubscribeInApp = messaging().onMessage(async (remoteMessage) => {
- notifyCard({
- text: remoteMessage.notification?.body ?? "",
- title: remoteMessage.notification?.title ?? "",
- action: async () => {
- showNotification(remoteMessage)
- },
- icon: "bell",
- })
+ console.log("A new FCM message arrived!", remoteMessage)
+ // TODO: add notifee library to show local notifications
})
// When the application is opened from a quit state.
@@ -88,7 +46,7 @@ export const PushNotificationComponent = (): JSX.Element => {
.getInitialNotification()
.then((remoteMessage: FirebaseMessagingTypes.RemoteMessage | null) => {
if (remoteMessage) {
- showNotification(remoteMessage)
+ followNotificationLink(remoteMessage)
}
})
@@ -96,7 +54,7 @@ export const PushNotificationComponent = (): JSX.Element => {
unsubscribeInApp()
unsubscribeBackground()
}
- }, [linkTo, isAppLocked, notifyCard])
+ }, [])
useEffect(() => {
;(async () => {
diff --git a/app/components/set-default-account-modal/set-default-account-modal.tsx b/app/components/set-default-account-modal/set-default-account-modal.tsx
index e1bbb09ebf..6ad00fc259 100644
--- a/app/components/set-default-account-modal/set-default-account-modal.tsx
+++ b/app/components/set-default-account-modal/set-default-account-modal.tsx
@@ -12,10 +12,7 @@ import {
} from "@app/graphql/generated"
import { getBtcWallet, getUsdWallet } from "@app/graphql/wallets-utils"
import { useI18nContext } from "@app/i18n/i18n-react"
-import { RootStackParamList } from "@app/navigation/stack-param-lists"
import crashlytics from "@react-native-firebase/crashlytics"
-import { useNavigation } from "@react-navigation/native"
-import { StackNavigationProp } from "@react-navigation/stack"
import { makeStyles, Text, useTheme } from "@rneui/themed"
import { GaloyCurrencyBubble } from "../atomic/galoy-currency-bubble"
@@ -51,7 +48,6 @@ export const SetDefaultAccountModal = ({
const [usdLoading, setUsdLoading] = React.useState(false)
const [accountUpdateDefaultWallet] = useAccountUpdateDefaultWalletIdMutation()
- const navigation = useNavigation>()
const { data } = useSetDefaultAccountModalQuery({
fetchPolicy: "cache-only",
@@ -83,7 +79,6 @@ export const SetDefaultAccountModal = ({
setHasPromptedSetDefaultAccount(client)
toggleModal()
- navigation.navigate("receiveBitcoin")
}
const onPressBtcAccount = async () => {
@@ -107,7 +102,6 @@ export const SetDefaultAccountModal = ({
setHasPromptedSetDefaultAccount(client)
toggleModal()
- navigation.navigate("receiveBitcoin")
}
return (
diff --git a/app/navigation/navigation-container-wrapper.tsx b/app/navigation/navigation-container-wrapper.tsx
index 69fa1f1749..6ac81268f9 100644
--- a/app/navigation/navigation-container-wrapper.tsx
+++ b/app/navigation/navigation-container-wrapper.tsx
@@ -1,5 +1,5 @@
import * as React from "react"
-import { useRef } from "react"
+import { useEffect, useRef } from "react"
import { Linking } from "react-native"
import RNBootSplash from "react-native-bootsplash"
@@ -16,6 +16,7 @@ import { useTheme } from "@rneui/themed"
import { useIsAuthed } from "../graphql/is-authed-context"
import { RootStackParamList } from "./stack-param-lists"
+import { Action, useActionsContext } from "@app/components/actions"
export type AuthenticationContextType = {
isAppLocked: boolean
@@ -32,31 +33,48 @@ export const AuthenticationContextProvider = AuthenticationContext.Provider
export const useAuthenticationContext = () => React.useContext(AuthenticationContext)
+const processLinkForAction = (url: string): Action | null => {
+ // grab action query param
+ const urlObj = new URL(url)
+ const action = urlObj.searchParams.get("action")
+
+ switch ((action || "").toLocaleLowerCase()) {
+ case "set-ln-address":
+ return Action.SetLnAddress
+ case "set-default-account":
+ return Action.SetDefaultAccount
+ case "upgrade-account":
+ return Action.UpgradeAccount
+ }
+ return null
+}
+
export const NavigationContainerWrapper: React.FC = ({
children,
}) => {
const isAuthed = useIsAuthed()
+ const [isAppLocked, setIsAppLocked] = React.useState(true)
+ const [urlAfterUnlockAndAuth, setUrlAfterUnlockAndAuth] = React.useState(
+ null,
+ )
+ const { setActiveAction } = useActionsContext()
- const processLink = useRef<((url: string) => void) | null>(() => {
- return undefined
- })
+ useEffect(() => {
+ if (isAuthed && !isAppLocked && urlAfterUnlockAndAuth) {
+ Linking.openURL(urlAfterUnlockAndAuth)
+ setUrlAfterUnlockAndAuth(null)
+ }
+ }, [isAuthed, isAppLocked, urlAfterUnlockAndAuth])
const setAppUnlocked = React.useMemo(
() => async () => {
setIsAppLocked(false)
- const url = await Linking.getInitialURL()
-
- if (url && isAuthed && processLink.current) {
- return processLink.current(url)
- }
},
- [isAuthed],
+ [],
)
const setAppLocked = React.useMemo(() => () => setIsAppLocked(true), [])
- const [isAppLocked, setIsAppLocked] = React.useState(true)
-
const routeName = useRef("Initial")
const {
@@ -101,6 +119,18 @@ export const NavigationContainerWrapper: React.FC = ({
receiveBitcoin: "receive",
conversionDetails: "convert",
scanningQRCode: "scan-qr",
+ chatbot: "chat",
+ totpRegistrationInitiate: "settings/2fa",
+ currency: "settings/display-currency",
+ defaultWallet: "settings/default-account",
+ language: "settings/language",
+ theme: "settings/theme",
+ security: "settings/security",
+ accountScreen: "settings/account",
+ transactionLimitsScreen: "settings/tx-limits",
+ notificationSettingsScreen: "settings/notifications",
+ emailRegistrationInitiate: "settings/email",
+ settings: "settings",
transactionDetail: {
path: "transaction/:txid",
},
@@ -109,17 +139,20 @@ export const NavigationContainerWrapper: React.FC = ({
},
getInitialURL: async () => {
const url = await Linking.getInitialURL()
- console.log("getInitialURL", url)
- if (Boolean(url) && isAuthed && !isAppLocked) {
- return url
- }
+ setUrlAfterUnlockAndAuth(url)
return null
},
subscribe: (listener) => {
- processLink.current = listener
const onReceiveURL = ({ url }: { url: string }) => {
- console.log("onReceiveURL", url)
- listener(url)
+ if (!isAppLocked && isAuthed) {
+ const maybeAction = processLinkForAction(url)
+ if (maybeAction) {
+ setActiveAction(maybeAction)
+ }
+ listener(url)
+ } else {
+ setUrlAfterUnlockAndAuth(url)
+ }
}
// Listen to incoming links from deep linking
const subscription = Linking.addEventListener("url", onReceiveURL)
@@ -127,7 +160,6 @@ export const NavigationContainerWrapper: React.FC = ({
return () => {
// Clean up the event listeners
subscription.remove()
- processLink.current = null
}
},
}
diff --git a/app/screens/home-screen/home-screen.tsx b/app/screens/home-screen/home-screen.tsx
index 884808894f..820f944c66 100644
--- a/app/screens/home-screen/home-screen.tsx
+++ b/app/screens/home-screen/home-screen.tsx
@@ -414,7 +414,10 @@ export const HomeScreen: React.FC = () => {
{
+ toggleSetDefaultAccountModal()
+ navigation.navigate("receiveBitcoin")
+ }}
/>