mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 09:50:15 +01:00
Merge pull request #6974 from BlueWallet/devmenu
ADD: Dev Menu (only for debug mode)
This commit is contained in:
commit
65211e7fa8
@ -3,8 +3,11 @@ import { Dimensions } from 'react-native';
|
||||
|
||||
import { isDesktop, isTablet } from '../../blue_modules/environment';
|
||||
|
||||
type ScreenSize = 'Handheld' | 'LargeScreen' | undefined;
|
||||
|
||||
interface ILargeScreenContext {
|
||||
isLargeScreen: boolean;
|
||||
setLargeScreenValue: (value: ScreenSize) => void;
|
||||
}
|
||||
|
||||
export const LargeScreenContext = createContext<ILargeScreenContext | undefined>(undefined);
|
||||
@ -15,7 +18,7 @@ interface LargeScreenProviderProps {
|
||||
|
||||
export const LargeScreenProvider: React.FC<LargeScreenProviderProps> = ({ children }) => {
|
||||
const [windowWidth, setWindowWidth] = useState<number>(Dimensions.get('window').width);
|
||||
const screenWidth: number = useMemo(() => Dimensions.get('screen').width, []);
|
||||
const [largeScreenValue, setLargeScreenValue] = useState<ScreenSize>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const updateScreenUsage = (): void => {
|
||||
@ -30,13 +33,23 @@ export const LargeScreenProvider: React.FC<LargeScreenProviderProps> = ({ childr
|
||||
}, [windowWidth]);
|
||||
|
||||
const isLargeScreen: boolean = useMemo(() => {
|
||||
if (largeScreenValue === 'LargeScreen') {
|
||||
return true;
|
||||
} else if (largeScreenValue === 'Handheld') {
|
||||
return false;
|
||||
}
|
||||
const screenWidth: number = Dimensions.get('screen').width;
|
||||
const halfScreenWidth = windowWidth >= screenWidth / 2;
|
||||
const condition = (isTablet && halfScreenWidth) || isDesktop;
|
||||
console.debug(
|
||||
`LargeScreenProvider.isLargeScreen: width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTablet}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`,
|
||||
);
|
||||
return condition;
|
||||
}, [windowWidth, screenWidth]);
|
||||
return (isTablet && halfScreenWidth) || isDesktop;
|
||||
}, [windowWidth, largeScreenValue]);
|
||||
|
||||
return <LargeScreenContext.Provider value={{ isLargeScreen }}>{children}</LargeScreenContext.Provider>;
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
isLargeScreen,
|
||||
setLargeScreenValue,
|
||||
}),
|
||||
[isLargeScreen, setLargeScreenValue],
|
||||
);
|
||||
|
||||
return <LargeScreenContext.Provider value={contextValue}>{children}</LargeScreenContext.Provider>;
|
||||
};
|
||||
|
187
components/DevMenu.tsx
Normal file
187
components/DevMenu.tsx
Normal file
@ -0,0 +1,187 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { DevSettings, Alert, Platform, AlertButton } from 'react-native';
|
||||
import { useStorage } from '../hooks/context/useStorage';
|
||||
import { HDSegwitBech32Wallet } from '../class';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import { useIsLargeScreen } from '../hooks/useIsLargeScreen';
|
||||
import { TWallet } from '../class/wallets/types';
|
||||
|
||||
const getRandomLabelFromSecret = (secret: string): string => {
|
||||
const words = secret.split(' ');
|
||||
const firstWord = words[0];
|
||||
const lastWord = words[words.length - 1];
|
||||
return `[Developer] ${firstWord} ${lastWord}`;
|
||||
};
|
||||
|
||||
const showAlertWithWalletOptions = (
|
||||
wallets: TWallet[],
|
||||
title: string,
|
||||
message: string,
|
||||
onWalletSelected: (wallet: TWallet) => void,
|
||||
filterFn?: (wallet: TWallet) => boolean,
|
||||
) => {
|
||||
const filteredWallets = filterFn ? wallets.filter(filterFn) : wallets;
|
||||
|
||||
const showWallet = (index: number) => {
|
||||
if (index >= filteredWallets.length) return;
|
||||
const wallet = filteredWallets[index];
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
// Android: Use a limited number of buttons since the alert dialog has a limit
|
||||
Alert.alert(
|
||||
`${title}: ${wallet.getLabel()}`,
|
||||
`${message}\n\nSelected Wallet: ${wallet.getLabel()}\n\nWould you like to select this wallet or see the next one?`,
|
||||
[
|
||||
{
|
||||
text: 'Select This Wallet',
|
||||
onPress: () => onWalletSelected(wallet),
|
||||
},
|
||||
{
|
||||
text: 'Show Next Wallet',
|
||||
onPress: () => showWallet(index + 1),
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
style: 'cancel',
|
||||
},
|
||||
],
|
||||
{ cancelable: true },
|
||||
);
|
||||
} else {
|
||||
const options: AlertButton[] = filteredWallets.map(w => ({
|
||||
text: w.getLabel(),
|
||||
onPress: () => onWalletSelected(w),
|
||||
}));
|
||||
|
||||
options.push({
|
||||
text: 'Cancel',
|
||||
style: 'cancel',
|
||||
});
|
||||
|
||||
Alert.alert(title, message, options, { cancelable: true });
|
||||
}
|
||||
};
|
||||
|
||||
if (filteredWallets.length > 0) {
|
||||
showWallet(0);
|
||||
} else {
|
||||
Alert.alert('No wallets available');
|
||||
}
|
||||
};
|
||||
|
||||
const DevMenu: React.FC = () => {
|
||||
const { wallets, addWallet } = useStorage();
|
||||
const { setLargeScreenValue } = useIsLargeScreen();
|
||||
|
||||
useEffect(() => {
|
||||
if (__DEV__) {
|
||||
// Clear existing Dev Menu items to prevent duplication
|
||||
DevSettings.addMenuItem('Reset Dev Menu', () => {
|
||||
DevSettings.reload();
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Add New Wallet', async () => {
|
||||
const wallet = new HDSegwitBech32Wallet();
|
||||
await wallet.generate();
|
||||
const label = getRandomLabelFromSecret(wallet.getSecret());
|
||||
wallet.setLabel(label);
|
||||
addWallet(wallet);
|
||||
|
||||
Clipboard.setString(wallet.getSecret());
|
||||
Alert.alert('New Wallet created!', `Wallet secret copied to clipboard.\nLabel: ${label}`);
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Copy Wallet Secret', () => {
|
||||
if (wallets.length === 0) {
|
||||
Alert.alert('No wallets available');
|
||||
return;
|
||||
}
|
||||
|
||||
showAlertWithWalletOptions(wallets, 'Copy Wallet Secret', 'Select the wallet to copy the secret', wallet => {
|
||||
Clipboard.setString(wallet.getSecret());
|
||||
Alert.alert('Wallet Secret copied to clipboard!');
|
||||
});
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Copy Wallet ID', () => {
|
||||
if (wallets.length === 0) {
|
||||
Alert.alert('No wallets available');
|
||||
return;
|
||||
}
|
||||
|
||||
showAlertWithWalletOptions(wallets, 'Copy Wallet ID', 'Select the wallet to copy the ID', wallet => {
|
||||
Clipboard.setString(wallet.getID());
|
||||
Alert.alert('Wallet ID copied to clipboard!');
|
||||
});
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Copy Wallet Xpub', () => {
|
||||
if (wallets.length === 0) {
|
||||
Alert.alert('No wallets available');
|
||||
return;
|
||||
}
|
||||
|
||||
showAlertWithWalletOptions(
|
||||
wallets,
|
||||
'Copy Wallet Xpub',
|
||||
'Select the wallet to copy the Xpub',
|
||||
wallet => {
|
||||
const xpub = wallet.getXpub();
|
||||
if (xpub) {
|
||||
Clipboard.setString(xpub);
|
||||
Alert.alert('Wallet Xpub copied to clipboard!');
|
||||
} else {
|
||||
Alert.alert('This wallet does not have an Xpub.');
|
||||
}
|
||||
},
|
||||
wallet => typeof wallet.getXpub === 'function',
|
||||
);
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Purge Wallet Transactions', () => {
|
||||
if (wallets.length === 0) {
|
||||
Alert.alert('No wallets available');
|
||||
return;
|
||||
}
|
||||
|
||||
showAlertWithWalletOptions(wallets, 'Purge Wallet Transactions', 'Select the wallet to purge transactions', wallet => {
|
||||
const msg = 'Transactions purged successfully!';
|
||||
|
||||
if (wallet.type === HDSegwitBech32Wallet.type) {
|
||||
wallet._txs_by_external_index = {};
|
||||
wallet._txs_by_internal_index = {};
|
||||
}
|
||||
|
||||
// @ts-ignore: Property '_hdWalletInstance' does not exist on type 'Wallet'. Pls help
|
||||
if (wallet._hdWalletInstance) {
|
||||
// @ts-ignore: Property '_hdWalletInstance' does not exist on type 'Wallet'. Pls help
|
||||
wallet._hdWalletInstance._txs_by_external_index = {};
|
||||
// @ts-ignore: Property '_hdWalletInstance' does not exist on type 'Wallet'. Pls help
|
||||
wallet._hdWalletInstance._txs_by_internal_index = {};
|
||||
}
|
||||
|
||||
Alert.alert(msg);
|
||||
});
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Force Large Screen Interface', () => {
|
||||
setLargeScreenValue('LargeScreen');
|
||||
Alert.alert('Large Screen Interface forced.');
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Force Handheld Interface', () => {
|
||||
setLargeScreenValue('Handheld');
|
||||
Alert.alert('Handheld Interface forced.');
|
||||
});
|
||||
|
||||
DevSettings.addMenuItem('Reset Screen Interface', () => {
|
||||
setLargeScreenValue(undefined);
|
||||
Alert.alert('Screen Interface reset to default.');
|
||||
});
|
||||
}
|
||||
}, [wallets, addWallet, setLargeScreenValue]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default DevMenu;
|
@ -61,7 +61,7 @@ const NewWalletPanel: React.FC<NewWalletPanelProps> = ({ onPress }) => {
|
||||
const { colors } = useTheme();
|
||||
const { width } = useWindowDimensions();
|
||||
const itemWidth = width * 0.82 > 375 ? 375 : width * 0.82;
|
||||
const isLargeScreen = useIsLargeScreen();
|
||||
const { isLargeScreen } = useIsLargeScreen();
|
||||
const nStylesHooks = StyleSheet.create({
|
||||
container: isLargeScreen
|
||||
? {
|
||||
@ -192,7 +192,7 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
||||
const { walletTransactionUpdateStatus } = useStorage();
|
||||
const { width } = useWindowDimensions();
|
||||
const itemWidth = width * 0.82 > 375 ? 375 : width * 0.82;
|
||||
const isLargeScreen = useIsLargeScreen();
|
||||
const { isLargeScreen } = useIsLargeScreen();
|
||||
|
||||
const onPressedIn = useCallback(() => {
|
||||
if (animationsEnabled) {
|
||||
|
@ -1,10 +1,18 @@
|
||||
import { useContext } from 'react';
|
||||
import { LargeScreenContext } from '../components/Context/LargeScreenProvider';
|
||||
|
||||
export const useIsLargeScreen = (): boolean => {
|
||||
interface UseIsLargeScreenResult {
|
||||
isLargeScreen: boolean;
|
||||
setLargeScreenValue: (value: 'Handheld' | 'LargeScreen' | undefined) => void;
|
||||
}
|
||||
|
||||
export const useIsLargeScreen = (): UseIsLargeScreenResult => {
|
||||
const context = useContext(LargeScreenContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useIsLargeScreen must be used within a LargeScreenProvider');
|
||||
}
|
||||
return context.isLargeScreen;
|
||||
};
|
||||
return {
|
||||
isLargeScreen: context.isLargeScreen,
|
||||
setLargeScreenValue: context.setLargeScreenValue,
|
||||
};
|
||||
};
|
@ -14,7 +14,7 @@ const DrawerListContent = (props: any) => {
|
||||
};
|
||||
|
||||
const DrawerRoot = () => {
|
||||
const isLargeScreen = useIsLargeScreen();
|
||||
const { isLargeScreen } = useIsLargeScreen();
|
||||
|
||||
const drawerStyle: DrawerNavigationOptions = useMemo(
|
||||
() => ({
|
||||
|
@ -3,6 +3,7 @@ import 'react-native-gesture-handler'; // should be on top
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import MainRoot from '../navigation';
|
||||
import { useStorage } from '../hooks/context/useStorage';
|
||||
import DevMenu from '../components/DevMenu';
|
||||
const CompanionDelegates = lazy(() => import('../components/CompanionDelegates'));
|
||||
|
||||
const MasterView = () => {
|
||||
@ -16,6 +17,7 @@ const MasterView = () => {
|
||||
<CompanionDelegates />
|
||||
</Suspense>
|
||||
)}
|
||||
{__DEV__ && <DevMenu />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -95,7 +95,7 @@ type RouteProps = RouteProp<DetailViewStackParamList, 'WalletsList'>;
|
||||
const WalletsList: React.FC = () => {
|
||||
const [state, dispatch] = useReducer<React.Reducer<WalletListState, WalletListAction>>(reducer, initialState);
|
||||
const { isLoading } = state;
|
||||
const isLargeScreen = useIsLargeScreen();
|
||||
const { isLargeScreen } = useIsLargeScreen();
|
||||
const walletsCarousel = useRef<any>();
|
||||
const currentWalletIndex = useRef<number>(0);
|
||||
const {
|
||||
|
Loading…
Reference in New Issue
Block a user