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

[LIVE-13575][LLD, LLM][MyLedger]: Filtering of apps depending on feature flag #7542

Merged
merged 1 commit into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading