Merge pull request #7248 from BlueWallet/set

REF: SettingsProvider
This commit is contained in:
GLaDOS 2024-11-01 04:56:24 +00:00 committed by GitHub
commit 4fe4970a02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 311 additions and 392 deletions

View File

@ -22,4 +22,20 @@ const triggerHapticFeedback = (type: HapticFeedbackTypes) => {
});
};
export const triggerSuccessHapticFeedback = () => {
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
};
export const triggerWarningHapticFeedback = () => {
triggerHapticFeedback(HapticFeedbackTypes.NotificationWarning);
};
export const triggerErrorHapticFeedback = () => {
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
};
export const triggerSelectionHapticFeedback = () => {
triggerHapticFeedback(HapticFeedbackTypes.Selection);
};
export default triggerHapticFeedback;

View File

@ -2,69 +2,76 @@ import { useAsyncStorage } from '@react-native-async-storage/async-storage';
import React, { createContext, useCallback, useEffect, useMemo, useState } from 'react';
import DefaultPreference from 'react-native-default-preference';
import BlueClipboard from '../../blue_modules/clipboard';
import { getPreferredCurrency, GROUP_IO_BLUEWALLET, initCurrencyDaemon } from '../../blue_modules/currency';
import { getPreferredCurrency, GROUP_IO_BLUEWALLET, initCurrencyDaemon, PREFERRED_CURRENCY_STORAGE_KEY } from '../../blue_modules/currency';
import { clearUseURv1, isURv1Enabled, setUseURv1 } from '../../blue_modules/ur';
import { BlueApp } from '../../class';
import { saveLanguage, STORAGE_KEY } from '../../loc';
import { FiatUnit, TFiatUnit } from '../../models/fiatUnit';
import { getEnabled as getIsDeviceQuickActionsEnabled, setEnabled as setIsDeviceQuickActionsEnabled } from '..//DeviceQuickActions';
import { getEnabled as getIsDeviceQuickActionsEnabled, setEnabled as setIsDeviceQuickActionsEnabled } from '../DeviceQuickActions';
import { getIsHandOffUseEnabled, setIsHandOffUseEnabled } from '../HandOffComponent';
import { isBalanceDisplayAllowed, setBalanceDisplayAllowed } from '../WidgetCommunication';
import { useStorage } from '../../hooks/context/useStorage';
import { BitcoinUnit } from '../../models/bitcoinUnits';
import { TotalWalletsBalanceKey, TotalWalletsBalancePreferredUnit } from '../TotalWalletsBalance';
import { LayoutAnimation } from 'react-native';
import { BLOCK_EXPLORERS, getBlockExplorerUrl, saveBlockExplorer, BlockExplorer, normalizeUrl } from '../../models/blockExplorer';
// DefaultPreference and AsyncStorage get/set
const getDoNotTrackStorage = async (): Promise<boolean> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
const doNotTrack = await DefaultPreference.get(BlueApp.DO_NOT_TRACK);
return doNotTrack === '1';
} catch {
console.error('Error getting DoNotTrack');
return false;
}
};
// TotalWalletsBalance
export const setTotalBalanceViewEnabled = async (value: boolean) => {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
await DefaultPreference.set(TotalWalletsBalanceKey, value ? 'true' : 'false');
console.debug('setTotalBalanceViewEnabled value:', value);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
export const setTotalBalanceViewEnabledStorage = async (value: boolean): Promise<void> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
await DefaultPreference.set(TotalWalletsBalanceKey, value ? 'true' : 'false');
console.debug('setTotalBalanceViewEnabledStorage value:', value);
} catch (e) {
console.error('Error setting TotalBalanceViewEnabled:', e);
}
};
export const getIsTotalBalanceViewEnabled = async (): Promise<boolean> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
const isEnabledValue = (await DefaultPreference.get(TotalWalletsBalanceKey)) ?? 'true';
console.debug('getIsTotalBalanceViewEnabled', isEnabledValue);
return isEnabledValue === 'true';
} catch (e) {
console.debug('getIsTotalBalanceViewEnabled error', e);
await setTotalBalanceViewEnabled(true);
console.error('Error getting TotalBalanceViewEnabled:', e);
return true;
}
await setTotalBalanceViewEnabled(true);
return true;
};
export const setTotalBalancePreferredUnit = async (unit: BitcoinUnit) => {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
await DefaultPreference.set(TotalWalletsBalancePreferredUnit, unit);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); // Add animation when changing unit
export const setTotalBalancePreferredUnitStorageFunc = async (unit: BitcoinUnit): Promise<void> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
await DefaultPreference.set(TotalWalletsBalancePreferredUnit, unit);
} catch (e) {
console.error('Error setting TotalBalancePreferredUnit:', e);
}
};
//
export const getTotalBalancePreferredUnit = async (): Promise<BitcoinUnit> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
const unit = ((await DefaultPreference.get(TotalWalletsBalancePreferredUnit)) as BitcoinUnit) ?? BitcoinUnit.BTC;
return unit;
const unit = (await DefaultPreference.get(TotalWalletsBalancePreferredUnit)) as BitcoinUnit | null;
return unit ?? BitcoinUnit.BTC;
} catch (e) {
console.debug('getPreferredUnit error', e);
console.error('Error getting TotalBalancePreferredUnit:', e);
return BitcoinUnit.BTC;
}
return BitcoinUnit.BTC;
};
interface SettingsContextType {
preferredFiatCurrency: TFiatUnit;
setPreferredFiatCurrencyStorage: (currency: TFiatUnit) => Promise<void>;
language: string | undefined;
language: string;
setLanguageStorage: (language: string) => Promise<void>;
isHandOffUseEnabled: boolean;
setIsHandOffUseEnabledAsyncStorage: (value: boolean) => Promise<void>;
@ -103,8 +110,8 @@ const defaultSettingsContext: SettingsContextType = {
setDoNotTrackStorage: async () => {},
isWidgetBalanceDisplayAllowed: true,
setIsWidgetBalanceDisplayAllowedStorage: async () => {},
setIsLegacyURv1EnabledStorage: async () => {},
isLegacyURv1Enabled: false,
setIsLegacyURv1EnabledStorage: async () => {},
isClipboardGetContentEnabled: true,
setIsClipboardGetContentEnabledStorage: async () => {},
isQuickActionsEnabled: true,
@ -112,215 +119,226 @@ const defaultSettingsContext: SettingsContextType = {
isTotalBalanceEnabled: true,
setIsTotalBalanceEnabledStorage: async () => {},
totalBalancePreferredUnit: BitcoinUnit.BTC,
setTotalBalancePreferredUnitStorage: async (unit: BitcoinUnit) => {},
setTotalBalancePreferredUnitStorage: async () => {},
isDrawerShouldHide: false,
setIsDrawerShouldHide: () => {},
selectedBlockExplorer: BLOCK_EXPLORERS.default,
setBlockExplorerStorage: async (explorer: BlockExplorer) => false,
setBlockExplorerStorage: async () => false,
};
export const SettingsContext = createContext<SettingsContextType>(defaultSettingsContext);
export const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
// FiatCurrency
export const SettingsProvider: React.FC<{ children: React.ReactNode }> = React.memo(({ children }) => {
const [preferredFiatCurrency, setPreferredFiatCurrency] = useState<TFiatUnit>(FiatUnit.USD);
// Language
const [language, setLanguage] = useState<string>();
// HandOff
const [isHandOffUseEnabled, setHandOffUseEnabled] = useState<boolean>(false);
// PrivacyBlur
const [language, setLanguage] = useState<string>('en');
const [isHandOffUseEnabled, setIsHandOffUseEnabledState] = useState<boolean>(false);
const [isPrivacyBlurEnabled, setIsPrivacyBlurEnabled] = useState<boolean>(true);
// DoNotTrack
const [isDoNotTrackEnabled, setIsDoNotTrackEnabled] = useState<boolean>(false);
// WidgetCommunication
const [isWidgetBalanceDisplayAllowed, setIsWidgetBalanceDisplayAllowed] = useState<boolean>(true);
// LegacyURv1
const [isLegacyURv1Enabled, setIsLegacyURv1Enabled] = useState<boolean>(false);
// Clipboard
const [isClipboardGetContentEnabled, setIsClipboardGetContentEnabled] = useState<boolean>(false);
// Quick Actions
const [isClipboardGetContentEnabled, setIsClipboardGetContentEnabled] = useState<boolean>(true);
const [isQuickActionsEnabled, setIsQuickActionsEnabled] = useState<boolean>(true);
// Total Balance
const [isTotalBalanceEnabled, setIsTotalBalanceEnabled] = useState<boolean>(true);
const [totalBalancePreferredUnit, setTotalBalancePreferredUnitState] = useState<BitcoinUnit>(BitcoinUnit.BTC);
// Toggle Drawer (for screens like Manage Wallets or ScanQRCode)
const [totalBalancePreferredUnit, setTotalBalancePreferredUnit] = useState<BitcoinUnit>(BitcoinUnit.BTC);
const [isDrawerShouldHide, setIsDrawerShouldHide] = useState<boolean>(false);
const [selectedBlockExplorer, setSelectedBlockExplorer] = useState<BlockExplorer>(BLOCK_EXPLORERS.default);
const languageStorage = useAsyncStorage(STORAGE_KEY);
const { walletsInitialized } = useStorage();
useEffect(() => {
getIsHandOffUseEnabled()
.then(handOff => {
console.debug('SettingsContext handOff:', handOff);
setHandOffUseEnabled(handOff);
})
.catch(error => console.error('Error fetching hand-off usage:', error));
const loadSettings = async () => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
} catch (e) {
console.error('Error setting preference name:', e);
}
languageStorage
.getItem()
.then(lang => {
lang = lang ?? 'en';
console.debug('SettingsContext lang:', lang);
setLanguage(lang);
})
.catch(error => console.error('Error fetching language setting:', error));
const promises: Promise<void>[] = [
getIsHandOffUseEnabled().then(handOff => {
setIsHandOffUseEnabledState(handOff);
}),
languageStorage.getItem().then(lang => {
setLanguage(lang ?? 'en');
}),
isBalanceDisplayAllowed().then(balanceDisplayAllowed => {
setIsWidgetBalanceDisplayAllowed(balanceDisplayAllowed);
}),
isURv1Enabled().then(urv1Enabled => {
setIsLegacyURv1Enabled(urv1Enabled);
}),
BlueClipboard()
.isReadClipboardAllowed()
.then(clipboardEnabled => {
setIsClipboardGetContentEnabled(clipboardEnabled);
}),
getIsDeviceQuickActionsEnabled().then(quickActionsEnabled => {
setIsQuickActionsEnabled(quickActionsEnabled);
}),
getDoNotTrackStorage().then(doNotTrack => {
setIsDoNotTrackEnabled(doNotTrack);
}),
getIsTotalBalanceViewEnabled().then(totalBalanceEnabled => {
setIsTotalBalanceEnabled(totalBalanceEnabled);
}),
getTotalBalancePreferredUnit().then(preferredUnit => {
setTotalBalancePreferredUnit(preferredUnit);
}),
getBlockExplorerUrl().then(url => {
const predefinedExplorer = Object.values(BLOCK_EXPLORERS).find(explorer => normalizeUrl(explorer.url) === normalizeUrl(url));
setSelectedBlockExplorer(predefinedExplorer ?? ({ key: 'custom', name: 'Custom', url } as BlockExplorer));
}),
];
isBalanceDisplayAllowed()
.then(isBalanceDisplayAllowedStorage => {
console.debug('SettingsContext isBalanceDisplayAllowed:', isBalanceDisplayAllowedStorage);
setIsWidgetBalanceDisplayAllowed(isBalanceDisplayAllowedStorage);
})
.catch(error => console.error('Error fetching balance display allowance:', error));
const results = await Promise.allSettled(promises);
isURv1Enabled()
.then(isURv1EnabledStorage => {
console.debug('SettingsContext isURv1Enabled:', isURv1EnabledStorage);
setIsLegacyURv1EnabledStorage(isURv1EnabledStorage);
})
.catch(error => console.error('Error fetching UR v1 enabled status:', error));
BlueClipboard()
.isReadClipboardAllowed()
.then(isClipboardGetContentEnabledStorage => {
console.debug('SettingsContext isClipboardGetContentEnabled:', isClipboardGetContentEnabledStorage);
setIsClipboardGetContentEnabledStorage(isClipboardGetContentEnabledStorage);
})
.catch(error => console.error('Error fetching clipboard content allowance:', error));
getIsDeviceQuickActionsEnabled()
.then(isQuickActionsEnabledStorage => {
console.debug('SettingsContext isQuickActionsEnabled:', isQuickActionsEnabledStorage);
setIsQuickActionsEnabledStorage(isQuickActionsEnabledStorage);
})
.catch(error => console.error('Error fetching device quick actions enabled status:', error));
getDoNotTrackStorage()
.then(value => {
console.debug('SettingsContext doNotTrack:', value);
setDoNotTrackStorage(value ?? false);
})
.catch(error => console.error('Error fetching do not track settings:', error));
getIsTotalBalanceViewEnabled()
.then(value => {
console.debug('SettingsContext totalBalance:', value);
setIsTotalBalanceEnabledStorage(value);
})
.catch(error => console.error('Error fetching total balance settings:', error));
getTotalBalancePreferredUnit()
.then(unit => {
console.debug('SettingsContext totalBalancePreferredUnit:', unit);
setTotalBalancePreferredUnitState(unit);
})
.catch(error => console.error('Error fetching total balance preferred unit:', error));
getBlockExplorerUrl()
.then(url => {
console.debug('SettingsContext blockExplorer:', url);
const predefinedExplorer = Object.values(BLOCK_EXPLORERS).find(explorer => normalizeUrl(explorer.url) === normalizeUrl(url));
if (predefinedExplorer) {
setSelectedBlockExplorer(predefinedExplorer);
} else {
setSelectedBlockExplorer({ key: 'custom', name: 'Custom', url });
results.forEach((result, index) => {
if (result.status === 'rejected') {
console.error(`Error loading setting ${index}:`, result.reason);
}
})
.catch(error => console.error('Error fetching block explorer settings:', error));
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
loadSettings();
}, [languageStorage]);
useEffect(() => {
if (walletsInitialized) {
initCurrencyDaemon().finally(() => {
getPreferredCurrency().then(currency => {
initCurrencyDaemon()
.then(getPreferredCurrency)
.then(currency => {
console.debug('SettingsContext currency:', currency);
setPreferredFiatCurrency(FiatUnit[currency.endPointKey]);
setPreferredFiatCurrency(currency as TFiatUnit);
})
.catch(e => {
console.error('Error initializing currency daemon or getting preferred currency:', e);
});
});
}
}, [walletsInitialized]);
const setPreferredFiatCurrencyStorage = useCallback(async (currency: TFiatUnit) => {
await setPreferredFiatCurrency(currency);
setPreferredFiatCurrency(currency);
}, []);
const setLanguageStorage = useCallback(async (newLanguage: string) => {
await saveLanguage(newLanguage);
setLanguage(newLanguage);
}, []);
const setDoNotTrackStorage = useCallback(async (value: boolean) => {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
if (value) {
await DefaultPreference.set(BlueApp.DO_NOT_TRACK, '1');
} else {
await DefaultPreference.clear(BlueApp.DO_NOT_TRACK);
const setPreferredFiatCurrencyStorage = useCallback(async (currency: TFiatUnit): Promise<void> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
await DefaultPreference.set(PREFERRED_CURRENCY_STORAGE_KEY, currency.endPointKey);
setPreferredFiatCurrency(currency);
} catch (e) {
console.error('Error setting preferredFiatCurrency:', e);
}
setIsDoNotTrackEnabled(value);
}, []);
const getDoNotTrackStorage = useCallback(async () => {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
const doNotTrack = await DefaultPreference.get(BlueApp.DO_NOT_TRACK);
return doNotTrack === '1';
const setLanguageStorage = useCallback(async (newLanguage: string): Promise<void> => {
try {
await saveLanguage(newLanguage);
setLanguage(newLanguage);
} catch (e) {
console.error('Error setting language:', e);
}
}, []);
const setIsHandOffUseEnabledAsyncStorage = useCallback(async (value: boolean) => {
console.debug('setIsHandOffUseEnabledAsyncStorage', value);
await setIsHandOffUseEnabled(value);
setHandOffUseEnabled(value);
const setDoNotTrackStorage = useCallback(async (value: boolean): Promise<void> => {
try {
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
if (value) {
await DefaultPreference.set(BlueApp.DO_NOT_TRACK, '1');
} else {
await DefaultPreference.clear(BlueApp.DO_NOT_TRACK);
}
setIsDoNotTrackEnabled(value);
} catch (e) {
console.error('Error setting DoNotTrack:', e);
}
}, []);
const setIsWidgetBalanceDisplayAllowedStorage = useCallback(async (value: boolean) => {
await setBalanceDisplayAllowed(value);
setIsWidgetBalanceDisplayAllowed(value);
const setIsHandOffUseEnabledAsyncStorage = useCallback(async (value: boolean): Promise<void> => {
try {
console.debug('setIsHandOffUseEnabledAsyncStorage', value);
await setIsHandOffUseEnabled(value);
setIsHandOffUseEnabledState(value);
} catch (e) {
console.error('Error setting isHandOffUseEnabled:', e);
}
}, []);
const setIsLegacyURv1EnabledStorage = useCallback(async (value: boolean) => {
value ? await setUseURv1() : await clearUseURv1();
await setIsLegacyURv1Enabled(value);
const setIsWidgetBalanceDisplayAllowedStorage = useCallback(async (value: boolean): Promise<void> => {
try {
await setBalanceDisplayAllowed(value);
setIsWidgetBalanceDisplayAllowed(value);
} catch (e) {
console.error('Error setting isWidgetBalanceDisplayAllowed:', e);
}
}, []);
const setIsClipboardGetContentEnabledStorage = useCallback(async (value: boolean) => {
await BlueClipboard().setReadClipboardAllowed(value);
setIsClipboardGetContentEnabled(value);
const setIsLegacyURv1EnabledStorage = useCallback(async (value: boolean): Promise<void> => {
try {
if (value) {
await setUseURv1();
} else {
await clearUseURv1();
}
setIsLegacyURv1Enabled(value);
} catch (e) {
console.error('Error setting isLegacyURv1Enabled:', e);
}
}, []);
const setIsQuickActionsEnabledStorage = useCallback(async (value: boolean) => {
await setIsDeviceQuickActionsEnabled(value);
setIsQuickActionsEnabled(value);
const setIsClipboardGetContentEnabledStorage = useCallback(async (value: boolean): Promise<void> => {
try {
await BlueClipboard().setReadClipboardAllowed(value);
setIsClipboardGetContentEnabled(value);
} catch (e) {
console.error('Error setting isClipboardGetContentEnabled:', e);
}
}, []);
const setIsPrivacyBlurEnabledState = useCallback(
(value: boolean) => {
const setIsQuickActionsEnabledStorage = useCallback(async (value: boolean): Promise<void> => {
try {
await setIsDeviceQuickActionsEnabled(value);
setIsQuickActionsEnabled(value);
} catch (e) {
console.error('Error setting isQuickActionsEnabled:', e);
}
}, []);
const setIsPrivacyBlurEnabledState = useCallback((value: boolean): void => {
try {
setIsPrivacyBlurEnabled(value);
console.debug(`Privacy blur: ${isPrivacyBlurEnabled}`);
},
[isPrivacyBlurEnabled],
);
const setIsTotalBalanceEnabledStorage = useCallback(async (value: boolean) => {
setTotalBalanceViewEnabled(value);
setIsTotalBalanceEnabled(value);
console.debug(`Privacy blur: ${value}`);
} catch (e) {
console.error('Error setting isPrivacyBlurEnabled:', e);
}
}, []);
const setTotalBalancePreferredUnitStorage = useCallback(async (unit: BitcoinUnit) => {
await setTotalBalancePreferredUnit(unit);
setTotalBalancePreferredUnitState(unit);
const setIsTotalBalanceEnabledStorage = useCallback(async (value: boolean): Promise<void> => {
try {
await setTotalBalanceViewEnabledStorage(value);
setIsTotalBalanceEnabled(value);
} catch (e) {
console.error('Error setting isTotalBalanceEnabled:', e);
}
}, []);
const setTotalBalancePreferredUnitStorage = useCallback(async (unit: BitcoinUnit): Promise<void> => {
try {
await setTotalBalancePreferredUnitStorageFunc(unit);
setTotalBalancePreferredUnit(unit);
} catch (e) {
console.error('Error setting totalBalancePreferredUnit:', e);
}
}, []);
const setBlockExplorerStorage = useCallback(async (explorer: BlockExplorer): Promise<boolean> => {
const success = await saveBlockExplorer(explorer.url);
if (success) {
setSelectedBlockExplorer(explorer);
try {
const success = await saveBlockExplorer(explorer.url);
if (success) {
setSelectedBlockExplorer(explorer);
}
return success;
} catch (e) {
console.error('Error setting BlockExplorer:', e);
return false;
}
return success;
}, []);
const value = useMemo(
() => ({
preferredFiatCurrency,
@ -381,4 +399,4 @@ export const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({ chil
);
return <SettingsContext.Provider value={value}>{children}</SettingsContext.Provider>;
};
});

View File

@ -11,7 +11,7 @@ const HandOffComponent: React.FC<HandOffComponentProps> = props => {
const { isHandOffUseEnabled } = useSettings();
if (process.env.NODE_ENV === 'development') {
console.debug('HandOffComponent: props', props);
console.debug('HandOffComponent: render');
}
if (isHandOffUseEnabled) {
return <Handoff {...props} />;
@ -35,8 +35,8 @@ export const getIsHandOffUseEnabled = async (): Promise<boolean> => {
return isEnabledValue === 'true';
} catch (e) {
console.debug('getIsHandOffUseEnabled error', e);
return false;
}
return false;
};
export default MemoizedHandOffComponent;

View File

@ -2,7 +2,7 @@ import React from 'react';
import { HandOffComponentProps } from './types';
const HandOffComponent: React.FC<HandOffComponentProps> = props => {
console.debug('HandOffComponent: props', props);
console.debug('HandOffComponent render.');
return null;
};

View File

@ -12,10 +12,15 @@ import { useTheme } from './themes';
export const TotalWalletsBalancePreferredUnit = 'TotalWalletsBalancePreferredUnit';
export const TotalWalletsBalanceKey = 'TotalWalletsBalance';
const TotalWalletsBalance: React.FC = () => {
const TotalWalletsBalance: React.FC = React.memo(() => {
const { wallets } = useStorage();
const { preferredFiatCurrency, setIsTotalBalanceEnabledStorage, totalBalancePreferredUnit, setTotalBalancePreferredUnitStorage } =
useSettings();
const {
preferredFiatCurrency,
isTotalBalanceEnabled,
setIsTotalBalanceEnabledStorage,
totalBalancePreferredUnit,
setTotalBalancePreferredUnitStorage,
} = useSettings();
const { colors } = useTheme();
const styleHooks = useMemo(
@ -26,13 +31,19 @@ const TotalWalletsBalance: React.FC = () => {
[colors.foregroundColor],
);
const totalBalance = useMemo(() => wallets.reduce((prev, curr) => (!curr.hideBalance ? prev + curr.getBalance() : prev), 0), [wallets]);
const totalBalance = useMemo(() => {
return wallets.reduce((prev, curr) => {
if (!curr.hideBalance) {
const balance = curr.getBalance();
return prev + (typeof balance === 'number' ? balance : 0);
}
return prev;
}, 0);
}, [wallets]);
const formattedBalance = useMemo(
() => formatBalanceWithoutSuffix(totalBalance, totalBalancePreferredUnit, true),
// eslint-disable-next-line react-hooks/exhaustive-deps
[totalBalance, totalBalancePreferredUnit, preferredFiatCurrency],
);
const formattedBalance = useMemo(() => {
return formatBalanceWithoutSuffix(totalBalance, totalBalancePreferredUnit, true);
}, [totalBalance, totalBalancePreferredUnit]);
const toolTipActions = useMemo(() => {
const viewInFiat = {
@ -59,21 +70,29 @@ const TotalWalletsBalance: React.FC = () => {
};
return [viewInActions, CommonToolTipActions.CopyAmount, CommonToolTipActions.HideBalance];
}, [preferredFiatCurrency.endPointKey, totalBalancePreferredUnit]);
}, [preferredFiatCurrency, totalBalancePreferredUnit]);
const onPressMenuItem = useCallback(
async (id: string) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (id === CommonToolTipActions.ViewInFiat.id) {
await setTotalBalancePreferredUnitStorage(BitcoinUnit.LOCAL_CURRENCY);
} else if (id === CommonToolTipActions.ViewInSats.id) {
await setTotalBalancePreferredUnitStorage(BitcoinUnit.SATS);
} else if (id === CommonToolTipActions.ViewInBitcoin.id) {
await setTotalBalancePreferredUnitStorage(BitcoinUnit.BTC);
} else if (id === CommonToolTipActions.HideBalance.id) {
setIsTotalBalanceEnabledStorage(false);
} else if (id === CommonToolTipActions.CopyAmount.id) {
Clipboard.setString(formattedBalance.toString());
switch (id) {
case CommonToolTipActions.ViewInFiat.id:
await setTotalBalancePreferredUnitStorage(BitcoinUnit.LOCAL_CURRENCY);
break;
case CommonToolTipActions.ViewInSats.id:
await setTotalBalancePreferredUnitStorage(BitcoinUnit.SATS);
break;
case CommonToolTipActions.ViewInBitcoin.id:
await setTotalBalancePreferredUnitStorage(BitcoinUnit.BTC);
break;
case CommonToolTipActions.HideBalance.id:
await setIsTotalBalanceEnabledStorage(false);
break;
case CommonToolTipActions.CopyAmount.id:
Clipboard.setString(formattedBalance.toString());
break;
default:
break;
}
},
[setIsTotalBalanceEnabledStorage, formattedBalance, setTotalBalancePreferredUnitStorage],
@ -81,16 +100,22 @@ const TotalWalletsBalance: React.FC = () => {
const handleBalanceOnPress = useCallback(async () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
const nextUnit =
totalBalancePreferredUnit === BitcoinUnit.BTC
? BitcoinUnit.SATS
: totalBalancePreferredUnit === BitcoinUnit.SATS
? BitcoinUnit.LOCAL_CURRENCY
: BitcoinUnit.BTC;
let nextUnit: BitcoinUnit;
switch (totalBalancePreferredUnit) {
case BitcoinUnit.BTC:
nextUnit = BitcoinUnit.SATS;
break;
case BitcoinUnit.SATS:
nextUnit = BitcoinUnit.LOCAL_CURRENCY;
break;
default:
nextUnit = BitcoinUnit.BTC;
}
await setTotalBalancePreferredUnitStorage(nextUnit);
}, [totalBalancePreferredUnit, setTotalBalancePreferredUnitStorage]);
if (wallets.length <= 1) return null;
// If there's only one wallet or total balance view is disabled, don't render
if (wallets.length <= 1 || !isTotalBalanceEnabled) return null;
return (
<ToolTipMenu actions={toolTipActions} onPressMenuItem={onPressMenuItem}>
@ -107,7 +132,7 @@ const TotalWalletsBalance: React.FC = () => {
</View>
</ToolTipMenu>
);
};
});
const styles = StyleSheet.create({
container: {

View File

@ -29,26 +29,6 @@ import WalletsList from '../screen/wallets/WalletsList';
import { NavigationDefaultOptions, NavigationFormModalOptions, StatusBarLightOptions, DetailViewStack } from './index'; // Importing the navigator
import AddWalletStack from './AddWalletStack';
import AztecoRedeemStackRoot from './AztecoRedeemStack';
import {
AboutComponent,
BlockExplorerSettingsComponent,
CurrencyComponent,
DefaultViewComponent,
ElectrumSettingsComponent,
EncryptStorageComponent,
GeneralSettingsComponent,
LanguageComponent,
LicensingComponent,
LightningSettingsComponent,
NetworkSettingsComponent,
NotificationSettingsComponent,
PlausibleDeniabilityComponent,
ReleaseNotesComponent,
SelfTestComponent,
SettingsComponent,
SettingsPrivacyComponent,
ToolsComponent,
} from './LazyLoadSettingsStack';
import PaymentCodesListComponent from './LazyLoadPaymentCodeStack';
import LNDCreateInvoiceRoot from './LNDCreateInvoiceStack';
import ReceiveDetailsStackRoot from './ReceiveDetailsStack';
@ -67,6 +47,24 @@ import { useSettings } from '../hooks/context/useSettings';
import { useStorage } from '../hooks/context/useStorage';
import WalletTransactions from '../screen/wallets/WalletTransactions';
import AddWalletButton from '../components/AddWalletButton';
import Settings from '../screen/settings/Settings';
import Currency from '../screen/settings/Currency';
import GeneralSettings from '../screen/settings/GeneralSettings';
import PlausibleDeniability from '../screen/PlausibleDeniability';
import Licensing from '../screen/settings/Licensing';
import NetworkSettings from '../screen/settings/NetworkSettings';
import SettingsBlockExplorer from '../screen/settings/SettingsBlockExplorer';
import About from '../screen/settings/About';
import DefaultView from '../screen/settings/DefaultView';
import ElectrumSettings from '../screen/settings/ElectrumSettings';
import EncryptStorage from '../screen/settings/EncryptStorage';
import Language from '../screen/settings/Language';
import LightningSettings from '../screen/settings/LightningSettings';
import NotificationSettings from '../screen/settings/NotificationSettings';
import SelfTest from '../screen/settings/SelfTest';
import ReleaseNotes from '../screen/settings/ReleaseNotes';
import ToolsScreen from '../screen/settings/tools';
import SettingsPrivacy from '../screen/settings/SettingsPrivacy';
const DetailViewStackScreensStack = () => {
const theme = useTheme();
@ -268,7 +266,7 @@ const DetailViewStackScreensStack = () => {
/>
<DetailViewStack.Screen
name="Settings"
component={SettingsComponent}
component={Settings}
options={navigationStyle({
headerTransparent: true,
title: loc.settings.header,
@ -280,83 +278,67 @@ const DetailViewStackScreensStack = () => {
animationTypeForReplace: 'push',
})(theme)}
/>
<DetailViewStack.Screen
name="Currency"
component={CurrencyComponent}
options={navigationStyle({ title: loc.settings.currency })(theme)}
/>
<DetailViewStack.Screen name="Currency" component={Currency} options={navigationStyle({ title: loc.settings.currency })(theme)} />
<DetailViewStack.Screen
name="GeneralSettings"
component={GeneralSettingsComponent}
component={GeneralSettings}
options={navigationStyle({ title: loc.settings.general })(theme)}
/>
<DetailViewStack.Screen
name="PlausibleDeniability"
component={PlausibleDeniabilityComponent}
component={PlausibleDeniability}
options={navigationStyle({ title: loc.plausibledeniability.title })(theme)}
/>
<DetailViewStack.Screen
name="Licensing"
component={LicensingComponent}
options={navigationStyle({ title: loc.settings.license })(theme)}
/>
<DetailViewStack.Screen name="Licensing" component={Licensing} options={navigationStyle({ title: loc.settings.license })(theme)} />
<DetailViewStack.Screen
name="NetworkSettings"
component={NetworkSettingsComponent}
component={NetworkSettings}
options={navigationStyle({ title: loc.settings.network })(theme)}
/>
<DetailViewStack.Screen
name="SettingsBlockExplorer"
component={BlockExplorerSettingsComponent}
component={SettingsBlockExplorer}
options={navigationStyle({ title: loc.settings.block_explorer })(theme)}
/>
<DetailViewStack.Screen name="About" component={AboutComponent} options={navigationStyle({ title: loc.settings.about })(theme)} />
<DetailViewStack.Screen name="About" component={About} options={navigationStyle({ title: loc.settings.about })(theme)} />
<DetailViewStack.Screen
name="DefaultView"
component={DefaultViewComponent}
component={DefaultView}
options={navigationStyle({ title: loc.settings.default_title })(theme)}
/>
<DetailViewStack.Screen
name="ElectrumSettings"
component={ElectrumSettingsComponent}
component={ElectrumSettings}
options={navigationStyle({ title: loc.settings.electrum_settings_server })(theme)}
initialParams={{ server: undefined }}
/>
<DetailViewStack.Screen
name="EncryptStorage"
component={EncryptStorageComponent}
component={EncryptStorage}
options={navigationStyle({ title: loc.settings.encrypt_title })(theme)}
/>
<DetailViewStack.Screen
name="Language"
component={LanguageComponent}
options={navigationStyle({ title: loc.settings.language })(theme)}
/>
<DetailViewStack.Screen name="Language" component={Language} options={navigationStyle({ title: loc.settings.language })(theme)} />
<DetailViewStack.Screen
name="LightningSettings"
component={LightningSettingsComponent}
component={LightningSettings}
options={navigationStyle({ title: loc.settings.lightning_settings })(theme)}
/>
<DetailViewStack.Screen
name="NotificationSettings"
component={NotificationSettingsComponent}
component={NotificationSettings}
options={navigationStyle({ title: loc.settings.notifications })(theme)}
/>
<DetailViewStack.Screen
name="SelfTest"
component={SelfTestComponent}
options={navigationStyle({ title: loc.settings.selfTest })(theme)}
/>
<DetailViewStack.Screen name="SelfTest" component={SelfTest} options={navigationStyle({ title: loc.settings.selfTest })(theme)} />
<DetailViewStack.Screen
name="ReleaseNotes"
component={ReleaseNotesComponent}
component={ReleaseNotes}
options={navigationStyle({ title: loc.settings.about_release_notes })(theme)}
/>
<DetailViewStack.Screen name="Tools" component={ToolsComponent} options={navigationStyle({ title: loc.settings.tools })(theme)} />
<DetailViewStack.Screen name="ToolsScreen" component={ToolsScreen} options={navigationStyle({ title: loc.settings.tools })(theme)} />
<DetailViewStack.Screen
name="SettingsPrivacy"
component={SettingsPrivacyComponent}
component={SettingsPrivacy}
options={navigationStyle({ title: loc.settings.privacy })(theme)}
/>
<DetailViewStack.Screen

View File

@ -64,7 +64,7 @@ export type DetailViewStackParamList = {
NotificationSettings: undefined;
SelfTest: undefined;
ReleaseNotes: undefined;
Tools: undefined;
ToolsScreen: undefined;
SettingsPrivacy: undefined;
ViewEditMultisigCosignersRoot: { walletID: string; cosigners: string[] };
WalletXpubRoot: undefined;

View File

@ -1,122 +0,0 @@
import React, { lazy, Suspense } from 'react';
import Currency from '../screen/settings/Currency';
import Language from '../screen/settings/Language';
import { LazyLoadingIndicator } from './LazyLoadingIndicator'; // Assume you have this component for loading indication
import SettingsBlockExplorer from '../screen/settings/SettingsBlockExplorer';
const Settings = lazy(() => import('../screen/settings/Settings'));
const GeneralSettings = lazy(() => import('../screen/settings/GeneralSettings'));
const Licensing = lazy(() => import('../screen/settings/Licensing'));
const NetworkSettings = lazy(() => import('../screen/settings/NetworkSettings'));
const About = lazy(() => import('../screen/settings/About'));
const DefaultView = lazy(() => import('../screen/settings/DefaultView'));
const ElectrumSettings = lazy(() => import('../screen/settings/ElectrumSettings'));
const EncryptStorage = lazy(() => import('../screen/settings/EncryptStorage'));
const LightningSettings = lazy(() => import('../screen/settings/LightningSettings'));
const NotificationSettings = lazy(() => import('../screen/settings/NotificationSettings'));
const SelfTest = lazy(() => import('../screen/settings/SelfTest'));
const ReleaseNotes = lazy(() => import('../screen/settings/ReleaseNotes'));
const Tools = lazy(() => import('../screen/settings/tools'));
const SettingsPrivacy = lazy(() => import('../screen/settings/SettingsPrivacy'));
const PlausibleDeniability = lazy(() => import('../screen/PlausibleDeniability'));
export const SettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<Settings />
</Suspense>
);
export const CurrencyComponent = () => <Currency />;
export const GeneralSettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<GeneralSettings />
</Suspense>
);
export const LicensingComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<Licensing />
</Suspense>
);
export const NetworkSettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<NetworkSettings />
</Suspense>
);
export const BlockExplorerSettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<SettingsBlockExplorer />
</Suspense>
);
export const AboutComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<About />
</Suspense>
);
export const DefaultViewComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<DefaultView />
</Suspense>
);
export const ElectrumSettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<ElectrumSettings />
</Suspense>
);
export const EncryptStorageComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<EncryptStorage />
</Suspense>
);
export const LanguageComponent = () => <Language />;
export const LightningSettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<LightningSettings />
</Suspense>
);
export const NotificationSettingsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<NotificationSettings />
</Suspense>
);
export const SelfTestComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<SelfTest />
</Suspense>
);
export const ReleaseNotesComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<ReleaseNotes />
</Suspense>
);
export const ToolsComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<Tools />
</Suspense>
);
export const SettingsPrivacyComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<SettingsPrivacy />
</Suspense>
);
export const PlausibleDeniabilityComponent = () => (
<Suspense fallback={<LazyLoadingIndicator />}>
<PlausibleDeniability />
</Suspense>
);

View File

@ -35,7 +35,7 @@ const Settings = () => {
<ListItem title={loc.settings.language} onPress={() => navigate('Language')} testID="Language" chevron />
<ListItem title={loc.settings.encrypt_title} onPress={() => navigate('EncryptStorage')} testID="SecurityButton" chevron />
<ListItem title={loc.settings.network} onPress={() => navigate('NetworkSettings')} testID="NetworkSettings" chevron />
<ListItem title={loc.settings.tools} onPress={() => navigate('Tools')} testID="Tools" chevron />
<ListItem title={loc.settings.tools} onPress={() => navigate('ToolsScreen')} testID="Tools" chevron />
<ListItem title={loc.settings.about} onPress={() => navigate('About')} testID="AboutButton" chevron />
</ScrollView>
);

View File

@ -5,7 +5,7 @@ import { ScrollView } from 'react-native';
import ListItem from '../../components/ListItem';
import loc from '../../loc';
const NetworkSettings = () => {
const ToolsScreen = () => {
const { navigate } = useNavigation();
const navigateToIsItMyAddress = () => {
@ -29,4 +29,4 @@ const NetworkSettings = () => {
);
};
export default NetworkSettings;
export default ToolsScreen;