From ca4274009ae050b30695b7b505241e4530ecbd55 Mon Sep 17 00:00:00 2001
From: Ramy EL BEHEDY <32883529+RamyEB@users.noreply.github.com>
Date: Fri, 10 May 2024 14:49:38 +0200
Subject: [PATCH] feat: Save locally added manifest into the storage on both
Mobile and Desktop client (#6719)
feat: Save locally added manifest into the storage on both Mobile and Desktop client
---
.changeset/hot-zebras-ring.md | 7 +
.../components/PlatformAppProviderWrapper.tsx | 19 +-
.../StakeFlowModal/component/ProviderItem.tsx | 2 +-
.../modals/CreateLocalManifest/index.tsx | 2 +-
.../src/renderer/screens/earn/index.tsx | 2 +-
.../screens/exchange/Swap2/Form/index.tsx | 2 +-
.../src/renderer/screens/exchange/index.tsx | 2 +-
.../src/renderer/screens/platform/LiveApp.tsx | 2 +-
.../platform/v2/Catalog/Card/Minimum.tsx | 13 +-
.../v2/Catalog/LocalLiveAppSection.tsx | 37 +++
.../screens/platform/v2/Catalog/index.tsx | 10 +-
.../src/renderer/screens/platform/v2/hooks.ts | 10 +-
.../src/renderer/screens/recover/Player.tsx | 2 +-
.../sections/Developer/RunLocalAppButton.tsx | 10 +-
.../src/renderer/screens/swapWeb/index.tsx | 2 +-
.../static/i18n/en/app.json | 1 +
.../src/PlatformAppProviderWrapper.tsx | 19 +-
.../EvmStakingDrawerProvider.tsx | 8 +-
.../src/families/tron/Votes/index.tsx | 8 +-
.../src/locales/en/common.json | 1 +
.../src/screens/PTX/BuyAndSell/index.tsx | 2 +-
.../src/screens/PTX/Earn/index.tsx | 2 +-
.../src/screens/Platform/Catalog/AppCard.tsx | 2 +
.../src/screens/Platform/LiveApp.tsx | 2 +-
.../Platform/v2/Catalog/LocalLiveApp.tsx | 52 +++++
.../src/screens/Platform/v2/Catalog/index.tsx | 9 +-
.../src/screens/Platform/v2/hooks.ts | 12 +-
.../src/screens/Protect/Player.tsx | 2 +-
.../Settings/Developer/CustomManifest.tsx | 212 ++++++++++--------
libs/ledger-live-common/.unimportedrc.json | 4 +-
.../src/platform/hooks/useManifest.test.ts | 70 ------
.../src/platform/hooks/useManifest.ts | 15 --
.../providers/LocalLiveAppProvider/index.tsx | 83 -------
.../providers/LocalLiveAppProvider/types.ts | 10 -
.../providers/RemoteLiveAppProvider/types.ts | 4 -
.../wallet-api/LocalLiveAppProvider/index.tsx | 40 ++++
.../wallet-api/LocalLiveAppProvider/types.ts | 14 ++
.../src/wallet-api/constants.ts | 6 +-
.../src/wallet-api/react.ts | 52 +++++
.../src/wallet-api/types.ts | 1 +
40 files changed, 425 insertions(+), 328 deletions(-)
create mode 100644 .changeset/hot-zebras-ring.md
create mode 100644 apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/LocalLiveAppSection.tsx
create mode 100644 apps/ledger-live-mobile/src/screens/Platform/v2/Catalog/LocalLiveApp.tsx
delete mode 100644 libs/ledger-live-common/src/platform/hooks/useManifest.test.ts
delete mode 100644 libs/ledger-live-common/src/platform/hooks/useManifest.ts
delete mode 100644 libs/ledger-live-common/src/platform/providers/LocalLiveAppProvider/index.tsx
delete mode 100644 libs/ledger-live-common/src/platform/providers/LocalLiveAppProvider/types.ts
create mode 100644 libs/ledger-live-common/src/wallet-api/LocalLiveAppProvider/index.tsx
create mode 100644 libs/ledger-live-common/src/wallet-api/LocalLiveAppProvider/types.ts
diff --git a/.changeset/hot-zebras-ring.md b/.changeset/hot-zebras-ring.md
new file mode 100644
index 000000000000..ab6a0d6c7479
--- /dev/null
+++ b/.changeset/hot-zebras-ring.md
@@ -0,0 +1,7 @@
+---
+"ledger-live-desktop": patch
+"live-mobile": patch
+"@ledgerhq/live-common": patch
+---
+
+Save locally added manifest into the storage on both Mobile and Desktop client
diff --git a/apps/ledger-live-desktop/src/renderer/components/PlatformAppProviderWrapper.tsx b/apps/ledger-live-desktop/src/renderer/components/PlatformAppProviderWrapper.tsx
index 6bf9f3f63648..589e295657fa 100644
--- a/apps/ledger-live-desktop/src/renderer/components/PlatformAppProviderWrapper.tsx
+++ b/apps/ledger-live-desktop/src/renderer/components/PlatformAppProviderWrapper.tsx
@@ -7,8 +7,13 @@ import {
} from "~/renderer/reducers/settings";
import { useSelector } from "react-redux";
import { RemoteLiveAppProvider } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
-import { LocalLiveAppProvider } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
+import { LocalLiveAppProvider } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
import { RampCatalogProvider } from "@ledgerhq/live-common/platform/providers/RampCatalogProvider/index";
+import { useDB } from "../storage";
+import {
+ DISCOVER_STORE_KEY,
+ INITIAL_PLATFORM_STATE,
+} from "@ledgerhq/live-common/wallet-api/constants";
type PlatformAppProviderWrapperProps = {
children: ReactNode;
@@ -21,6 +26,7 @@ export function PlatformAppProviderWrapper({ children }: PlatformAppProviderWrap
const allowExperimentalApps = useSelector(allowExperimentalAppsSelector);
const provider = useSelector(catalogProviderSelector);
const locale = useSelector(languageSelector);
+ const localLiveAppDB = useLocalLiveAppDB();
return (
-
+
{children}
@@ -41,3 +47,12 @@ export function PlatformAppProviderWrapper({ children }: PlatformAppProviderWrap
);
}
+
+function useLocalLiveAppDB() {
+ return useDB(
+ "app",
+ DISCOVER_STORE_KEY,
+ INITIAL_PLATFORM_STATE,
+ state => state.localLiveApp || INITIAL_PLATFORM_STATE.localLiveApp,
+ );
+}
diff --git a/apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal/component/ProviderItem.tsx b/apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal/component/ProviderItem.tsx
index c3e80d1a2173..edc723a8548f 100644
--- a/apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal/component/ProviderItem.tsx
+++ b/apps/ledger-live-desktop/src/renderer/families/evm/StakeFlowModal/component/ProviderItem.tsx
@@ -1,4 +1,3 @@
-import { useLocalLiveAppManifest } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
import { Flex, Icon, Tag as TagCore, Text } from "@ledgerhq/react-ui";
import React, { useCallback, useEffect, useMemo } from "react";
@@ -7,6 +6,7 @@ import styled, { DefaultTheme, StyledComponent } from "styled-components";
import { StakeOnClickProps } from "../EthStakingModalBody";
import { StakingIcon } from "../StakingIcon";
import { ListProvider } from "../types";
+import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
export const Container: StyledComponent<
"div",
diff --git a/apps/ledger-live-desktop/src/renderer/modals/CreateLocalManifest/index.tsx b/apps/ledger-live-desktop/src/renderer/modals/CreateLocalManifest/index.tsx
index bf34f37bfb4f..ce7881299040 100644
--- a/apps/ledger-live-desktop/src/renderer/modals/CreateLocalManifest/index.tsx
+++ b/apps/ledger-live-desktop/src/renderer/modals/CreateLocalManifest/index.tsx
@@ -15,7 +15,6 @@ import {
LiveAppManifestSchemaType,
} from "@ledgerhq/live-common/platform/types";
import Text from "~/renderer/components/Text";
-import { useLocalLiveAppContext } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import Switch from "~/renderer/components/Switch";
import FormLiveAppInput from "./FormLiveAppInput";
import NestedFormCategory from "./NestedFormCategory";
@@ -32,6 +31,7 @@ import { Separator } from "~/renderer/components/Onboarding/Screens/SelectUseCas
import { DEFAULT_FORM, DEFAULT_VALUES } from "./defaultValues";
import { objectKeysType } from "@ledgerhq/live-common/helpers";
+import { useLocalLiveAppContext } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
function createLocalManifest() {
return (
diff --git a/apps/ledger-live-desktop/src/renderer/screens/earn/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/earn/index.tsx
index fde361c55229..a9156306ac21 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/earn/index.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/earn/index.tsx
@@ -9,9 +9,9 @@ import {
import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
import WebPlatformPlayer from "~/renderer/components/WebPlatformPlayer";
import useTheme from "~/renderer/hooks/useTheme";
-import { useLocalLiveAppManifest } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import { useDeepLinkListener } from "~/renderer/screens/earn/useDeepLinkListener";
import { useDiscreetMode } from "~/renderer/components/Discreet";
+import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
const DEFAULT_EARN_APP_ID = "earn";
diff --git a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/index.tsx
index f7e7370938c4..f8e011595edc 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/index.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/exchange/Swap2/Form/index.tsx
@@ -35,9 +35,9 @@ import SwapWebView, { SwapWebProps, useSwapLiveAppManifestID } from "./SwapWebVi
import { SwapMigrationUI } from "./Migrations/SwapMigrationUI";
import { useSwapLiveAppHook } from "~/renderer/hooks/swap-migrations/useSwapLiveAppHook";
import SwapFormSummary from "./FormSummary";
-import { useLocalLiveAppManifest } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
import { languageSelector } from "~/renderer/reducers/settings";
+import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
import { walletSelector } from "~/renderer/reducers/wallet";
const DAPP_PROVIDERS = ["paraswap", "oneinch", "moonpay"];
diff --git a/apps/ledger-live-desktop/src/renderer/screens/exchange/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/exchange/index.tsx
index 82b9b568c588..6191f55558de 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/exchange/index.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/exchange/index.tsx
@@ -8,7 +8,6 @@ import { languageSelector } from "~/renderer/reducers/settings";
import { accountsSelector } from "~/renderer/reducers/accounts";
import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
import useTheme from "~/renderer/hooks/useTheme";
-import { useLocalLiveAppManifest } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import WebPTXPlayer from "~/renderer/components/WebPTXPlayer";
import { getParentAccount, isTokenAccount } from "@ledgerhq/live-common/account/index";
import { LiveAppManifest, Loadable } from "@ledgerhq/live-common/platform/types";
@@ -20,6 +19,7 @@ import {
} from "@ledgerhq/live-common/wallet-api/constants";
import { useInternalAppIds } from "@ledgerhq/live-common/hooks/useInternalAppIds";
import { useFeature } from "@ledgerhq/live-common/featureFlags/index";
+import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
import { walletSelector } from "~/renderer/reducers/wallet";
export type DProps = {
diff --git a/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx b/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx
index f53f68f62faf..7ab5bfe641cc 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/platform/LiveApp.tsx
@@ -6,7 +6,7 @@ import WebPlatformPlayer from "~/renderer/components/WebPlatformPlayer";
import { languageSelector } from "~/renderer/reducers/settings";
import { useSelector } from "react-redux";
import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
-import { useLocalLiveAppManifest } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
+import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
type Props = {
match: {
diff --git a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/Card/Minimum.tsx b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/Card/Minimum.tsx
index 721e9760e68c..3da77bb2e917 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/Card/Minimum.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/Card/Minimum.tsx
@@ -7,16 +7,19 @@ import { Container, Subtitle } from "./Layout";
import { useSelector } from "react-redux";
import { languageSelector } from "~/renderer/reducers/settings";
import { RecentlyUsedManifest } from "@ledgerhq/live-common/wallet-api/react";
+import { LiveAppManifest } from "@ledgerhq/live-common/platform/types";
-export function MinimumCard(props: PropsCard) {
+export function MinimumCard(props: PropsCard) {
const { disabled, onClick } = useCard(props);
const { manifest } = props;
const lang = useSelector(languageSelector);
const usedAt = useMemo(() => {
- const rtf = new Intl.RelativeTimeFormat(lang);
- return rtf.format(-manifest.usedAt.diff, manifest.usedAt.unit);
- }, [lang, manifest.usedAt.diff, manifest.usedAt.unit]);
+ if ("usedAt" in manifest) {
+ const rtf = new Intl.RelativeTimeFormat(lang);
+ return rtf.format(-manifest.usedAt.diff, manifest.usedAt.unit);
+ } else return;
+ }, [lang, manifest]);
return (
@@ -27,7 +30,7 @@ export function MinimumCard(props: PropsCard) {
{manifest.name}
- {usedAt}
+ {usedAt && {usedAt}}
diff --git a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/LocalLiveAppSection.tsx b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/LocalLiveAppSection.tsx
new file mode 100644
index 000000000000..1f90ecc477f7
--- /dev/null
+++ b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/LocalLiveAppSection.tsx
@@ -0,0 +1,37 @@
+import React from "react";
+import { Flex } from "@ledgerhq/react-ui";
+import { MinimumCard } from "./Card";
+import styled from "styled-components";
+import { LiveAppManifest } from "@ledgerhq/live-common/platform/types";
+import { useHistory } from "react-router";
+import { SectionHeader } from "./SectionHeader";
+import { useTranslation } from "react-i18next";
+
+export function LocalLiveAppSection({ localLiveApps }: { localLiveApps: LiveAppManifest[] }) {
+ const history = useHistory();
+ const { t } = useTranslation();
+
+ return (
+
+
+ {t("platform.catalog.section.locallyLoaded")}
+
+
+ {localLiveApps.map(manifest => (
+
+ history.push(`/platform/${manifest.id}`)}
+ />
+
+ ))}
+
+
+ );
+}
+
+const Scroll = styled(Flex).attrs({ overflowX: "scroll" })`
+ &::-webkit-scrollbar {
+ display: none;
+ }
+`;
diff --git a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/index.tsx b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/index.tsx
index c1a8d4cd18d8..073b426ca46d 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/index.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/Catalog/index.tsx
@@ -4,13 +4,15 @@ import { Text, Flex } from "@ledgerhq/react-ui";
import { RecentlyUsed } from "./RecentlyUsed";
import { Browse } from "./Browse";
import { useTranslation } from "react-i18next";
-import { useCatalog, useDiscoverDB } from "../hooks";
+import { useCatalog, useRecentlyUsedDB } from "../hooks";
+import { LocalLiveAppSection } from "./LocalLiveAppSection";
export function Catalog() {
- const discoverDB = useDiscoverDB();
+ const recentlyUsedDB = useRecentlyUsedDB();
const { t } = useTranslation();
- const { categories, recentlyUsed, disclaimer, search } = useCatalog(discoverDB);
+ const { categories, recentlyUsed, disclaimer, search, localLiveApps } =
+ useCatalog(recentlyUsedDB);
return (
@@ -20,6 +22,8 @@ export function Catalog() {
{t("platform.catalog.title")}
+ {localLiveApps.length ? : null}
+
{recentlyUsed.data.length ? (
) : null}
diff --git a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/hooks.ts b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/hooks.ts
index 9afb043f8c2b..a9cbb17043b5 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/platform/v2/hooks.ts
+++ b/apps/ledger-live-desktop/src/renderer/screens/platform/v2/hooks.ts
@@ -21,12 +21,14 @@ import { useCallback, useMemo } from "react";
import { useHistory } from "react-router";
import { closePlatformAppDrawer, openPlatformAppDisclaimerDrawer } from "~/renderer/actions/UI";
import { useManifests } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
+import { useLocalLiveAppContext } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
-export function useCatalog(db: RecentlyUsedDB) {
+export function useCatalog(recentlyUsedDB: RecentlyUsedDB) {
const completeManifests = useManifests({ visibility: ["complete"] });
const combinedManifests = useManifests({ visibility: ["searchable", "complete"] });
const categories = useCategories(completeManifests);
- const recentlyUsed = useRecentlyUsed(combinedManifests, db);
+ const recentlyUsed = useRecentlyUsed(combinedManifests, recentlyUsedDB);
+ const { state: localLiveApps } = useLocalLiveAppContext();
const search = useSearch({
list: combinedManifests,
@@ -50,11 +52,11 @@ export function useCatalog(db: RecentlyUsedDB) {
recentlyUsed,
disclaimer,
search,
+ localLiveApps,
};
}
-// TODO: rename to useRecentlyUsedDB
-export function useDiscoverDB() {
+export function useRecentlyUsedDB() {
return useDB("app", DISCOVER_STORE_KEY, INITIAL_PLATFORM_STATE, state => state.recentlyUsed);
}
diff --git a/apps/ledger-live-desktop/src/renderer/screens/recover/Player.tsx b/apps/ledger-live-desktop/src/renderer/screens/recover/Player.tsx
index ac9a97e5e7db..81c452c2e698 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/recover/Player.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/recover/Player.tsx
@@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useMemo } from "react";
import { useSelector } from "react-redux";
import { RouteComponentProps, useHistory } from "react-router-dom";
import { useRemoteLiveAppManifest } from "@ledgerhq/live-common/platform/providers/RemoteLiveAppProvider/index";
-import { useLocalLiveAppManifest } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import { useOnboardingStatePolling } from "@ledgerhq/live-common/onboarding/hooks/useOnboardingStatePolling";
import { OnboardingStep } from "@ledgerhq/live-common/hw/extractOnboardingState";
import { counterValueCurrencySelector, languageSelector } from "~/renderer/reducers/settings";
@@ -12,6 +11,7 @@ import { getCurrentDevice } from "~/renderer/reducers/devices";
import styled from "styled-components";
import { useFeature } from "@ledgerhq/live-common/featureFlags/index";
import { StaticContext } from "react-router";
+import { useLocalLiveAppManifest } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
const pollingPeriodMs = 1000;
diff --git a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/RunLocalAppButton.tsx b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/RunLocalAppButton.tsx
index aa6d2213e0a1..1bebb7639d89 100644
--- a/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/RunLocalAppButton.tsx
+++ b/apps/ledger-live-desktop/src/renderer/screens/settings/sections/Developer/RunLocalAppButton.tsx
@@ -4,13 +4,13 @@ import React, { useCallback } from "react";
import Button from "~/renderer/components/Button";
import { useTranslation } from "react-i18next";
import { readFile, writeFile } from "fs";
-import { useLocalLiveAppContext } from "@ledgerhq/live-common/platform/providers/LocalLiveAppProvider/index";
import { SettingsSectionRow as Row } from "../../SettingsSection";
import { useHistory } from "react-router-dom";
import styled from "styled-components";
import { Flex } from "@ledgerhq/react-ui";
import { useDispatch } from "react-redux";
import { openModal } from "~/renderer/actions/modals";
+import { useLocalLiveAppContext } from "@ledgerhq/live-common/wallet-api/LocalLiveAppProvider/index";
import { LiveAppManifest } from "@ledgerhq/live-common/platform/types";
const ButtonContainer = styled.div`
@@ -23,7 +23,7 @@ const RunLocalAppButton = () => {
const { t } = useTranslation();
const {
addLocalManifest,
- state: { liveAppByIndex },
+ state: localLiveApps,
removeLocalManifestById,
} = useLocalLiveAppContext();
@@ -41,7 +41,7 @@ const RunLocalAppButton = () => {
})
.then(function (response) {
if (!response.canceled && response.filePath) {
- const exportedManifest = liveAppByIndex.find(
+ const exportedManifest = localLiveApps.find(
(manifest: LiveAppManifest) => manifest.id === id,
);
@@ -56,7 +56,7 @@ const RunLocalAppButton = () => {
}
});
},
- [liveAppByIndex],
+ [localLiveApps],
);
const onBrowseLocalManifest = useCallback(() => {
@@ -121,7 +121,7 @@ const RunLocalAppButton = () => {
- {liveAppByIndex.map((manifest: LiveAppManifest) => (
+ {localLiveApps.map((manifest: LiveAppManifest) => (