mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-18 21:35:21 +01:00
Merge branch 'master' into refBlueUseAllFundsButton
This commit is contained in:
commit
450b01f0f3
6
App.js
6
App.js
@ -43,7 +43,7 @@ const App = () => {
|
||||
const appState = useRef(AppState.currentState);
|
||||
const [isClipboardContentModalVisible, setIsClipboardContentModalVisible] = useState(false);
|
||||
const [clipboardContentType, setClipboardContentType] = useState();
|
||||
const [clipboardContent, setClipboardContent] = useState('');
|
||||
const clipboardContent = useRef();
|
||||
const colorScheme = useColorScheme();
|
||||
const stylesHook = StyleSheet.create({
|
||||
modalContent: {
|
||||
@ -217,7 +217,7 @@ const App = () => {
|
||||
const isBothBitcoinAndLightning = DeeplinkSchemaMatch.isBothBitcoinAndLightning(clipboard);
|
||||
if (
|
||||
!isAddressFromStoredWallet &&
|
||||
clipboardContent !== clipboard &&
|
||||
clipboardContent.current !== clipboard &&
|
||||
(isBitcoinAddress || isLightningInvoice || isLNURL || isBothBitcoinAndLightning)
|
||||
) {
|
||||
if (isBitcoinAddress) {
|
||||
@ -229,7 +229,7 @@ const App = () => {
|
||||
}
|
||||
setIsClipboardContentModalVisible(true);
|
||||
}
|
||||
setClipboardContent(clipboard);
|
||||
clipboardContent.current = clipboard;
|
||||
}
|
||||
if (nextAppState) {
|
||||
appState.current = nextAppState;
|
||||
|
@ -1353,7 +1353,7 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
|
||||
const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1);
|
||||
const { colors } = useTheme();
|
||||
const { navigate } = useNavigation();
|
||||
const { txMetadata, wallets } = useContext(BlueStorageContext);
|
||||
const { txMetadata, wallets, preferredFiatCurrency, language } = useContext(BlueStorageContext);
|
||||
const containerStyle = useMemo(
|
||||
() => ({
|
||||
backgroundColor: 'transparent',
|
||||
@ -1371,7 +1371,8 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
|
||||
} else {
|
||||
return transactionTimeToReadable(item.received);
|
||||
}
|
||||
}, [item.confirmations, item.received]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [item.confirmations, item.received, language]);
|
||||
const txMemo = txMetadata[item.hash]?.memo ?? '';
|
||||
const subtitle = useMemo(() => {
|
||||
let sub = item.confirmations < 7 ? loc.formatString(loc.transactions.list_conf, { number: item.confirmations }) : '';
|
||||
@ -1402,7 +1403,8 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
|
||||
} else {
|
||||
return formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString();
|
||||
}
|
||||
}, [item, itemPriceUnit]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [item, itemPriceUnit, preferredFiatCurrency]);
|
||||
|
||||
const rowTitleStyle = useMemo(() => {
|
||||
let color = colors.successColor;
|
||||
|
@ -1,5 +1,7 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { useAsyncStorage } from '@react-native-community/async-storage';
|
||||
import React, { createContext, useEffect, useState } from 'react';
|
||||
import { AppStorage } from '../class';
|
||||
const BlueApp = require('../BlueApp');
|
||||
const BlueElectrum = require('./BlueElectrum');
|
||||
|
||||
@ -9,6 +11,10 @@ export const BlueStorageProvider = ({ children }) => {
|
||||
const [pendingWallets, setPendingWallets] = useState([]);
|
||||
const [selectedWallet, setSelectedWallet] = useState('');
|
||||
const [walletsInitialized, setWalletsInitialized] = useState(false);
|
||||
const [preferredFiatCurrency, _setPreferredFiatCurrency] = useState();
|
||||
const [language, _setLanguage] = useState();
|
||||
const getPreferredCurrencyAsyncStorage = useAsyncStorage(AppStorage.PREFERRED_CURRENCY).getItem;
|
||||
const getLanguageAsyncStorage = useAsyncStorage(AppStorage.LANG).getItem;
|
||||
const [newWalletAdded, setNewWalletAdded] = useState(false);
|
||||
const saveToDisk = async () => {
|
||||
BlueApp.tx_metadata = txMetadata;
|
||||
@ -21,6 +27,30 @@ export const BlueStorageProvider = ({ children }) => {
|
||||
setWallets(BlueApp.getWallets());
|
||||
}, []);
|
||||
|
||||
const getPreferredCurrency = async () => {
|
||||
const item = await getPreferredCurrencyAsyncStorage();
|
||||
_setPreferredFiatCurrency(item);
|
||||
};
|
||||
|
||||
const setPreferredFiatCurrency = () => {
|
||||
getPreferredCurrency();
|
||||
};
|
||||
|
||||
const getLanguage = async () => {
|
||||
const item = await getLanguageAsyncStorage();
|
||||
_setLanguage(item);
|
||||
};
|
||||
|
||||
const setLanguage = () => {
|
||||
getLanguage();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getPreferredCurrency();
|
||||
getLanguageAsyncStorage();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const resetWallets = () => {
|
||||
setWallets(BlueApp.getWallets());
|
||||
};
|
||||
@ -149,6 +179,10 @@ export const BlueStorageProvider = ({ children }) => {
|
||||
setResetOnAppUninstallTo,
|
||||
isPasswordInUse,
|
||||
setIsAdancedModeEnabled,
|
||||
setPreferredFiatCurrency,
|
||||
preferredFiatCurrency,
|
||||
setLanguage,
|
||||
language,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useRef, useCallback, useState, useImperativeHandle, forwardRef } from 'react';
|
||||
import React, { useRef, useCallback, useState, useImperativeHandle, forwardRef, useContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
@ -21,6 +21,8 @@ import { LightningCustodianWallet, MultisigHDWallet, PlaceholderWallet } from '.
|
||||
import WalletGradient from '../class/wallet-gradient';
|
||||
import { BluePrivateBalance } from '../BlueComponents';
|
||||
|
||||
import { BlueStorageContext } from '../blue_modules/storage-context';
|
||||
|
||||
const nStyles = StyleSheet.create({
|
||||
root: {
|
||||
marginVertical: 17,
|
||||
@ -268,6 +270,7 @@ const cStyles = StyleSheet.create({
|
||||
const WalletsCarousel = forwardRef((props, ref) => {
|
||||
const carouselRef = useRef();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const { preferredFiatCurrency, language } = useContext(BlueStorageContext);
|
||||
const renderItem = useCallback(
|
||||
({ item, index }) => (
|
||||
<WalletCarouselItem
|
||||
@ -278,7 +281,8 @@ const WalletsCarousel = forwardRef((props, ref) => {
|
||||
onPress={props.onPress}
|
||||
/>
|
||||
),
|
||||
[props.vertical, props.selectedWallet, props.handleLongPress, props.onPress],
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[props.vertical, props.selectedWallet, props.handleLongPress, props.onPress, preferredFiatCurrency, language],
|
||||
);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"filename" : "bitcoin@3x.png"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
@ -12,6 +12,18 @@
|
||||
},
|
||||
{
|
||||
"filename" : "BlueWallet.sticker"
|
||||
},
|
||||
{
|
||||
"filename" : "bluebeast.sticker"
|
||||
},
|
||||
{
|
||||
"filename" : "Lightning.sticker"
|
||||
},
|
||||
{
|
||||
"filename" : "Vault.sticker"
|
||||
},
|
||||
{
|
||||
"filename" : "Bitcoin (Blue).sticker"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"filename" : "lightning@3x.png"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"filename" : "vault_main@3x.png"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"filename" : "bluebeast.png"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -232,7 +232,8 @@
|
||||
"about_review": "Leave us a review",
|
||||
"about_selftest": "Run self-test",
|
||||
"about_sm_github": "GitHub",
|
||||
"about_sm_telegram": "Telegram chat",
|
||||
"about_sm_discord": "Discord Server",
|
||||
"about_sm_telegram": "Telegram channel",
|
||||
"about_sm_twitter": "Follow us on Twitter",
|
||||
"advanced_options": "Advanced Options",
|
||||
"currency": "Currency",
|
||||
@ -402,6 +403,7 @@
|
||||
"list_tryagain": "Try again",
|
||||
"looks_like_bip38": "This looks like a password-protected private key (BIP38)",
|
||||
"reorder_title": "Reorder Wallets",
|
||||
"please_continue_scanning": "Please continue scanning",
|
||||
"select_no_bitcoin": "There are currently no Bitcoin wallets available.",
|
||||
"select_no_bitcoin_exp": "A Bitcoin wallet is required to refill Lightning wallets. Please create or import one.",
|
||||
"select_wallet": "Select Wallet",
|
||||
|
245
loc/index.js
245
loc/index.js
@ -13,125 +13,131 @@ const currency = require('../blue_modules/currency');
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
// first-time loading sequence
|
||||
(async () => {
|
||||
|
||||
const setDateTimeLocale = async () => {
|
||||
let lang = await AsyncStorage.getItem('lang');
|
||||
let localeForDayJSAvailable = true;
|
||||
switch (lang) {
|
||||
case 'ar':
|
||||
require('dayjs/locale/ar');
|
||||
break;
|
||||
case 'bg_bg':
|
||||
lang = 'bg';
|
||||
require('dayjs/locale/bg');
|
||||
break;
|
||||
case 'ca':
|
||||
require('dayjs/locale/ca');
|
||||
break;
|
||||
case 'cy':
|
||||
require('dayjs/locale/cy');
|
||||
break;
|
||||
case 'da_dk':
|
||||
require('dayjs/locale/da');
|
||||
break;
|
||||
case 'de_de':
|
||||
require('dayjs/locale/de');
|
||||
break;
|
||||
case 'el':
|
||||
require('dayjs/locale/el');
|
||||
break;
|
||||
case 'es':
|
||||
require('dayjs/locale/es');
|
||||
break;
|
||||
case 'es_419':
|
||||
// es-do it is the closes one to es_419
|
||||
lang = 'es-do';
|
||||
require('dayjs/locale/es-do');
|
||||
break;
|
||||
case 'fi_fi':
|
||||
require('dayjs/locale/fi');
|
||||
break;
|
||||
case 'fa':
|
||||
require('dayjs/locale/fa');
|
||||
break;
|
||||
case 'fr_fr':
|
||||
require('dayjs/locale/fr');
|
||||
break;
|
||||
case 'he':
|
||||
require('dayjs/locale/he');
|
||||
break;
|
||||
case 'hr_hr':
|
||||
require('dayjs/locale/hr');
|
||||
break;
|
||||
case 'hu_hu':
|
||||
require('dayjs/locale/hu');
|
||||
break;
|
||||
case 'id_id':
|
||||
require('dayjs/locale/id');
|
||||
break;
|
||||
case 'it':
|
||||
require('dayjs/locale/it');
|
||||
break;
|
||||
case 'jp_jp':
|
||||
lang = 'ja';
|
||||
require('dayjs/locale/ja');
|
||||
break;
|
||||
case 'nb_no':
|
||||
require('dayjs/locale/nb');
|
||||
break;
|
||||
case 'nl_nl':
|
||||
require('dayjs/locale/nl');
|
||||
break;
|
||||
case 'pt_br':
|
||||
lang = 'pt-br';
|
||||
require('dayjs/locale/pt-br');
|
||||
break;
|
||||
case 'pt_pt':
|
||||
lang = 'pt';
|
||||
require('dayjs/locale/pt');
|
||||
break;
|
||||
case 'pl':
|
||||
require('dayjs/locale/pl');
|
||||
break;
|
||||
case 'ru':
|
||||
require('dayjs/locale/ru');
|
||||
break;
|
||||
case 'sk_sk':
|
||||
require('dayjs/locale/sk');
|
||||
break;
|
||||
case 'sl_si':
|
||||
require('dayjs/locale/sl');
|
||||
break;
|
||||
case 'sv_se':
|
||||
require('dayjs/locale/sv');
|
||||
break;
|
||||
case 'th_th':
|
||||
require('dayjs/locale/th');
|
||||
break;
|
||||
case 'tr_tr':
|
||||
require('dayjs/locale/tr');
|
||||
break;
|
||||
case 'vi_vn':
|
||||
require('dayjs/locale/vi');
|
||||
break;
|
||||
case 'zh_cn':
|
||||
lang = 'zh-cn';
|
||||
require('dayjs/locale/zh-cn');
|
||||
break;
|
||||
case 'zh_tw':
|
||||
lang = 'zh-tw';
|
||||
require('dayjs/locale/zh-tw');
|
||||
break;
|
||||
default:
|
||||
localeForDayJSAvailable = false;
|
||||
break;
|
||||
}
|
||||
if (localeForDayJSAvailable) {
|
||||
dayjs.locale(lang.split('_')[0]);
|
||||
}
|
||||
};
|
||||
|
||||
const setLanguageLocale = async () => {
|
||||
// finding out whether lang preference was saved
|
||||
// For some reason using the AppStorage.LANG constant is not working. Hard coding string for now.
|
||||
let lang = await AsyncStorage.getItem('lang');
|
||||
const lang = await AsyncStorage.getItem('lang');
|
||||
if (lang) {
|
||||
strings.setLanguage(lang);
|
||||
let localeForDayJSAvailable = true;
|
||||
switch (lang) {
|
||||
case 'ar':
|
||||
require('dayjs/locale/ar');
|
||||
break;
|
||||
case 'bg_bg':
|
||||
lang = 'bg';
|
||||
require('dayjs/locale/bg');
|
||||
break;
|
||||
case 'ca':
|
||||
require('dayjs/locale/ca');
|
||||
break;
|
||||
case 'cy':
|
||||
require('dayjs/locale/cy');
|
||||
break;
|
||||
case 'da_dk':
|
||||
require('dayjs/locale/da');
|
||||
break;
|
||||
case 'de_de':
|
||||
require('dayjs/locale/de');
|
||||
break;
|
||||
case 'el':
|
||||
require('dayjs/locale/el');
|
||||
break;
|
||||
case 'es':
|
||||
require('dayjs/locale/es');
|
||||
break;
|
||||
case 'es_419':
|
||||
// es-do it is the closes one to es_419
|
||||
lang = 'es-do';
|
||||
require('dayjs/locale/es-do');
|
||||
break;
|
||||
case 'fi_fi':
|
||||
require('dayjs/locale/fi');
|
||||
break;
|
||||
case 'fa':
|
||||
require('dayjs/locale/fa');
|
||||
break;
|
||||
case 'fr_fr':
|
||||
require('dayjs/locale/fr');
|
||||
break;
|
||||
case 'he':
|
||||
require('dayjs/locale/he');
|
||||
break;
|
||||
case 'hr_hr':
|
||||
require('dayjs/locale/hr');
|
||||
break;
|
||||
case 'hu_hu':
|
||||
require('dayjs/locale/hu');
|
||||
break;
|
||||
case 'id_id':
|
||||
require('dayjs/locale/id');
|
||||
break;
|
||||
case 'it':
|
||||
require('dayjs/locale/it');
|
||||
break;
|
||||
case 'jp_jp':
|
||||
lang = 'ja';
|
||||
require('dayjs/locale/ja');
|
||||
break;
|
||||
case 'nb_no':
|
||||
require('dayjs/locale/nb');
|
||||
break;
|
||||
case 'nl_nl':
|
||||
require('dayjs/locale/nl');
|
||||
break;
|
||||
case 'pt_br':
|
||||
lang = 'pt-br';
|
||||
require('dayjs/locale/pt-br');
|
||||
break;
|
||||
case 'pt_pt':
|
||||
lang = 'pt';
|
||||
require('dayjs/locale/pt');
|
||||
break;
|
||||
case 'pl':
|
||||
require('dayjs/locale/pl');
|
||||
break;
|
||||
case 'ru':
|
||||
require('dayjs/locale/ru');
|
||||
break;
|
||||
case 'sk_sk':
|
||||
require('dayjs/locale/sk');
|
||||
break;
|
||||
case 'sl_si':
|
||||
require('dayjs/locale/sl');
|
||||
break;
|
||||
case 'sv_se':
|
||||
require('dayjs/locale/sv');
|
||||
break;
|
||||
case 'th_th':
|
||||
require('dayjs/locale/th');
|
||||
break;
|
||||
case 'tr_tr':
|
||||
require('dayjs/locale/tr');
|
||||
break;
|
||||
case 'vi_vn':
|
||||
require('dayjs/locale/vi');
|
||||
break;
|
||||
case 'zh_cn':
|
||||
lang = 'zh-cn';
|
||||
require('dayjs/locale/zh-cn');
|
||||
break;
|
||||
case 'zh_tw':
|
||||
lang = 'zh-tw';
|
||||
require('dayjs/locale/zh-tw');
|
||||
break;
|
||||
default:
|
||||
localeForDayJSAvailable = false;
|
||||
break;
|
||||
}
|
||||
if (localeForDayJSAvailable) {
|
||||
dayjs.locale(lang.split('_')[0]);
|
||||
}
|
||||
await setDateTimeLocale();
|
||||
} else {
|
||||
const locales = RNLocalize.getLocales();
|
||||
if (Object.keys(AvailableLanguages).some(language => language === locales[0])) {
|
||||
@ -142,7 +148,8 @@ dayjs.extend(relativeTime);
|
||||
strings.setLanguage('en');
|
||||
}
|
||||
}
|
||||
})();
|
||||
};
|
||||
setLanguageLocale();
|
||||
|
||||
const strings = new Localization({
|
||||
en: require('./en.json'),
|
||||
@ -184,7 +191,11 @@ const strings = new Localization({
|
||||
zh_tw: require('./zh_tw.json'),
|
||||
});
|
||||
|
||||
strings.saveLanguage = lang => AsyncStorage.setItem(AppStorage.LANG, lang);
|
||||
strings.saveLanguage = async lang => {
|
||||
await AsyncStorage.setItem(AppStorage.LANG, lang);
|
||||
strings.setLanguage(lang);
|
||||
await setDateTimeLocale();
|
||||
};
|
||||
|
||||
export const transactionTimeToReadable = time => {
|
||||
if (time === 0) {
|
||||
|
@ -70,7 +70,7 @@ const styles = StyleSheet.create({
|
||||
position: 'absolute',
|
||||
},
|
||||
backdoorInputWrapper: { position: 'absolute', left: '5%', top: '0%', width: '90%', height: '70%', backgroundColor: 'white' },
|
||||
progressWrapper: { position: 'absolute', right: '50%', top: '50%', backgroundColor: 'rgba(255, 255, 255, 0.1)' },
|
||||
progressWrapper: { position: 'absolute', alignSelf: 'center', alignItems: 'center', top: '50%', padding: 8, borderRadius: 8 },
|
||||
backdoorInput: {
|
||||
height: '50%',
|
||||
marginTop: 5,
|
||||
@ -105,6 +105,7 @@ const ScanQRCode = () => {
|
||||
openSettingsContainer: {
|
||||
backgroundColor: colors.brandingColor,
|
||||
},
|
||||
progressWrapper: { backgroundColor: colors.brandingColor, borderColor: colors.foregroundColor, borderWidth: 4 },
|
||||
});
|
||||
const HashIt = function (s) {
|
||||
return createHash('sha256').update(s).digest().toString('hex');
|
||||
@ -270,13 +271,13 @@ const ScanQRCode = () => {
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{urTotal > 0 && (
|
||||
<View style={styles.progressWrapper} testID="UrProgressBar">
|
||||
<View style={[styles.progressWrapper, stylesHook.progressWrapper]} testID="UrProgressBar">
|
||||
<BlueText>{loc.wallets.please_continue_scanning}</BlueText>
|
||||
<BlueText>
|
||||
{urHave} / {urTotal}
|
||||
</BlueText>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{backdoorVisible && (
|
||||
<View style={styles.backdoorInputWrapper}>
|
||||
<BlueText>Provide QR code contents manually:</BlueText>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { ScrollView, Linking, Image, View, Text, StyleSheet, useWindowDimensions } from 'react-native';
|
||||
import { TouchableOpacity, ScrollView, Linking, Image, View, Text, StyleSheet, useWindowDimensions } from 'react-native';
|
||||
import { useNavigation, useTheme } from '@react-navigation/native';
|
||||
import {
|
||||
BlueTextCentered,
|
||||
@ -10,6 +10,7 @@ import {
|
||||
BlueListItem,
|
||||
BlueNavigationStyle,
|
||||
} from '../../BlueComponents';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info';
|
||||
import Rate, { AndroidMarket } from 'react-native-rate';
|
||||
import loc from '../../loc';
|
||||
@ -53,6 +54,18 @@ const About = () => {
|
||||
paddingTop: 0,
|
||||
borderRadius: 8,
|
||||
},
|
||||
buttonLink :{
|
||||
backgroundColor: colors.lightButton,
|
||||
borderRadius: 12,
|
||||
justifyContent: 'center',
|
||||
padding: 8,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
textLink :{
|
||||
color: colors.foregroundColor,
|
||||
marginLeft: 8,
|
||||
fontWeight: '600',
|
||||
},
|
||||
});
|
||||
|
||||
const handleOnReleaseNotesPress = () => {
|
||||
@ -71,14 +84,16 @@ const About = () => {
|
||||
Linking.openURL('https://twitter.com/bluewalletio');
|
||||
};
|
||||
|
||||
const handleOnGithubPress = () => {
|
||||
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
|
||||
const handleOnDiscordPress = () => {
|
||||
Linking.openURL('https://discord.gg/btWq2Aby2z');
|
||||
};
|
||||
|
||||
const handleOnTelegramPress = () => {
|
||||
Linking.openURL('https://t.me/bluewallet');
|
||||
Linking.openURL('https://t.me/bluewallethat');
|
||||
};
|
||||
const handleOnGithubPress = () => {
|
||||
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
|
||||
};
|
||||
|
||||
const handleOnRatePress = () => {
|
||||
const options = {
|
||||
AppleAppID: '1376878040',
|
||||
@ -126,12 +141,12 @@ const About = () => {
|
||||
/>
|
||||
<BlueListItem
|
||||
leftIcon={{
|
||||
name: 'github',
|
||||
type: 'font-awesome',
|
||||
color: colors.foregroundColor,
|
||||
name: 'discord',
|
||||
type: 'font-awesome-5',
|
||||
color: '#7289da',
|
||||
}}
|
||||
onPress={handleOnGithubPress}
|
||||
title={loc.settings.about_sm_github}
|
||||
onPress={handleOnDiscordPress}
|
||||
title={loc.settings.about_sm_discord}
|
||||
/>
|
||||
<BlueCard>
|
||||
<View style={styles.buildWith}>
|
||||
@ -143,6 +158,15 @@ const About = () => {
|
||||
<BlueTextCentered>bitcoinjs-lib</BlueTextCentered>
|
||||
<BlueTextCentered>Nodejs</BlueTextCentered>
|
||||
<BlueTextCentered>Electrum server</BlueTextCentered>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={handleOnGithubPress}
|
||||
style={styles.buttonLink}
|
||||
>
|
||||
<Icon size={22} name="github" type="font-awesome-5" color={colors.foregroundColor} />
|
||||
<Text style={styles.textLink}>{loc.settings.about_sm_github}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</BlueCard>
|
||||
<BlueListItem
|
||||
|
@ -1,15 +1,17 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import { FlatList, ActivityIndicator, View, StyleSheet } from 'react-native';
|
||||
import { SafeBlueArea, BlueListItem, BlueText, BlueCard, BlueNavigationStyle } from '../../BlueComponents';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FiatUnit, FiatUnitSource } from '../../models/fiatUnit';
|
||||
import loc from '../../loc';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
|
||||
const data = Object.values(FiatUnit);
|
||||
|
||||
const Currency = () => {
|
||||
const { setPreferredFiatCurrency } = useContext(BlueStorageContext);
|
||||
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
|
||||
const [selectedCurrency, setSelectedCurrency] = useState(null);
|
||||
const { colors } = useTheme();
|
||||
@ -62,6 +64,7 @@ const Currency = () => {
|
||||
await currency.setPrefferedCurrency(item);
|
||||
await currency.startUpdater();
|
||||
setIsSavingNewPreferredCurrency(false);
|
||||
setPreferredFiatCurrency();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -1,9 +1,12 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import { FlatList, StyleSheet } from 'react-native';
|
||||
import { SafeBlueArea, BlueListItem, BlueCard, BlueLoading, BlueNavigationStyle, BlueText } from '../../BlueComponents';
|
||||
import { SafeBlueArea, BlueListItem, BlueLoading, BlueNavigationStyle } from '../../BlueComponents';
|
||||
import { AvailableLanguages } from '../../loc/languages';
|
||||
import loc from '../../loc';
|
||||
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import { useNavigation, useTheme } from '@react-navigation/native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
flex: {
|
||||
flex: 1,
|
||||
@ -11,42 +14,50 @@ const styles = StyleSheet.create({
|
||||
});
|
||||
|
||||
const Language = () => {
|
||||
const { setLanguage, language } = useContext(BlueStorageContext);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [language, setLanguage] = useState(loc.getLanguage());
|
||||
|
||||
const [selectedLanguage, setSelectedLanguage] = useState(loc.getLanguage());
|
||||
const { setOptions } = useNavigation();
|
||||
const { colors } = useTheme();
|
||||
const stylesHook = StyleSheet.create({
|
||||
flex: {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
});
|
||||
useEffect(() => {
|
||||
setIsLoading(false);
|
||||
}, []);
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ item }) => {
|
||||
return (
|
||||
<BlueListItem
|
||||
onPress={() => {
|
||||
console.log('setLanguage', item.value);
|
||||
loc.saveLanguage(item.value);
|
||||
setLanguage(item.value);
|
||||
}}
|
||||
title={item.label}
|
||||
{...(language === item.value
|
||||
? {
|
||||
rightIcon: { name: 'check', type: 'octaicon', color: '#0070FF' },
|
||||
}
|
||||
: { hideChevron: true })}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[language],
|
||||
);
|
||||
useEffect(() => {
|
||||
setOptions({ headerTitle: loc.settings.language });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [language]);
|
||||
|
||||
const renderItem = item => {
|
||||
return (
|
||||
<BlueListItem
|
||||
onPress={async () => {
|
||||
await loc.saveLanguage(item.item.value);
|
||||
setSelectedLanguage(item.item.value);
|
||||
setLanguage();
|
||||
}}
|
||||
title={item.item.label}
|
||||
checkmark={selectedLanguage === item.item.value}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return isLoading ? (
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
|
||||
<FlatList style={styles.flex} keyExtractor={(_item, index) => `${index}`} data={AvailableLanguages} renderItem={renderItem} />
|
||||
<BlueCard>
|
||||
<BlueText>{loc.settings.language_restart}</BlueText>
|
||||
</BlueCard>
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.flex, stylesHook.flex]}>
|
||||
<FlatList
|
||||
style={[styles.flex, stylesHook.flex]}
|
||||
keyExtractor={(_item, index) => `${index}`}
|
||||
data={AvailableLanguages}
|
||||
renderItem={renderItem}
|
||||
initialNumToRender={25}
|
||||
/>
|
||||
</SafeBlueArea>
|
||||
);
|
||||
};
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import { ScrollView, TouchableOpacity, StyleSheet, StatusBar } from 'react-native';
|
||||
import React, { useContext } from 'react';
|
||||
import { ScrollView, StyleSheet, StatusBar } from 'react-native';
|
||||
import { BlueListItem, BlueNavigationStyle, BlueHeaderDefaultSub } from '../../BlueComponents';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
@ -12,36 +13,22 @@ const styles = StyleSheet.create({
|
||||
|
||||
const Settings = () => {
|
||||
const { navigate } = useNavigation();
|
||||
// By simply having it here, it'll re-render the UI if language is changed
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { language } = useContext(BlueStorageContext);
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.root}>
|
||||
<StatusBar barStyle="default" />
|
||||
<BlueHeaderDefaultSub leftText={loc.settings.header} rightComponent={null} />
|
||||
<BlueListItem title={loc.settings.general} component={TouchableOpacity} onPress={() => navigate('GeneralSettings')} chevron />
|
||||
<BlueListItem title={loc.settings.currency} component={TouchableOpacity} onPress={() => navigate('Currency')} chevron />
|
||||
<BlueListItem title={loc.settings.language} component={TouchableOpacity} onPress={() => navigate('Language')} chevron />
|
||||
<BlueListItem
|
||||
title={loc.settings.encrypt_title}
|
||||
onPress={() => navigate('EncryptStorage')}
|
||||
component={TouchableOpacity}
|
||||
testID="SecurityButton"
|
||||
chevron
|
||||
/>
|
||||
<BlueListItem title={loc.settings.network} component={TouchableOpacity} onPress={() => navigate('NetworkSettings')} chevron />
|
||||
<BlueListItem
|
||||
title={loc.settings.notifications}
|
||||
component={TouchableOpacity}
|
||||
onPress={() => navigate('NotificationSettings')}
|
||||
chevron
|
||||
/>
|
||||
<BlueListItem title={loc.settings.privacy} component={TouchableOpacity} onPress={() => navigate('SettingsPrivacy')} chevron />
|
||||
<BlueListItem
|
||||
title={loc.settings.about}
|
||||
component={TouchableOpacity}
|
||||
onPress={() => navigate('About')}
|
||||
testID="AboutButton"
|
||||
chevron
|
||||
/>
|
||||
<BlueHeaderDefaultSub leftText={loc.settings.header}/>
|
||||
<BlueListItem title={loc.settings.general} onPress={() => navigate('GeneralSettings')} chevron />
|
||||
<BlueListItem title={loc.settings.currency} onPress={() => navigate('Currency')} chevron />
|
||||
<BlueListItem title={loc.settings.language} onPress={() => navigate('Language')} chevron />
|
||||
<BlueListItem title={loc.settings.encrypt_title} onPress={() => navigate('EncryptStorage')} testID="SecurityButton" chevron />
|
||||
<BlueListItem title={loc.settings.network} onPress={() => navigate('NetworkSettings')} chevron />
|
||||
<BlueListItem title={loc.settings.notifications} onPress={() => navigate('NotificationSettings')} chevron />
|
||||
<BlueListItem title={loc.settings.privacy} onPress={() => navigate('SettingsPrivacy')} chevron />
|
||||
<BlueListItem title={loc.settings.about} onPress={() => navigate('About')} testID="AboutButton" chevron />
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user