Skip to content

Commit

Permalink
Merge pull request #507 from LedgerHQ/feat/LIVE-2536-llm-notification…
Browse files Browse the repository at this point in the history
…s-prompts

LLM notifications prompts
  • Loading branch information
LFBarreto authored Jul 29, 2022
2 parents 1a64f6a + 671a3fd commit b7a4dcf
Show file tree
Hide file tree
Showing 39 changed files with 1,850 additions and 128 deletions.
6 changes: 6 additions & 0 deletions .changeset/three-pugs-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"live-mobile": minor
"@ledgerhq/live-common": minor
---

Push notifications support added to ledger live mobile, new 'notifications' section added to the settings to enable or disable them, new modal added to ask the user if he wants to allow the notifications
32 changes: 32 additions & 0 deletions apps/ledger-live-mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ PODS:
- ReactCommon/turbomodule/core (= 0.68.2)
- Firebase/CoreOnly (8.15.0):
- FirebaseCore (= 8.15.0)
- Firebase/Messaging (8.15.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 8.15.0)
- Firebase/RemoteConfig (8.15.0):
- Firebase/CoreOnly
- FirebaseRemoteConfig (~> 8.15.0)
Expand All @@ -52,6 +55,15 @@ PODS:
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/UserDefaults (~> 7.7)
- PromisesObjC (< 3.0, >= 1.2)
- FirebaseMessaging (8.15.0):
- FirebaseCore (~> 8.0)
- FirebaseInstallations (~> 8.0)
- GoogleDataTransport (~> 9.1)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Reachability (~> 7.7)
- GoogleUtilities/UserDefaults (~> 7.7)
- nanopb (~> 2.30908.0)
- FirebaseRemoteConfig (8.15.0):
- FirebaseABTesting (~> 8.0)
- FirebaseCore (~> 8.0)
Expand Down Expand Up @@ -125,11 +137,21 @@ PODS:
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/AppDelegateSwizzler (7.7.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (7.7.0):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.7.0):
- GoogleUtilities/Environment
- GoogleUtilities/Network (7.7.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.7.0)"
- GoogleUtilities/Reachability (7.7.0):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.7.0):
- GoogleUtilities/Logger
- hermes-engine (0.11.0)
Expand Down Expand Up @@ -514,6 +536,10 @@ PODS:
- RNFBApp (14.9.3):
- Firebase/CoreOnly (= 8.15.0)
- React-Core
- RNFBMessaging (14.11.1):
- Firebase/Messaging (= 8.15.0)
- React-Core
- RNFBApp
- RNFBRemoteConfig (14.9.3):
- Firebase/RemoteConfig (= 8.15.0)
- React-Core
Expand Down Expand Up @@ -680,6 +706,7 @@ DEPENDENCIES:
- "RNCMaskedView (from `../../../node_modules/.pnpm/@react-native-masked-view+masked-view@0.2.6_zqxy7fpkavjkgz5xll7ed4r6rq/node_modules/@react-native-masked-view/masked-view`)"
- "RNFastImage (from `../../../node_modules/.pnpm/react-native-fast-image@8.5.11_zqxy7fpkavjkgz5xll7ed4r6rq/node_modules/react-native-fast-image`)"
- "RNFBApp (from `../../../node_modules/.pnpm/@react-native-firebase+app@14.9.3_zqxy7fpkavjkgz5xll7ed4r6rq/node_modules/@react-native-firebase/app`)"
- "RNFBMessaging (from `../../../node_modules/.pnpm/@react-native-firebase+messaging@14.11.1_ljhxmmg6zhnbalfqtji2e6aebm/node_modules/@react-native-firebase/messaging`)"
- "RNFBRemoteConfig (from `../../../node_modules/.pnpm/@react-native-firebase+remote-config@14.9.3_ljhxmmg6zhnbalfqtji2e6aebm/node_modules/@react-native-firebase/remote-config`)"
- "RNGestureHandler (from `../../../node_modules/.pnpm/react-native-gesture-handler@2.5.0_mk7ksnag22facomrynqrp7v6gy/node_modules/react-native-gesture-handler`)"
- "RNKeychain (from `../../../node_modules/.pnpm/react-native-keychain@7.0.0/node_modules/react-native-keychain`)"
Expand All @@ -705,6 +732,7 @@ SPEC REPOS:
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseInstallations
- FirebaseMessaging
- FirebaseRemoteConfig
- Flipper
- Flipper-Boost-iOSX
Expand Down Expand Up @@ -861,6 +889,8 @@ EXTERNAL SOURCES:
:path: "../../../node_modules/.pnpm/react-native-fast-image@8.5.11_zqxy7fpkavjkgz5xll7ed4r6rq/node_modules/react-native-fast-image"
RNFBApp:
:path: "../../../node_modules/.pnpm/@react-native-firebase+app@14.9.3_zqxy7fpkavjkgz5xll7ed4r6rq/node_modules/@react-native-firebase/app"
RNFBMessaging:
:path: "../../../node_modules/.pnpm/@react-native-firebase+messaging@14.11.1_ljhxmmg6zhnbalfqtji2e6aebm/node_modules/@react-native-firebase/messaging"
RNFBRemoteConfig:
:path: "../../../node_modules/.pnpm/@react-native-firebase+remote-config@14.9.3_ljhxmmg6zhnbalfqtji2e6aebm/node_modules/@react-native-firebase/remote-config"
RNGestureHandler:
Expand Down Expand Up @@ -909,6 +939,7 @@ SPEC CHECKSUMS:
FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1
FirebaseCoreDiagnostics: 92e07a649aeb66352b319d43bdd2ee3942af84cb
FirebaseInstallations: 40bd9054049b2eae9a2c38ef1c3dd213df3605cd
FirebaseMessaging: 5e5118a2383b3531e730d974680954c679ca0a13
FirebaseRemoteConfig: 2d6e2cfdb49af79535c8af8a80a4a5009038ec2b
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Expand Down Expand Up @@ -983,6 +1014,7 @@ SPEC CHECKSUMS:
RNCMaskedView: c298b644a10c0c142055b3ae24d83879ecb13ccd
RNFastImage: 1f2cab428712a4baaf78d6169eaec7f622556dd7
RNFBApp: b6276fc67748c7174275cace56776f0228ae58b2
RNFBMessaging: 3e2682ea5e15fe86da24d16d16019395a881f33c
RNFBRemoteConfig: e2ab6deecf08a4f7d41274425163ddfdc6ae268a
RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50
RNKeychain: f75b8c8b2f17d3b2aa1f25b4a0ac5b83d947ff8f
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
5 changes: 5 additions & 0 deletions apps/ledger-live-mobile/ios/ledgerlivemobile/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@
<string>HMAlphaMono-Medium.otf</string>
<string>Inter-Medium.otf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<array>
<string>applinks:r354.adj.st</string>
</array>
<key>aps-environment</key>
<string>development</string>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.ledger.live</string>
Expand Down
1 change: 1 addition & 0 deletions apps/ledger-live-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/netinfo": "^6.0.1",
"@react-native-firebase/app": "^14.3.1",
"@react-native-firebase/messaging": "^14.5.1",
"@react-native-firebase/remote-config": "^14.3.1",
"@react-native-masked-view/masked-view": "^0.2.6",
"@react-navigation/bottom-tabs": "^6.0.9",
Expand Down
41 changes: 41 additions & 0 deletions apps/ledger-live-mobile/src/actions/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// @flow

import type { EventTrigger, DataOfUser } from "../logic/notifications";

export const setNotificationsModalOpen = (
isPushNotificationsModalOpen: boolean,
) => ({
type: "NOTIFICATIONS_SET_MODAL_OPEN",
isPushNotificationsModalOpen,
});

export const setNotificationsModalLocked = (
isPushNotificationsModalLocked: boolean,
) => ({
type: "NOTIFICATIONS_SET_MODAL_LOCKED",
isPushNotificationsModalLocked,
});

export const setNotificationsModalType = (notificationsModalType: string) => ({
type: "NOTIFICATIONS_SET_MODAL_TYPE",
notificationsModalType,
});

export const setNotificationsCurrentRouteName = (
currentRouteName?: string,
) => ({
type: "NOTIFICATIONS_SET_CURRENT_ROUTE_NAME",
currentRouteName,
});

export const setNotificationsEventTriggered = (
eventTriggered?: EventTrigger,
) => ({
type: "NOTIFICATIONS_SET_EVENT_TRIGGERED",
eventTriggered,
});

export const setNotificationsDataOfUser = (dataOfUser?: DataOfUser) => ({
type: "NOTIFICATIONS_SET_DATA_OF_USER",
dataOfUser,
});
5 changes: 5 additions & 0 deletions apps/ledger-live-mobile/src/actions/ratings.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export const setRatingsModalOpen = (isRatingsModalOpen: boolean) => ({
isRatingsModalOpen,
});

export const setRatingsModalLocked = (isRatingsModalLocked: boolean) => ({
type: "RATINGS_SET_MODAL_LOCKED",
isRatingsModalLocked,
});

export const setRatingsCurrentRouteName = (currentRouteName?: string) => ({
type: "RATINGS_SET_CURRENT_ROUTE_NAME",
currentRouteName,
Expand Down
6 changes: 5 additions & 1 deletion apps/ledger-live-mobile/src/actions/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,12 @@ export const setSensitiveAnalytics = (enabled: boolean) => ({
enabled,
});

export const setFirstConnectionHasDevice = (payload: boolean) => ({
export const setFirstConnectionHasDevice = () => ({
type: "SET_FIRST_CONNECTION_HAS_DEVICE",
});

export const setNotifications = (payload: any) => ({
type: "SET_NOTIFICATIONS",
payload,
});

Expand Down
16 changes: 16 additions & 0 deletions apps/ledger-live-mobile/src/components/FirebaseFeatureFlags.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { ReactNode } from "react";
import { useSelector } from "react-redux";
import remoteConfig from "@react-native-firebase/remote-config";
import {
FeatureFlagsProvider,
Expand All @@ -8,6 +9,8 @@ import { FeatureId } from "@ledgerhq/live-common/types/index";

import { formatFeatureId } from "./FirebaseRemoteConfig";

import { languageSelector } from "../reducers/settings";

type Props = {
children?: ReactNode;
};
Expand All @@ -16,6 +19,19 @@ const getFeature = (key: FeatureId) => {
try {
const value = remoteConfig().getValue(formatFeatureId(key));
const feature = JSON.parse(value.asString());
const currAppLanguage = useSelector(languageSelector);

if (
(feature.languages_whitelisted &&
!feature.languages_whitelisted.includes(currAppLanguage)) ||
(feature.languages_blacklisted &&
feature.languages_blacklisted.includes(currAppLanguage))
) {
return {
...feature,
enabled: false,
};
}

return feature;
} catch (error) {
Expand Down
29 changes: 15 additions & 14 deletions apps/ledger-live-mobile/src/components/FirebaseRemoteConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,22 @@ export const FirebaseRemoteConfigProvider = ({
}: Props): JSX.Element | null => {
const [loaded, setLoaded] = useState<boolean>(false);

const loadRemoteConfig = async () => {
try {
await remoteConfig().setDefaults({
...formatDefaultFeatures(defaultFeatures),
});
await remoteConfig().fetchAndActivate();
} catch (error) {
console.error(
`Failed to fetch Firebase remote config with error: ${error}`,
);
}
setLoaded(true);
};

useEffect(() => {
const fetchConfig = async () => {
try {
await remoteConfig().setDefaults({
...formatDefaultFeatures(defaultFeatures),
});
await remoteConfig().fetchAndActivate();
} catch (error) {
console.error(
`Failed to fetch Firebase remote config with error: ${error}`,
);
}
setLoaded(true);
};
fetchConfig();
loadRemoteConfig();
}, []);

if (!loaded) {
Expand Down
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 All @@ -24,6 +27,7 @@ import AboutSettings from "../../screens/Settings/About";
import Resources from "../../screens/Settings/Resources";
import GeneralSettings from "../../screens/Settings/General";
import CountervalueSettings from "../../screens/Settings/General/CountervalueSettings";
import NotificationsSettings from "../../screens/Settings/Notifications";
import HelpSettings from "../../screens/Settings/Help";
import RegionSettings from "../../screens/Settings/General/Region";
import CurrenciesList from "../../screens/Settings/CryptoAssets/Currencies/CurrenciesList";
Expand All @@ -45,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 @@ -97,6 +115,20 @@ export default function SettingsNavigator() {
title: t("settings.about.title"),
}}
/>
<Stack.Screen
name={ScreenName.NotificationsSettings}
component={NotificationsSettings}
options={{
headerLeft: () => (
<Box ml={6}>
<TouchableOpacity onPress={goBackFromNotifications}>
<Icons.ArrowLeftMedium size={24} />
</TouchableOpacity>
</Box>
),
title: t("settings.notifications.title"),
}}
/>
<Stack.Screen
name={ScreenName.HelpSettings}
component={HelpSettings}
Expand Down
Loading

0 comments on commit b7a4dcf

Please sign in to comment.