Skip to content

Commit

Permalink
Merge pull request #529 from LedgerHQ/feat/LIVE-2542-push-notif-analy…
Browse files Browse the repository at this point in the history
…tics

Push notifications analytics
  • Loading branch information
cgrellard-ledger authored Jul 26, 2022
2 parents 364c801 + 3bcabf2 commit 46da5ec
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { useMemo } from "react";
import React, { useMemo, useCallback } from "react";
import {
createStackNavigator,
TransitionPresets,
} from "@react-navigation/stack";
import { useTranslation } from "react-i18next";
import { useTheme } from "styled-components/native";
import { TouchableOpacity } from "react-native";
import { Box, Icons } from "@ledgerhq/native-ui";
import { useNavigation } from "@react-navigation/native";
import { ScreenName } from "../../const";
import BenchmarkQRStream from "../../screens/BenchmarkQRStream";
import DebugSwap from "../../screens/DebugSwap";
Expand Down Expand Up @@ -46,13 +49,27 @@ import OnboardingStepLanguage from "../../screens/Onboarding/steps/language";
import { GenerateMockAccountSelectScreen } from "../../screens/Settings/Debug/GenerateMockAccountsSelect";
import HiddenNftCollections from "../../screens/Settings/Accounts/HiddenNftCollections";
import DebugStoryly from "../../screens/DebugStoryly";
import { track } from "../../analytics";
import { useCurrentRouteName } from "../../helpers/routeHooks";

export default function SettingsNavigator() {
const { t } = useTranslation();
const { colors } = useTheme();
const stackNavConfig = useMemo(() => getStackNavigatorConfig(colors), [
colors,
]);

const navigation = useNavigation();
const currentRoute = useCurrentRouteName();

const goBackFromNotifications = useCallback(() => {
track("button_clicked", {
button: "Back Arrow",
screen: currentRoute,
});
navigation.goBack();
}, [navigation, currentRoute]);

return (
<Stack.Navigator screenOptions={stackNavConfig}>
<Stack.Screen
Expand Down Expand Up @@ -102,6 +119,13 @@ export default function SettingsNavigator() {
name={ScreenName.NotificationsSettings}
component={NotificationsSettings}
options={{
headerLeft: () => (
<Box ml={6}>
<TouchableOpacity onPress={goBackFromNotifications}>
<Icons.ArrowLeftMedium size={24} />
</TouchableOpacity>
</Box>
),
title: t("settings.notifications.title"),
}}
/>
Expand Down
40 changes: 36 additions & 4 deletions apps/ledger-live-mobile/src/logic/notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
import { notificationsSelector } from "../reducers/settings";
import { ScreenName, NavigatorName } from "../const";
import { setRatingsModalLocked } from "../actions/ratings";
import { track } from "../analytics";

export type EventTrigger = {
/** Name of the route that will trigger the push notification modal */
Expand Down Expand Up @@ -136,6 +137,10 @@ const useNotifications = () => {
}, [notificationsToken]);

const handlePushNotificationsPermission = useCallback(async () => {
track("button_clicked", {
button: "Go to system settings",
screen: pushNotificationsOldRoute,
});
if (Platform.OS === "android") {
Linking.openSettings();
} else {
Expand All @@ -148,7 +153,7 @@ const useNotifications = () => {
fcm.requestPermission();
}
}
}, []);
}, [pushNotificationsOldRoute]);

const setPushNotificationsModalOpenCallback = useCallback(
isModalOpen => {
Expand Down Expand Up @@ -362,16 +367,34 @@ const useNotifications = () => {
}, [pushNotificationsDataOfUser, updatePushNotificationsDataOfUserInStateAndStore]);

const modalAllowNotifications = useCallback(() => {
track("button_clicked", {
button: "Allow",
screen: pushNotificationsOldRoute,
drawer: "Notif",
});
setPushNotificationsModalOpenCallback(false);
navigation.navigate(NavigatorName.Settings, {
screen: ScreenName.NotificationsSettings
});
if (pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts) {
handleSetDateOfNextAllowedRequest(pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts);
handleSetDateOfNextAllowedRequest(
pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts,
);
}
}, [handleSetDateOfNextAllowedRequest, navigation, pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts, setPushNotificationsModalOpenCallback]);
}, [
pushNotificationsOldRoute,
handleSetDateOfNextAllowedRequest,
navigation,
pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts,
setPushNotificationsModalOpenCallback,
]);

const modalDelayLater = useCallback(() => {
track("button_clicked", {
button: "Maybe Later",
screen: pushNotificationsOldRoute,
drawer: "Notif",
});
setPushNotificationsModalOpenCallback(false);
if (pushNotificationsDataOfUser?.alreadyDelayedToLater) {
updatePushNotificationsDataOfUserInStateAndStore({
Expand All @@ -386,12 +409,21 @@ const useNotifications = () => {
},
);
}
}, [handleSetDateOfNextAllowedRequest, pushNotificationsDataOfUser, pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts, pushNotificationsFeature?.params?.conditions?.maybe_later_delay, setPushNotificationsModalOpenCallback, updatePushNotificationsDataOfUserInStateAndStore]);
}, [
pushNotificationsOldRoute,
handleSetDateOfNextAllowedRequest,
pushNotificationsDataOfUser,
pushNotificationsFeature?.params?.conditions?.default_delay_between_two_prompts,
pushNotificationsFeature?.params?.conditions?.maybe_later_delay,
setPushNotificationsModalOpenCallback,
updatePushNotificationsDataOfUserInStateAndStore,
]);

return {
initPushNotifications,
initPushNotificationsData,
cleanPushNotifications,
pushNotificationsOldRoute,
pushNotificationsModalType,
isPushNotificationsModalOpen,
getIsNotifEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ const ReadOnlyAccountRow = ({ navigation, currency, screen }: Props) => {
const onAccountPress = useCallback(() => {
track("account_clicked", { currency: name, screen });
navigation.navigate(NavigatorName.Portfolio, {
screen: ScreenName.Account,
screen: NavigatorName.PortfolioAccounts,
params: {
currencyId: id,
currencyType: type,
screen: ScreenName.Account,
params: {
currencyId: id,
currencyType: type,
},
},
});
}, [name, screen, navigation, id, type]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { StyleSheet, SectionList, RefreshControl, View } from "react-native";
import { useAnnouncements } from "@ledgerhq/live-common/notifications/AnnouncementProvider/index";
import { groupAnnouncements } from "@ledgerhq/live-common/notifications/AnnouncementProvider/helpers";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from "react";
import React, { useEffect } from "react";
import { useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import {
Expand All @@ -15,6 +15,7 @@ import PromptNotifGenericLight from "../../images/illustration/Light/_PromptNoti
import PromptNotifMarketDark from "../../images/illustration/Dark/_PromptNotifMarket.png";
import PromptNotifMarketLight from "../../images/illustration/Light/_PromptNotifMarket.png";
import { notificationsSelector } from "../../reducers/settings";
import { TrackScreen } from "../../analytics";

const PushNotificationsModal = () => {
const { t } = useTranslation();
Expand All @@ -29,6 +30,7 @@ const PushNotificationsModal = () => {
getIsNotifEnabled,
listenForNotifications,
clearNotificationsListeners,
pushNotificationsOldRoute,
} = useNotifications();
const notificationsSettings = useSelector(notificationsSelector);

Expand Down Expand Up @@ -78,6 +80,16 @@ const PushNotificationsModal = () => {
isOpen={isPushNotificationsModalOpen}
noCloseButton
>
<TrackScreen
category="Notification Prompt"
name={
pushNotificationsModalType === "generic"
? "Notification Prompt 1 - Notif"
: "Notification Prompt 2 - Graph"
}
source={pushNotificationsOldRoute}
type={"drawer"}
/>
<Flex mb={4}>
<Flex alignItems={"center"}>
<NotifIllustration />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@ import { Platform } from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import { capitalize } from "lodash/fp";
import { Box, Switch, Text, Button, Icons, InfiniteLoader } from "@ledgerhq/native-ui";

import {
Box,
Switch,
Text,
Button,
Icons,
InfiniteLoader,
} from "@ledgerhq/native-ui";
import SettingsNavigationScrollView from "../SettingsNavigationScrollView";
import SettingsRow from "../../../components/SettingsRow";
import Track from "../../../analytics/Track";
import { TrackScreen } from "../../../analytics";

import { track, TrackScreen } from "../../../analytics";
import { notificationsSelector } from "../../../reducers/settings";
import { setNotifications } from "../../../actions/settings";
import { State } from "../../../reducers";
import useNotifications from "../../../logic/notifications";
import {
usePreviousRouteName,
useCurrentRouteName,
} from "../../../helpers/routeHooks";

type NotificationRowProps = {
disabled?: boolean;
Expand All @@ -31,19 +40,28 @@ function NotificationSettingsRow({

const { t } = useTranslation();

const capitalizedKey = capitalize(notificationKey);

const screen = useCurrentRouteName();

const onChange = useCallback(
(value: boolean) => {
dispatch(
setNotifications({
[notificationKey]: value,
}),
);
track("toggle_clicked", {
toggle: `Toggle_${
capitalizedKey === "Allowed" ? "Allow" : capitalizedKey
}`,
enabled: value,
screen,
});
},
[dispatch, notificationKey],
[capitalizedKey, dispatch, notificationKey, screen],
);

const capitalizedKey = capitalize(notificationKey);

return (
<SettingsRow
event={`${capitalizedKey}Row`}
Expand Down Expand Up @@ -71,7 +89,10 @@ function NotificationSettingsRow({
function NotificationsSettings() {
const { t } = useTranslation();
const notifications = useSelector(notificationsSelector);
const { getIsNotifEnabled, handlePushNotificationsPermission } = useNotifications();
const {
getIsNotifEnabled,
handlePushNotificationsPermission,
} = useNotifications();
const [isNotifPermissionEnabled, setIsNotifPermissionEnabled] = useState();

const refreshNotifPermission = useCallback(() => {
Expand All @@ -85,27 +106,36 @@ function NotificationsSettings() {

return () => {
clearInterval(interval);
}
};
}, [refreshNotifPermission]);

const disableSubSettings = !notifications.allowed;

const platformData = useMemo(() => {
return Platform.OS === "ios" ? {
osName: "iOS",
ctaTransKey: "turnOnNotif",
ctaIcon: Icons.NotificationsMedium,
} : {
osName: "Android",
ctaTransKey: "goToSettings",
ctaIcon: Icons.SettingsMedium,
};
}, []);
const platformData = useMemo(
() =>
Platform.OS === "ios"
? {
osName: "iOS",
ctaTransKey: "turnOnNotif",
ctaIcon: Icons.NotificationsMedium,
}
: {
osName: "Android",
ctaTransKey: "goToSettings",
ctaIcon: Icons.SettingsMedium,
},
[],
);

return (
<SettingsNavigationScrollView>
<TrackScreen category="Settings" name="Notifications" />
{isNotifPermissionEnabled === null || isNotifPermissionEnabled === undefined ? (
<TrackScreen
category="Settings"
name="Notifications"
source={usePreviousRouteName()}
/>
{isNotifPermissionEnabled === null ||
isNotifPermissionEnabled === undefined ? (
<InfiniteLoader />
) : (
<Box>
Expand All @@ -120,7 +150,9 @@ function NotificationsSettings() {
{t(`settings.notifications.disabledNotifications.title`)}
</Text>
<Text color={"neutral.c70"} variant={"bodyLineHeight"}>
{t(`settings.notifications.disabledNotifications.desc`, { platform: platformData.osName })}
{t(`settings.notifications.disabledNotifications.desc`, {
platform: platformData.osName,
})}
</Text>
<Button
type={"main"}
Expand All @@ -129,12 +161,17 @@ function NotificationsSettings() {
Icon={platformData.ctaIcon}
iconPosition={"left"}
>
{t(`settings.notifications.disabledNotifications.${platformData.ctaTransKey}`)}
{t(
`settings.notifications.disabledNotifications.${platformData.ctaTransKey}`,
)}
</Button>
</Box>
) : null}
<Box opacity={isNotifPermissionEnabled ? 1 : 0.2}>
<NotificationSettingsRow notificationKey={"allowed"} disabled={!isNotifPermissionEnabled} />
<NotificationSettingsRow
notificationKey={"allowed"}
disabled={!isNotifPermissionEnabled}
/>
</Box>
<Box opacity={notifications.allowed ? 1 : 0.2}>
<NotificationSettingsRow
Expand Down
Loading

0 comments on commit 46da5ec

Please sign in to comment.