Skip to content
This repository has been archived by the owner on Jun 16, 2022. It is now read-only.

Commit

Permalink
Merge pull request #2084 from LedgerHQ/platform-experimental
Browse files Browse the repository at this point in the history
Introduce Developer settings and add toggle button to show experimental platform apps
  • Loading branch information
JunichiSugiura authored Jan 7, 2022
2 parents 8b28024 + b8add92 commit 7be135d
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/components/KeyboardView.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "react-native";
import { useHeaderHeight } from "@react-navigation/elements";
import { HEIGHT as ExperimentalHeaderHeight } from "../screens/Settings/Experimental/ExperimentalHeader";
import useExperimental from "../screens/Settings/Experimental/useExperimental";
import { useExperimental } from "../experimental";

const { DeviceInfo } = NativeModules;

Expand Down
8 changes: 8 additions & 0 deletions src/components/RootNavigator/SettingsNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import DebugSettings, {
} from "../../screens/Settings/Debug";
import DebugExport from "../../screens/Settings/Debug/ExportAccounts";
import ExperimentalSettings from "../../screens/Settings/Experimental";
import DeveloperSettings from "../../screens/Settings/Developer";
import RepairDevice from "../../screens/RepairDevice";
import { getStackNavigatorConfig } from "../../navigation/navigatorConfig";
import Button from "../Button";
Expand Down Expand Up @@ -118,6 +119,13 @@ export default function SettingsNavigator() {
title: t("settings.experimental.title"),
}}
/>
<Stack.Screen
name={ScreenName.DeveloperSettings}
component={DeveloperSettings}
options={{
title: t("settings.developer.title"),
}}
/>
<Stack.Screen
name={ScreenName.DebugSettings}
component={DebugSettings}
Expand Down
1 change: 1 addition & 0 deletions src/const/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const ScreenName = {
DelegationSummary: "DelegationSummary",
DelegationValidationError: "DelegationValidationError",
DelegationValidationSuccess: "DelegationValidationSuccess",
DeveloperSettings: "DeveloperSettings",
DisplayResult: "DisplayResult",
Distribution: "Distribution",
EditAccountName: "EditAccountName",
Expand Down
38 changes: 36 additions & 2 deletions src/experimental.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @flow
import { useState, useEffect } from "react";
import Config from "react-native-config";
import AsyncStorage from "@react-native-community/async-storage";
import { concatMap } from "rxjs/operators";
Expand Down Expand Up @@ -102,6 +103,15 @@ export const experimentalFeatures: Feature[] = [
: []),
];

export const developerFeatures: Feature[] = [
{
type: "toggle",
name: "PLATFORM_EXPERIMENTAL_APPS",
title: "Allow experimental apps",
description: "Display and allow opening experimental tagged platform apps.",
},
];

const storageKey = "experimentalFlags";

export const getStorageEnv = async () => {
Expand All @@ -128,7 +138,9 @@ export const isReadOnly = (key: EnvName) => key in Config;

export const enabledExperimentalFeatures = (): string[] =>
// $FlowFixMe
experimentalFeatures.map(e => e.name).filter(k => !isEnvDefault(k));
[...experimentalFeatures, ...developerFeatures]
.map(e => e.name)
.filter(k => !isEnvDefault(k));

(async () => {
const envs = await getStorageEnv();
Expand All @@ -144,7 +156,12 @@ export const enabledExperimentalFeatures = (): string[] =>
/* eslint-enable guard-for-in */

const saveEnvs = async (name, value) => {
if (experimentalFeatures.find(f => f.name === name) && !isReadOnly(name)) {
if (
[...experimentalFeatures, ...developerFeatures].find(
f => f.name === name,
) &&
!isReadOnly(name)
) {
await setStorageEnvs(name, value);
}
};
Expand All @@ -153,3 +170,20 @@ export const enabledExperimentalFeatures = (): string[] =>
.pipe(concatMap(({ name, value }) => saveEnvs(name, value)))
.subscribe();
})();

export function useExperimental(): boolean {
const [state, setState] = useState(
() => enabledExperimentalFeatures().length > 0,
);

useEffect(() => {
const sub = changes.subscribe(() => {
const newExperimental = enabledExperimentalFeatures().length > 0;
setState(newExperimental);
});

return () => sub.unsubscribe();
}, []);

return state;
}
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ const linkingOptions = {
[ScreenName.AboutSettings]: "settings/about",
[ScreenName.HelpSettings]: "settings/help",
[ScreenName.ExperimentalSettings]: "settings/experimental",
[ScreenName.DeveloperSettings]: "settings/developer",
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,10 @@
"title": "Experimental features",
"desc": "Try out the Experimental features and let us know what you think.",
"disclaimer": "These are Experimental features provided on an \"as is\" basis for our community of tech enthusiasts. They may change, break or be removed at any time. By enabling them, you agree to use them at your own risk."
},
"developer": {
"title": "Developer",
"desc": "Try out the Developer features and let us know what you think."
}
},
"migrateAccounts": {
Expand Down
3 changes: 3 additions & 0 deletions src/navigation/useDeepLinking.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ function getSettingsScreen(pathname) {
case "experimental":
screen = ScreenName.ExperimentalSettings;
break;
case "developer":
screen = ScreenName.DeveloperSettings;
break;
default:
screen = ScreenName.Settings;
}
Expand Down
10 changes: 8 additions & 2 deletions src/screens/Platform/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { usePlatformApp } from "@ledgerhq/live-common/lib/platform/PlatformAppPr
import { filterPlatformApps } from "@ledgerhq/live-common/lib/platform/PlatformAppProvider/helpers";
import type { AccountLike, Account } from "@ledgerhq/live-common/lib/types";
import type { AppManifest } from "@ledgerhq/live-common/lib/platform/types";
import useEnv from "@ledgerhq/live-common/lib/hooks/useEnv";

import { useBanner } from "../../components/banners/hooks";
import TrackScreen from "../../analytics/TrackScreen";
Expand Down Expand Up @@ -39,16 +40,21 @@ const PlatformCatalog = ({ route }: { route: { params: RouteParams } }) => {
const navigation = useNavigation();

const { manifests } = usePlatformApp();
const experimental = useEnv("PLATFORM_EXPERIMENTAL_APPS");

const filteredManifests = useMemo(() => {
const branches = ["stable", "soon"];
const branches = [
"stable",
"soon",
...(experimental ? ["experimental"] : []),
];

return filterPlatformApps(Array.from(manifests.values()), {
version: "0.0.1",
platform: "mobile",
branches,
});
}, [manifests]);
}, [manifests, experimental]);

// Disclaimer State
const [disclaimerOpts, setDisclaimerOpts] = useState<DisclaimerOpts>(null);
Expand Down
23 changes: 23 additions & 0 deletions src/screens/Settings/Developer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// @flow
import { isEnvDefault } from "@ledgerhq/live-common/lib/env";
import React from "react";
import { ScrollView } from "react-native";
import { developerFeatures } from "../../experimental";
import { TrackScreen } from "../../analytics";
import FeatureRow from "./Experimental/FeatureRow";

export default function DeveloperSettings() {
return (
<ScrollView>
<TrackScreen category="Settings" name="Developer" />

{developerFeatures.map(
feat =>
(!feat.shadow || (feat.shadow && !isEnvDefault(feat.name))) && (
// $FlowFixMe
<FeatureRow key={feat.name} feature={feat} />
),
)}
</ScrollView>
);
}
2 changes: 1 addition & 1 deletion src/screens/Settings/Experimental/ExperimentalHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Animated, { Extrapolate } from "react-native-reanimated";
import { Trans } from "react-i18next";
import { useTheme } from "@react-navigation/native";
import Config from "react-native-config";
import useExperimental from "./useExperimental";
import { useExperimental } from "../../../experimental";
import { runCollapse } from "../../../components/CollapsibleList";
import LText from "../../../components/LText";
import ExperimentalIcon from "../../../icons/Experimental";
Expand Down
24 changes: 0 additions & 24 deletions src/screens/Settings/Experimental/useExperimental.js

This file was deleted.

7 changes: 7 additions & 0 deletions src/screens/Settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import LiveLogo from "../../icons/LiveLogo";
import Atom from "../../icons/Atom";
import Help from "../../icons/Help";
import Display from "../../icons/Display";
import Wrench from "../../icons/Wrench";
import TrackScreen from "../../analytics/TrackScreen";
import timer from "../../timer";
import NavigationScrollView from "../../components/NavigationScrollView";
Expand Down Expand Up @@ -87,6 +88,12 @@ export default function Settings({ navigation }: Props) {
icon={<Atom size={16} color={colors.live} />}
onClick={() => navigation.navigate(ScreenName.ExperimentalSettings)}
/>
<SettingsCard
title={t("settings.developer.title")}
desc={t("settings.developer.desc")}
icon={<Wrench size={16} color={colors.live} />}
onClick={() => navigation.navigate(ScreenName.DeveloperSettings)}
/>
{debugVisible || __DEV__ ? (
<SettingsCard
title="Debug"
Expand Down

0 comments on commit 7be135d

Please sign in to comment.