Skip to content

Commit

Permalink
fix(MyLedger): filtering of apps depending on feature flag
Browse files Browse the repository at this point in the history
  • Loading branch information
ofreyssinet-ledger committed Aug 7, 2024
1 parent a00351f commit 313d0e4
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 78 deletions.
7 changes: 7 additions & 0 deletions .changeset/khaki-melons-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"ledger-live-desktop": patch
"live-mobile": patch
"@ledgerhq/live-common": patch
---

My Ledger: fix & refactor logic of "is app supported by Ledger Live" depending on feature flags, and associated filters in apps catalog. Now this logic is in one single place and fully unit tested.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ type Props = {
setAppUninstallDep?: (a: { dependents: App[]; app: App }) => void;
isLiveSupported: boolean;
addAccount?: () => void;
featureFlagActivated: boolean;
};

// eslint-disable-next-line react/display-name
Expand All @@ -80,7 +79,6 @@ const AppActions = React.memo(
setAppUninstallDep,
isLiveSupported,
addAccount,
featureFlagActivated,
}: Props) => {
const { name, type } = app;

Expand Down Expand Up @@ -141,7 +139,7 @@ const AppActions = React.memo(

// FIXME: given the heavy use of conditions in the rendering logic below,
// it would be better to derive this value from the same rendering logic...
const hasTwoItems = showLearnMore || (hasSpecificAction && installed && featureFlagActivated);
const hasTwoItems = showLearnMore || (hasSpecificAction && installed);

return (
<AppActionsWrapper right={!hasTwoItems}>
Expand Down Expand Up @@ -182,7 +180,7 @@ const AppActions = React.memo(
/>
) : showActions ? (
<>
{installed && featureFlagActivated ? (
{installed ? (
isCurrencyApp && isLiveSupported ? (
<Tooltip
content={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useMemo, memo, useCallback } from "react";
import camelCase from "lodash/camelCase";
import { useNotEnoughMemoryToInstall } from "@ledgerhq/live-common/apps/react";
import { getCryptoCurrencyById, isCurrencySupported } from "@ledgerhq/live-common/currencies/index";
import { App, FeatureId } from "@ledgerhq/types-live";
import { getCryptoCurrencyById } from "@ledgerhq/live-common/currencies/index";
import { App } from "@ledgerhq/types-live";
import { State, Action, InstalledItem } from "@ledgerhq/live-common/apps/types";
import { isAppAssociatedCurrencySupported } from "@ledgerhq/live-common/apps/filtering";
import styled from "styled-components";
import { Trans } from "react-i18next";

Expand All @@ -16,7 +16,7 @@ import IconInfoCircleFull from "~/renderer/icons/InfoCircleFull";
import AppActions from "./AppActions";
import AppIcon from "./AppIcon";
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
import { useFeature } from "@ledgerhq/live-common/featureFlags/index";
import { useFeature, useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
import ToolTip from "~/renderer/components/Tooltip";

const AppRowContainer = styled.div`
Expand Down Expand Up @@ -92,7 +92,7 @@ const Item = ({
setAppUninstallDep,
addAccount,
}: Props) => {
const { name, type, currencyId, authorName } = app;
const { name, authorName } = app;
const { deviceModel, deviceInfo } = state;
const notEnoughMemoryToInstall = useNotEnoughMemoryToInstall(optimisticState, name);
const currency = useMemo(
Expand All @@ -109,13 +109,8 @@ const Item = ({
[app.name, state.apps],
);

// FIXME No explicit mapping between Currency.id and FeatureId
const flag = useFeature(camelCase(`currency_${currencyId}`) as FeatureId);

// when the flag doesn't exist it's equivalent to being enabled
const currencyFlagEnabled = !flag || flag.enabled;
const currencySupported = !!currency && isCurrencySupported(currency) && currencyFlagEnabled;
const isLiveSupported = currencySupported || ["swap", "plugin"].includes(type);
const { getFeature, isFeature } = useFeatureFlags();
const isLiveSupported = isAppAssociatedCurrencySupported({ app, isFeature, getFeature });

const bytes = useMemo(
() =>
Expand Down Expand Up @@ -169,7 +164,7 @@ const Item = ({
</ToolTip>
</Box>
<Box flex="0.7" horizontal alignContent="center" justifyContent="flex-start" ml={5}>
{isLiveSupported && currencyFlagEnabled ? (
{isLiveSupported ? (
<>
<Box>
<IconCheckFull size={16} />
Expand Down Expand Up @@ -204,7 +199,6 @@ const Item = ({
setAppUninstallDep={setAppUninstallDep}
isLiveSupported={isLiveSupported}
addAccount={onAddAccount}
featureFlagActivated={currencyFlagEnabled}
/>
</AppRowContainer>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, memo, useCallback, useEffect, useRef, useMemo } from "react";
import React, { useState, memo, useCallback, useEffect, useRef } from "react";
import { useLocation, useHistory } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import styled from "styled-components";
Expand All @@ -21,12 +21,10 @@ import { openModal } from "~/renderer/actions/modals";
import debounce from "lodash/debounce";
import InstallSuccessBanner from "./InstallSuccessBanner";
import SearchBox from "../../../accounts/AccountList/SearchBox";
import { App, FeatureId } from "@ledgerhq/types-live";
import { App } from "@ledgerhq/types-live";
import { AppType, SortOptions } from "@ledgerhq/live-common/apps/filtering";
import NoResults from "~/renderer/icons/NoResults";
import { CryptoOrTokenCurrency } from "@ledgerhq/types-cryptoassets";
import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
import camelCase from "lodash/camelCase";
import { getEnv } from "@ledgerhq/live-env";

// sticky top bar with extra width to cover card boxshadow underneath
Expand Down Expand Up @@ -128,17 +126,6 @@ const AppsList = ({

const displayedAppList = isDeviceTab ? device : catalog;

const { getFeature } = useFeatureFlags();
const enabledAppList = useMemo(
() =>
displayedAppList.filter(({ currencyId }: App) => {
if (!currencyId) return true;
const currencyFeatureKey = camelCase(`currency_${currencyId}`) as FeatureId;
return getFeature(currencyFeatureKey)?.enabled ?? true;
}),
[displayedAppList, getFeature],
);

const mapApp = useCallback(
(app: App, appStoreView: boolean, onlyUpdate?: boolean, showActions?: boolean) => {
return (
Expand Down Expand Up @@ -238,8 +225,8 @@ const AppsList = ({
/>
)}
</FilterHeader>
{enabledAppList.length ? (
enabledAppList.map((app: App) => mapApp(app, !isDeviceTab))
{displayedAppList.length ? (
displayedAppList.map((app: App) => mapApp(app, !isDeviceTab))
) : (
<Placeholder
query={query}
Expand Down
17 changes: 2 additions & 15 deletions apps/ledger-live-mobile/src/screens/MyLedgerDevice/AppsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
predictOptimisticState,
reducer,
} from "@ledgerhq/live-common/apps/index";
import { App, DeviceInfo, FeatureId } from "@ledgerhq/types-live";
import { App, DeviceInfo } from "@ledgerhq/types-live";
import { useAppsSections } from "@ledgerhq/live-common/apps/react";

import { Text, Flex } from "@ledgerhq/native-ui";
Expand Down Expand Up @@ -51,8 +51,6 @@ import { ScreenName } from "~/const";
import { lastSeenDeviceSelector } from "~/reducers/settings";
import ProviderWarning from "./ProviderWarning";
import { UpdateStep } from "../FirmwareUpdate";
import { useFeatureFlags } from "@ledgerhq/live-common/featureFlags/index";
import camelCase from "lodash/camelCase";
import { useTheme } from "styled-components/native";
import KeyboardView from "~/components/KeyboardView";
import { getEnv } from "@ledgerhq/live-env";
Expand Down Expand Up @@ -392,17 +390,6 @@ const AppsScreen = ({
[listHeader, onScroll, renderFooter, renderRow, renderSearchBar],
);

const { getFeature, isFeature } = useFeatureFlags();
const enabledApps = useMemo(
() =>
catalog.filter(({ currencyId }: App) => {
if (!currencyId) return true;
const currencyFeatureKey = camelCase(`currency_${currencyId}`) as FeatureId;
return isFeature(currencyFeatureKey) ? getFeature(currencyFeatureKey)?.enabled : true;
}),
[catalog, getFeature, isFeature],
);

return (
<Flex flex={1} bg="background.main" px={6}>
<Search
Expand All @@ -412,7 +399,7 @@ const AppsScreen = ({
shouldSort: false,
}}
value={query.trim()}
items={enabledApps}
items={catalog}
render={renderList}
renderEmptySearch={renderList}
/>
Expand Down
Loading

0 comments on commit 313d0e4

Please sign in to comment.