Merge pull request #6315 from BlueWallet/defaultview

REF: DefaultView to TSX and hook
This commit is contained in:
GLaDOS 2024-03-23 22:03:05 +00:00 committed by GitHub
commit b589f1ab0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 189 additions and 151 deletions

View file

@ -11,7 +11,7 @@ import Licensing from './screen/settings/Licensing';
import NetworkSettings from './screen/settings/NetworkSettings';
import Settings from './screen/settings/Settings';
import About from './screen/settings/about';
import DefaultView from './screen/settings/defaultView';
import DefaultView from './screen/settings/DefaultView';
import ElectrumSettings from './screen/settings/electrumSettings';
import EncryptStorage from './screen/settings/encryptStorage';
import Language from './screen/settings/language';
@ -114,7 +114,12 @@ const WalletsRoot = () => {
<WalletsStack.Screen name="ReleaseNotes" component={ReleaseNotes} options={ReleaseNotes.navigationOptions(theme)} />
<WalletsStack.Screen name="Selftest" component={Selftest} options={Selftest.navigationOptions(theme)} />
<WalletsStack.Screen name="Licensing" component={Licensing} options={Licensing.navigationOptions(theme)} />
<WalletsStack.Screen name="DefaultView" component={DefaultView} options={DefaultView.navigationOptions(theme)} />
<WalletsStack.Screen
name="DefaultView"
component={DefaultView}
options={navigationStyle({ title: loc.settings.default_title })(theme)}
/>
<WalletsStack.Screen name="Language" component={Language} options={navigationStyle({ title: loc.settings.language })(theme)} />
<WalletsStack.Screen name="EncryptStorage" component={EncryptStorage} options={EncryptStorage.navigationOptions(theme)} />
<WalletsStack.Screen

View file

@ -1,48 +0,0 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { TWallet } from './wallets/types';
import BlueApp from '../BlueApp';
export default class OnAppLaunch {
static STORAGE_KEY = 'ONAPP_LAUNCH_SELECTED_DEFAULT_WALLET_KEY';
static async isViewAllWalletsEnabled(): Promise<boolean> {
try {
const selectedDefaultWallet = await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY);
return selectedDefaultWallet === '' || selectedDefaultWallet === null;
} catch (_e) {
return true;
}
}
static async setViewAllWalletsEnabled(value: boolean) {
if (!value) {
const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet();
if (!selectedDefaultWallet) {
const firstWallet = BlueApp.getWallets()[0];
await OnAppLaunch.setSelectedDefaultWallet(firstWallet.getID());
}
} else {
await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, '');
}
}
static async getSelectedDefaultWallet(): Promise<TWallet | undefined> {
let selectedWallet: TWallet | undefined;
try {
const selectedWalletID = JSON.parse((await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY)) || 'null');
if (selectedWalletID) {
selectedWallet = BlueApp.getWallets().find(wallet => wallet.getID() === selectedWalletID);
if (!selectedWallet) {
await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, '');
}
}
} catch (_e) {
return;
}
return selectedWallet;
}
static async setSelectedDefaultWallet(value: string) {
await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, JSON.stringify(value));
}
}

View file

@ -3,19 +3,19 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { CommonActions } from '@react-navigation/native';
import { DeviceEventEmitter, Linking, Platform } from 'react-native';
import QuickActions from 'react-native-quick-actions';
import * as NavigationService from '../NavigationService';
import { BlueStorageContext } from '../blue_modules/storage-context';
import { formatBalance } from '../loc';
import DeeplinkSchemaMatch from './deeplink-schema-match';
import OnAppLaunch from './on-app-launch';
import { TWallet } from './wallets/types';
import useOnAppLaunch from '../hooks/useOnAppLaunch';
const DeviceQuickActionsStorageKey = 'DeviceQuickActionsEnabled';
function DeviceQuickActions(): JSX.Element | null {
const { wallets, walletsInitialized, isStorageEncrypted, preferredFiatCurrency, addWallet, saveToDisk, setSharedCosigner } =
useContext(BlueStorageContext);
const { isViewAllWalletsEnabled, getSelectedDefaultWallet } = useOnAppLaunch();
useEffect(() => {
if (walletsInitialized) {
@ -92,22 +92,19 @@ function DeviceQuickActions(): JSX.Element | null {
handleOpenURL({ url });
}
} else {
const isViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
if (!isViewAllWalletsEnabled) {
const selectedDefaultWallet = (await OnAppLaunch.getSelectedDefaultWallet()) as TWallet;
if (!(await isViewAllWalletsEnabled())) {
const selectedDefaultWalletID = (await getSelectedDefaultWallet()) as string;
const selectedDefaultWallet = wallets.find((w: TWallet) => w.getID() === selectedDefaultWalletID);
if (selectedDefaultWallet) {
const wallet = wallets.find(w => w.getID() === selectedDefaultWallet.getID());
if (wallet) {
NavigationService.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
params: {
walletID: wallet.getID(),
walletType: wallet.type,
},
}),
);
}
NavigationService.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
params: {
walletID: selectedDefaultWalletID,
walletType: selectedDefaultWallet.type,
},
}),
);
}
}
}

70
hooks/useOnAppLaunch.ts Normal file
View file

@ -0,0 +1,70 @@
import { useCallback, useContext } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { BlueStorageContext } from '../blue_modules/storage-context';
import { TWallet } from '../class/wallets/types';
const useOnAppLaunch = () => {
const STORAGE_KEY = 'ONAPP_LAUNCH_SELECTED_DEFAULT_WALLET_KEY';
const { wallets } = useContext(BlueStorageContext);
const getSelectedDefaultWallet = useCallback(async (): Promise<string | undefined> => {
let selectedWallet: TWallet | undefined;
try {
const selectedWalletID = JSON.parse((await AsyncStorage.getItem(STORAGE_KEY)) || 'null');
if (selectedWalletID !== null) {
selectedWallet = wallets.find((wallet: TWallet) => wallet.getID() === selectedWalletID);
if (!selectedWallet) {
await AsyncStorage.removeItem(STORAGE_KEY);
return undefined;
}
} else {
return undefined;
}
} catch (_e) {
return undefined;
}
return selectedWallet.getID();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [STORAGE_KEY]);
const setSelectedDefaultWallet = useCallback(
async (value: string): Promise<void> => {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(value));
},
[STORAGE_KEY],
); // No external dependencies
const isViewAllWalletsEnabled = useCallback(async (): Promise<boolean> => {
try {
const selectedDefaultWallet = await AsyncStorage.getItem(STORAGE_KEY);
return selectedDefaultWallet === '' || selectedDefaultWallet === null;
} catch (_e) {
return true;
}
}, [STORAGE_KEY]); // No external dependencies
const setViewAllWalletsEnabled = useCallback(
async (value: boolean): Promise<void> => {
if (!value) {
const selectedDefaultWallet = await getSelectedDefaultWallet();
if (!selectedDefaultWallet) {
const firstWallet = wallets[0];
await setSelectedDefaultWallet(firstWallet.getID());
}
} else {
await AsyncStorage.setItem(STORAGE_KEY, '');
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[STORAGE_KEY, getSelectedDefaultWallet, setSelectedDefaultWallet],
);
return {
isViewAllWalletsEnabled,
setViewAllWalletsEnabled,
getSelectedDefaultWallet,
setSelectedDefaultWallet,
};
};
export default useOnAppLaunch;

View file

@ -0,0 +1,91 @@
import React, { useContext, useEffect, useState } from 'react';
import { View, TouchableWithoutFeedback, ScrollView } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { BlueCard, BlueText } from '../../BlueComponents';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import ListItem from '../../components/ListItem';
import useOnAppLaunch from '../../hooks/useOnAppLaunch';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { TWallet } from '../../class/wallets/types';
type RootStackParamList = {
SelectWallet: { onWalletSelect: (wallet: TWallet) => void; onChainRequireSend: boolean };
};
type DefaultViewNavigationProp = NativeStackNavigationProp<RootStackParamList, 'SelectWallet'>;
const DefaultView: React.FC = () => {
const [defaultWalletLabel, setDefaultWalletLabel] = useState<string>('');
const [isViewAllWalletsSwitchEnabled, setIsViewAllWalletsSwitchEnabled] = useState<boolean>(true);
const { navigate, pop } = useNavigation<DefaultViewNavigationProp>();
const { wallets } = useContext(BlueStorageContext);
const { isViewAllWalletsEnabled, getSelectedDefaultWallet, setSelectedDefaultWallet, setViewAllWalletsEnabled } = useOnAppLaunch();
useEffect(() => {
(async () => {
const newViewAllWalletsEnabled: boolean = await isViewAllWalletsEnabled();
let newDefaultWalletLabel: string = '';
const walletID = await getSelectedDefaultWallet();
if (walletID) {
const w = wallets.find(wallet => wallet.getID() === walletID);
if (w) newDefaultWalletLabel = w.getLabel();
}
setDefaultWalletLabel(newDefaultWalletLabel);
setIsViewAllWalletsSwitchEnabled(newViewAllWalletsEnabled);
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const onViewAllWalletsSwitchValueChanged = async (value: boolean) => {
await setViewAllWalletsEnabled(value);
if (value) {
setIsViewAllWalletsSwitchEnabled(true);
setDefaultWalletLabel('');
} else {
const selectedWalletID = await getSelectedDefaultWallet();
const selectedWallet = wallets.find(wallet => wallet.getID() === selectedWalletID);
if (selectedWallet) {
setDefaultWalletLabel(selectedWallet.getLabel());
setIsViewAllWalletsSwitchEnabled(false);
}
}
};
const selectWallet = () => {
navigate('SelectWallet', { onWalletSelect: onWalletSelectValueChanged, onChainRequireSend: false });
};
const onWalletSelectValueChanged = async (wallet: TWallet) => {
await setViewAllWalletsEnabled(false);
await setSelectedDefaultWallet(wallet.getID());
setDefaultWalletLabel(wallet.getLabel());
setIsViewAllWalletsSwitchEnabled(false);
pop();
};
return (
<ScrollView automaticallyAdjustContentInsets={false} contentInsetAdjustmentBehavior="automatic">
<View>
<ListItem
title={loc.settings.default_wallets}
Component={TouchableWithoutFeedback}
switch={{
onValueChange: onViewAllWalletsSwitchValueChanged,
value: isViewAllWalletsSwitchEnabled,
disabled: wallets.length <= 0,
}}
/>
<BlueCard>
<BlueText>{loc.settings.default_desc}</BlueText>
</BlueCard>
{!isViewAllWalletsSwitchEnabled && (
<ListItem title={loc.settings.default_info} onPress={selectWallet} rightTitle={defaultWalletLabel} chevron />
)}
</View>
</ScrollView>
);
};
export default DefaultView;

View file

@ -1,80 +0,0 @@
import React, { useContext, useEffect, useState } from 'react';
import { View, TouchableWithoutFeedback, ScrollView } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import navigationStyle from '../../components/navigationStyle';
import { BlueCard, BlueText } from '../../BlueComponents';
import OnAppLaunch from '../../class/on-app-launch';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import ListItem from '../../components/ListItem';
const DefaultView = () => {
const [defaultWalletLabel, setDefaultWalletLabel] = useState('');
const [viewAllWalletsEnabled, setViewAllWalletsEnabled] = useState(true);
const { navigate, pop } = useNavigation();
const { wallets } = useContext(BlueStorageContext);
useEffect(() => {
(async () => {
const newViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
let newDefaultWalletLabel = '';
const wallet = await OnAppLaunch.getSelectedDefaultWallet();
if (wallet) {
newDefaultWalletLabel = wallet.getLabel();
}
setDefaultWalletLabel(newDefaultWalletLabel);
setViewAllWalletsEnabled(newViewAllWalletsEnabled);
})();
});
const onViewAllWalletsSwitchValueChanged = async value => {
await OnAppLaunch.setViewAllWalletsEnabled(value);
if (value) {
setViewAllWalletsEnabled(true);
setDefaultWalletLabel('');
} else {
const selectedWallet = await OnAppLaunch.getSelectedDefaultWallet();
setDefaultWalletLabel(selectedWallet.getLabel());
setViewAllWalletsEnabled(false);
}
};
const selectWallet = () => {
navigate('SelectWallet', { onWalletSelect: onWalletSelectValueChanged });
};
const onWalletSelectValueChanged = async wallet => {
await OnAppLaunch.setViewAllWalletsEnabled(false);
await OnAppLaunch.setSelectedDefaultWallet(wallet.getID());
setDefaultWalletLabel(wallet.getLabel());
setViewAllWalletsEnabled(false);
pop();
};
return (
<ScrollView automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
<View>
<ListItem
title={loc.settings.default_wallets}
Component={TouchableWithoutFeedback}
switch={{
onValueChange: onViewAllWalletsSwitchValueChanged,
value: viewAllWalletsEnabled,
disabled: wallets.length <= 0,
}}
/>
<BlueCard>
<BlueText>{loc.settings.default_desc}</BlueText>
</BlueCard>
{!viewAllWalletsEnabled && (
<ListItem title={loc.settings.default_info} onPress={selectWallet} rightTitle={defaultWalletLabel} chevron />
)}
</View>
</ScrollView>
);
};
DefaultView.navigationOptions = navigationStyle({}, opts => ({ ...opts, title: loc.settings.default_title }));
export default DefaultView;

View file

@ -12,17 +12,20 @@ import { BlueStorageContext } from '../../blue_modules/storage-context';
import { useTheme } from '../../components/themes';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import SafeArea from '../../components/SafeArea';
import { Chain } from '../../models/bitcoinUnits';
const SelectWallet = () => {
const { chainType, onWalletSelect, availableWallets, noWalletExplanationText } = useRoute().params;
const { chainType, onWalletSelect, availableWallets, noWalletExplanationText, onChainRequireSend = false } = useRoute().params;
const [isLoading, setIsLoading] = useState(true);
const { pop, navigate, setOptions, getParent } = useNavigation();
const { wallets } = useContext(BlueStorageContext);
const { colors, closeImage } = useTheme();
const isModal = useNavigationState(state => state.routes.length) === 1;
let data = chainType
? wallets.filter(item => item.chain === chainType && item.allowSend())
: wallets.filter(item => item.allowSend()) || [];
let data = !onChainRequireSend
? wallets.filter(item => item.chain === Chain.ONCHAIN) || []
: chainType
? wallets.filter(item => item.chain === chainType && item.allowSend())
: wallets.filter(item => item.allowSend()) || [];
if (availableWallets && availableWallets.length > 0) {
// availableWallets if provided, overrides chainType argument and `allowSend()` check