Merge branch 'master' into limpbrains-multisig-passphrase

This commit is contained in:
Ivan Vershigora 2022-02-15 17:41:20 +03:00
commit de8c46da17
146 changed files with 21116 additions and 25537 deletions

2
.bundle/config Normal file
View File

@ -0,0 +1,2 @@
BUNDLE_PATH: "vendor/bundle"
BUNDLE_FORCE_RUBY_PLATFORM: 1

View File

@ -18,6 +18,8 @@
"react/jsx-handler-names": "off", // activated by standard-react config
"react/display-name": "off",
"react-native/no-inline-styles": "error",
"react-native/no-unused-styles": "error",
"react-native/no-single-element-style-arrays": "error",
"prettier/prettier": [
"warn",
{

5
.gitattributes vendored
View File

@ -1,5 +0,0 @@
*.pbxproj -text
*.patch -text
# Windows files should use crlf line endings
# https://help.github.com/articles/dealing-with-line-endings/
*.bat text eol=crlf

View File

@ -92,7 +92,7 @@ jobs:
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
emulator-build: 6110076 # tmp fix for https://github.com/ReactiveCircus/android-emulator-runner/issues/160
emulator-build: 6885378 # tmp fix for https://github.com/ReactiveCircus/android-emulator-runner/issues/160
target: google_apis
avd-name: Pixel_API_29_AOSP
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047

1
.gitignore vendored
View File

@ -20,6 +20,7 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
*.hprof
# Android/IntelliJ
#

1
.ruby-version Normal file
View File

@ -0,0 +1 @@
2.7.4

38
App.js
View File

@ -39,7 +39,7 @@ import Privacy from './blue_modules/Privacy';
const A = require('./blue_modules/analytics');
const currency = require('./blue_modules/currency');
const eventEmitter = new NativeEventEmitter(NativeModules.EventEmitter);
const eventEmitter = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
const { EventEmitter } = NativeModules;
const ClipboardContentType = Object.freeze({
@ -54,9 +54,8 @@ if (Platform.OS === 'android') {
}
const App = () => {
const { walletsInitialized, wallets, addWallet, saveToDisk, fetchAndSaveWalletTransactions, refreshAllWalletTransactions } = useContext(
BlueStorageContext,
);
const { walletsInitialized, wallets, addWallet, saveToDisk, fetchAndSaveWalletTransactions, refreshAllWalletTransactions } =
useContext(BlueStorageContext);
const appState = useRef(AppState.currentState);
const clipboardContent = useRef();
const colorScheme = useColorScheme();
@ -114,9 +113,9 @@ const App = () => {
return () => {
Linking.removeEventListener('url', handleOpenURL);
AppState.removeEventListener('change', handleAppStateChange);
eventEmitter.removeAllListeners('onNotificationReceived');
eventEmitter.removeAllListeners('openSettings');
eventEmitter.removeAllListeners('onUserActivityOpen');
eventEmitter?.removeAllListeners('onNotificationReceived');
eventEmitter?.removeAllListeners('openSettings');
eventEmitter?.removeAllListeners('onUserActivityOpen');
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@ -145,9 +144,9 @@ const App = () => {
When a notification on iOS is shown while the app is on foreground;
On willPresent on AppDelegate.m
*/
eventEmitter.addListener('onNotificationReceived', onNotificationReceived);
eventEmitter.addListener('openSettings', openSettings);
eventEmitter.addListener('onUserActivityOpen', onUserActivityOpen);
eventEmitter?.addListener('onNotificationReceived', onNotificationReceived);
eventEmitter?.addListener('openSettings', openSettings);
eventEmitter?.addListener('onUserActivityOpen', onUserActivityOpen);
};
const popInitialAction = async data => {
@ -387,25 +386,6 @@ const styles = StyleSheet.create({
root: {
flex: 1,
},
space: {
marginHorizontal: 8,
},
modalContent: {
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 200,
height: 200,
},
modelContentButtonLayout: {
flexDirection: 'row',
margin: 16,
justifyContent: 'space-between',
alignItems: 'flex-end',
},
});
export default App;

View File

@ -1,7 +1,7 @@
/* eslint react/prop-types: "off", react-native/no-inline-styles: "off" */
import React, { Component, forwardRef } from 'react';
import PropTypes from 'prop-types';
import { Icon, Input, Text, Header, ListItem, Avatar } from 'react-native-elements';
import { Icon, Text, Header, ListItem, Avatar } from 'react-native-elements';
import {
ActivityIndicator,
Alert,
@ -11,9 +11,7 @@ import {
InputAccessoryView,
Keyboard,
KeyboardAvoidingView,
PixelRatio,
Platform,
PlatformColor,
SafeAreaView,
StyleSheet,
Switch,
@ -28,6 +26,7 @@ import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeTyp
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useTheme } from '@react-navigation/native';
import { BlueCurrentTheme } from './components/themes';
import PlusIcon from './components/icons/PlusIcon';
import loc, { formatStringAddTwoWhiteSpaces } from './loc';
const { height, width } = Dimensions.get('window');
@ -38,8 +37,6 @@ if (aspectRatio > 1.6) {
} else {
isIpad = true;
}
// eslint-disable-next-line no-unused-expressions
Platform.OS === 'android' ? (ActivityIndicator.defaultProps.color = PlatformColor('?attr/colorControlActivated')) : null;
export const BlueButton = props => {
const { colors } = useTheme();
@ -389,6 +386,7 @@ export const BlueTextCentered = props => {
const { colors } = useTheme();
return <Text {...props} style={{ color: colors.foregroundColor, textAlign: 'center' }} />;
};
export const BlueListItem = React.memo(props => {
const { colors } = useTheme();
@ -472,24 +470,6 @@ export const BlueFormLabel = props => {
);
};
export const BlueFormInput = props => {
const { colors } = useTheme();
return (
<Input
{...props}
inputStyle={{ color: colors.foregroundColor, maxWidth: width - 105 }}
containerStyle={{
marginTop: 5,
borderColor: colors.inputBorderColor,
borderBottomColor: colors.inputBorderColor,
borderWidth: 0.5,
borderBottomWidth: 0.5,
backgroundColor: colors.inputBackgroundColor,
}}
/>
);
};
export const BlueFormMultiInput = props => {
const { colors } = useTheme();
@ -523,19 +503,6 @@ export const BlueFormMultiInput = props => {
);
};
export const BlueHeader = props => {
return (
<Header
{...props}
backgroundColor="transparent"
outerContainerStyles={{
borderBottomColor: 'transparent',
borderBottomWidth: 0,
}}
/>
);
};
export const BlueHeaderDefaultSub = props => {
const { colors } = useTheme();
@ -592,7 +559,7 @@ export const BlueHeaderDefaultMain = props => {
>
{props.leftText}
</Text>
<BluePlusIcon onPress={props.onNewWalletPress} Component={TouchableOpacity} />
<PlusIcon onPress={props.onNewWalletPress} Component={TouchableOpacity} />
</View>
);
};
@ -605,14 +572,6 @@ export const BlueSpacing40 = props => {
return <View {...props} style={{ height: 50 }} />;
};
export const BlueSpacingVariable = props => {
if (isIpad) {
return <BlueSpacing40 {...props} />;
} else {
return <BlueSpacing {...props} />;
}
};
export class is {
static ipad() {
return isIpad;
@ -690,299 +649,6 @@ export const BlueLoading = props => {
);
};
const stylesBlueIcon = StyleSheet.create({
container: {
flex: 1,
},
box1: {
position: 'relative',
top: 15,
},
box: {
alignSelf: 'flex-end',
paddingHorizontal: 14,
paddingTop: 8,
},
boxIncoming: {
position: 'relative',
},
ball: {
width: 30,
height: 30,
borderRadius: 15,
},
ballIncoming: {
width: 30,
height: 30,
borderRadius: 15,
transform: [{ rotate: '-45deg' }],
justifyContent: 'center',
},
ballIncomingWithoutRotate: {
width: 30,
height: 30,
borderRadius: 15,
},
ballReceive: {
width: 30,
height: 30,
borderBottomLeftRadius: 15,
transform: [{ rotate: '-45deg' }],
},
ballOutgoing: {
width: 30,
height: 30,
borderRadius: 15,
transform: [{ rotate: '225deg' }],
justifyContent: 'center',
},
ballOutgoingWithoutRotate: {
width: 30,
height: 30,
borderRadius: 15,
},
ballOutgoingExpired: {
width: 30,
height: 30,
borderRadius: 15,
justifyContent: 'center',
},
ballTransparrent: {
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: 'transparent',
},
ballDimmed: {
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: 'gray',
},
});
export const BluePlusIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ball: {
backgroundColor: colors.buttonBackgroundColor,
},
});
return (
<Avatar
rounded
containerStyle={[stylesBlueIcon.ball, stylesBlueIconHooks.ball]}
icon={{ name: 'add', size: 22, type: 'ionicons', color: colors.foregroundColor }}
{...props}
/>
);
};
export const BlueTransactionIncomingIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballIncoming: {
backgroundColor: colors.ballReceive,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ballIncoming, stylesBlueIconHooks.ballIncoming]}>
<Icon {...props} name="arrow-down" size={16} type="font-awesome" color={colors.incomingForegroundColor} />
</View>
</View>
</View>
);
};
export const BlueTransactionPendingIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ball: {
backgroundColor: colors.buttonBackgroundColor,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ball, stylesBlueIconHooks.ball]}>
<Icon
{...props}
name="kebab-horizontal"
size={16}
type="octicon"
color={colors.foregroundColor}
iconStyle={{ left: 0, top: 7 }}
/>
</View>
</View>
</View>
);
};
export const BlueTransactionExpiredIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballOutgoingExpired: {
backgroundColor: colors.ballOutgoingExpired,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ballOutgoingExpired, stylesBlueIconHooks.ballOutgoingExpired]}>
<Icon {...props} name="clock" size={16} type="octicon" color="#9AA0AA" iconStyle={{ left: 0, top: 0 }} />
</View>
</View>
</View>
);
};
export const BlueTransactionOnchainIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballIncoming: {
backgroundColor: colors.ballReceive,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ballIncoming, stylesBlueIconHooks.ballIncoming]}>
<Icon
{...props}
name="link"
size={16}
type="font-awesome"
color={colors.incomingForegroundColor}
iconStyle={{ left: 0, top: 0, transform: [{ rotate: '-45deg' }] }}
/>
</View>
</View>
</View>
);
};
export const BlueTransactionOffchainIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballOutgoingWithoutRotate: {
backgroundColor: colors.ballOutgoing,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ballOutgoingWithoutRotate, stylesBlueIconHooks.ballOutgoingWithoutRotate]}>
<Icon
{...props}
name="bolt"
size={16}
type="font-awesome"
color={colors.outgoingForegroundColor}
iconStyle={{ left: 0, marginTop: 6 }}
/>
</View>
</View>
</View>
);
};
export const BlueTransactionOffchainIncomingIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballIncomingWithoutRotate: {
backgroundColor: colors.ballReceive,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ballIncomingWithoutRotate, stylesBlueIconHooks.ballIncomingWithoutRotate]}>
<Icon
{...props}
name="bolt"
size={16}
type="font-awesome"
color={colors.incomingForegroundColor}
iconStyle={{ left: 0, marginTop: 6 }}
/>
</View>
</View>
</View>
);
};
export const BlueTransactionOutgoingIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballOutgoing: {
backgroundColor: colors.ballOutgoing,
},
});
return (
<View {...props}>
<View style={stylesBlueIcon.boxIncoming}>
<View style={[stylesBlueIcon.ballOutgoing, stylesBlueIconHooks.ballOutgoing]}>
<Icon {...props} name="arrow-down" size={16} type="font-awesome" color={colors.outgoingForegroundColor} />
</View>
</View>
</View>
);
};
const sendReceiveScanButtonFontSize =
PixelRatio.roundToNearestPixel(Dimensions.get('window').width / 26) > 22
? 22
: PixelRatio.roundToNearestPixel(Dimensions.get('window').width / 26);
export const BlueReceiveButtonIcon = props => {
const { colors } = useTheme();
return (
<TouchableOpacity accessibilityRole="button" {...props} style={{ flex: 1 }}>
<View
style={{
flex: 1,
backgroundColor: colors.buttonBackgroundColor,
}}
>
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
<View
style={{
left: 5,
backgroundColor: 'transparent',
transform: [{ rotate: '-45deg' }],
alignItems: 'center',
marginRight: 8,
}}
>
<Icon
{...props}
name="arrow-down"
size={sendReceiveScanButtonFontSize}
type="font-awesome"
color={colors.buttonAlternativeTextColor}
/>
</View>
<Text
style={{
color: colors.buttonAlternativeTextColor,
fontWeight: '500',
fontSize: sendReceiveScanButtonFontSize,
left: 5,
backgroundColor: 'transparent',
}}
>
{formatStringAddTwoWhiteSpaces(loc.receive.header)}
</Text>
</View>
</View>
</TouchableOpacity>
);
};
export class BlueReplaceFeeSuggestions extends Component {
static propTypes = {
onFeeSelected: PropTypes.func.isRequired,

6
Gemfile Normal file
View File

@ -0,0 +1,6 @@
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby '2.7.4'
gem 'cocoapods', '~> 1.11', '>= 1.11.2'

100
Gemfile.lock Normal file
View File

@ -0,0 +1,100 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
rexml
activesupport (6.1.4.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
claide (1.1.0)
cocoapods (1.11.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.11.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.3.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.11.2)
activesupport (>= 5.0, < 7)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
netrc (~> 0.11)
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.5.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
cocoapods-trunk (1.6.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.1.9)
escape (0.0.4)
ethon (0.15.0)
ffi (>= 1.15.0)
ffi (1.15.5)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.8.3)
i18n (1.9.1)
concurrent-ruby (~> 1.0)
json (2.6.1)
minitest (5.15.0)
molinillo (0.8.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
public_suffix (4.0.6)
rexml (3.2.5)
ruby-macho (2.5.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
xcodeproj (1.21.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
zeitwerk (2.5.4)
PLATFORMS
ruby
DEPENDENCIES
cocoapods (~> 1.11, >= 1.11.2)
RUBY VERSION
ruby 2.7.4p191
BUNDLED WITH
2.2.27

View File

@ -52,7 +52,6 @@ import Marketplace from './screen/wallets/marketplace';
import ReorderWallets from './screen/wallets/reorderWallets';
import SelectWallet from './screen/wallets/selectWallet';
import ProvideEntropy from './screen/wallets/provideEntropy';
import AOPP from './screen/wallets/aopp';
import TransactionDetails from './screen/transactions/details';
import TransactionStatus from './screen/transactions/transactionStatus';
@ -84,6 +83,7 @@ import LdkInfo from './screen/lnd/ldkInfo';
import LNDViewAdditionalInvoiceInformation from './screen/lnd/lndViewAdditionalInvoiceInformation';
import LnurlPay from './screen/lnd/lnurlPay';
import LnurlPaySuccess from './screen/lnd/lnurlPaySuccess';
import LnurlAuth from './screen/lnd/lnurlAuth';
import UnlockWith from './UnlockWith';
import DrawerList from './screen/wallets/drawerList';
import { isDesktop, isTablet, isHandset } from './blue_modules/environment';
@ -153,6 +153,7 @@ const WalletsRoot = () => {
<WalletsStack.Screen name="IsItMyAddress" component={IsItMyAddress} options={IsItMyAddress.navigationOptions(theme)} />
<WalletsStack.Screen name="LnurlPay" component={LnurlPay} options={LnurlPay.navigationOptions(theme)} />
<WalletsStack.Screen name="LnurlPaySuccess" component={LnurlPaySuccess} options={LnurlPaySuccess.navigationOptions(theme)} />
<WalletsStack.Screen name="LnurlAuth" component={LnurlAuth} options={LnurlAuth.navigationOptions(theme)} />
<WalletsStack.Screen
name="Success"
component={Success}
@ -436,7 +437,7 @@ const InitRoot = () => (
<InitStack.Screen
name="ReorderWallets"
component={ReorderWalletsStackRoot}
options={{ headerShown: false, gestureEnabled: false, stackPresentation: isDesktop ? 'containedModal' : 'fullScreenModal' }}
options={{ headerShown: false, gestureEnabled: false, stackPresentation: isDesktop ? 'containedModal' : 'modal' }}
/>
<InitStack.Screen
name={isHandset ? 'Navigation' : 'DrawerRoot'}
@ -484,19 +485,6 @@ const ExportMultisigCoordinationSetupRoot = () => {
);
};
const AOPPStack = createNativeStackNavigator();
const AOPPRoot = () => {
const theme = useTheme();
return (
<AOPPStack.Navigator screenOptions={{ headerHideShadow: true }}>
<AOPPStack.Screen name="SelectWallet" component={SelectWallet} options={SelectWallet.navigationOptions(theme)} />
<AOPPStack.Screen name="AOPP" component={AOPP} options={AOPP.navigationOptions(theme)} />
<AOPPStack.Screen name="SignVerify" component={SignVerify} options={SignVerify.navigationOptions(theme)} />
</AOPPStack.Navigator>
);
};
const RootStack = createNativeStackNavigator();
const NavigationDefaultOptions = { headerShown: false, stackPresentation: isDesktop ? 'containedModal' : 'modal' };
const Navigation = () => {
@ -530,7 +518,6 @@ const Navigation = () => {
<RootStack.Screen name="SelectWallet" component={SelectWallet} />
<RootStack.Screen name="ReceiveDetailsRoot" component={ReceiveDetailsStackRoot} options={NavigationDefaultOptions} />
<RootStack.Screen name="LappBrowserRoot" component={LappBrowserStackRoot} options={NavigationDefaultOptions} />
<RootStack.Screen name="AOPPRoot" component={AOPPRoot} options={NavigationDefaultOptions} />
<RootStack.Screen name="LDKOpenChannelRoot" component={LDKOpenChannelRoot} options={NavigationDefaultOptions} />
<RootStack.Screen

View File

@ -31,10 +31,6 @@ const styles = StyleSheet.create({
width: 64,
height: 64,
},
encrypted: {
width: 0.5,
height: 20,
},
});
const UnlockWith = () => {

View File

@ -14,9 +14,8 @@ import { FiatUnit } from './models/fiatUnit';
import { MultisigHDWallet } from './class';
function WatchConnectivity() {
const { walletsInitialized, wallets, fetchWalletTransactions, saveToDisk, txMetadata, preferredFiatCurrency } = useContext(
BlueStorageContext,
);
const { walletsInitialized, wallets, fetchWalletTransactions, saveToDisk, txMetadata, preferredFiatCurrency } =
useContext(BlueStorageContext);
const isReachable = useReachability();
const isInstalled = useInstalled(); // true | false
const messagesListenerActive = useRef(false);

View File

@ -140,7 +140,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "6.2.17"
versionName "6.2.19"
multiDexEnabled true
missingDimensionStrategy 'react-native-camera', 'general'
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
@ -218,7 +218,7 @@ dependencies {
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
from configurations.implementation
into 'libs'
}

View File

@ -70,7 +70,6 @@
<data android:scheme="bluewallet" />
<data android:scheme="lapp" />
<data android:scheme="blue" />
<data android:scheme="aopp" />
<data android:scheme="bankid" />
<data android:scheme="swish" />
<data android:scheme="http" />

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
android:insetTop="@dimen/abc_edit_text_inset_top_material"
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
<selector>
<!--
This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
-->
<item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
<item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
</selector>
</inset>

View File

@ -3,6 +3,7 @@
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
</style>
</resources>

View File

@ -47,7 +47,13 @@ allprojects {
includeModule("com.wei.android.lib", "fingerprintidentify")
}
}
mavenCentral()
mavenCentral {
// We don't want to fetch react-native from Maven Central as there are
// older versions over there.
content {
excludeGroup "com.facebook.react"
}
}
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm

View File

@ -9,7 +9,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
@ -31,4 +31,4 @@ org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.128.4
FLIPPER_VERSION=0.127.0

View File

@ -69,9 +69,7 @@ export function getMempoolTransactionsByAddress(address: string): Promise<Mempoo
export function estimateCurrentBlockheight(): number;
export function multiGetHistoryByAddress(
addresses: string[],
): Promise<
export function multiGetHistoryByAddress(addresses: string[]): Promise<
Record<
string,
{

View File

@ -1,72 +0,0 @@
import Frisbee from 'frisbee';
import url from 'url';
export default class AOPP {
static typeAny = 'any';
static typeP2wpkh = 'p2wpkh';
static typeP2sh = 'p2sh';
static typeP2pkh = 'p2pkh';
static getSegwitByAddressFormat(addressType) {
if (![AOPP.typeP2wpkh, AOPP.typeP2sh, AOPP.typeP2pkh].includes(addressType)) {
throw new Error('Work only for limited types');
}
switch (addressType) {
case 'p2wpkh':
return 'p2wpkh';
case 'p2sh':
return 'p2sh(p2wpkh)';
case 'p2pkh':
return undefined;
}
}
constructor(uri) {
this.uri = uri;
const { protocol, query } = url.parse(uri, true); // eslint-disable-line node/no-deprecated-api
if (protocol !== 'aopp:') throw new Error('Unsupported protocol');
if (query.v !== '0') throw new Error('Unsupported version');
if (!query.msg) throw new Error('Message required');
if (query.msg.lenth > 1024) throw new Error('Message is too big');
if (query.asset && query.asset !== 'btc') throw new Error('Unsupported asset');
if (query.format) {
if (![AOPP.typeAny, AOPP.typeP2wpkh, AOPP.typeP2sh, AOPP.typeP2pkh].includes(query.format)) {
throw new Error('Unsupported address format');
}
} else {
query.format = 'any';
}
if (!query.callback) throw new Error('Callback required');
this.v = Number(query.v);
this.msg = query.msg;
this.format = query.format;
this.callback = query.callback;
// parse callback url
const { hostname } = url.parse(this.callback, true); // eslint-disable-line node/no-deprecated-api
if (!hostname) throw new Error('Wrong callback');
this.callbackHostname = hostname;
this._api = new Frisbee({
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
}
async send({ address, signature }) {
const res = await this._api.post(this.callback, {
body: {
version: this.v,
address,
signature,
},
});
if (res.err) throw res.err;
}
}

View File

@ -17,8 +17,7 @@ class DeeplinkSchemaMatch {
lowercaseString.startsWith('lightning:') ||
lowercaseString.startsWith('blue:') ||
lowercaseString.startsWith('bluewallet:') ||
lowercaseString.startsWith('lapp:') ||
lowercaseString.startsWith('aopp:')
lowercaseString.startsWith('lapp:')
);
}
@ -206,15 +205,7 @@ class DeeplinkSchemaMatch {
} else {
const urlObject = url.parse(event.url, true); // eslint-disable-line node/no-deprecated-api
(async () => {
if (urlObject.protocol === 'aopp:') {
completionHandler([
'AOPPRoot',
{
screen: 'AOPP',
params: { uri: event.url },
},
]);
} else if (urlObject.protocol === 'bluewallet:' || urlObject.protocol === 'lapp:' || urlObject.protocol === 'blue:') {
if (urlObject.protocol === 'bluewallet:' || urlObject.protocol === 'lapp:' || urlObject.protocol === 'blue:') {
switch (urlObject.host) {
case 'openlappbrowser': {
console.log('opening LAPP', urlObject.query.url);

View File

@ -1,6 +1,9 @@
import { bech32 } from 'bech32';
import bolt11 from 'bolt11';
import { isTorDaemonDisabled } from '../blue_modules/environment';
import { parse } from 'url'; // eslint-disable-line node/no-deprecated-api
import { createHmac } from 'crypto';
import secp256k1 from 'secp256k1';
const CryptoJS = require('crypto-js');
const createHash = require('create-hash');
const torrific = require('../blue_modules/torrific');
@ -12,6 +15,7 @@ const ONION_REGEX = /^(http:\/\/[^/:@]+\.onion(?::\d{1,5})?)(\/.*)?$/; // regex
export default class Lnurl {
static TAG_PAY_REQUEST = 'payRequest'; // type of LNURL
static TAG_WITHDRAW_REQUEST = 'withdrawRequest'; // type of LNURL
static TAG_LOGIN_REQUEST = 'login'; // type of LNURL
constructor(url, AsyncStorage) {
this._lnurl = url;
@ -285,6 +289,37 @@ export default class Lnurl {
return this?._lnurlPayServicePayload?.commentAllowed ? parseInt(this._lnurlPayServicePayload.commentAllowed) : false;
}
authenticate(secret) {
return new Promise((resolve, reject) => {
if (!this._lnurl) throw new Error('this._lnurl is not set');
const url = parse(Lnurl.getUrlFromLnurl(this._lnurl), true); // eslint-disable-line node/no-deprecated-api
const hmac = createHmac('sha256', secret);
hmac.on('readable', async () => {
try {
const privateKey = hmac.read();
if (!privateKey) return;
const privateKeyBuf = Buffer.from(privateKey, 'hex');
const publicKey = secp256k1.publicKeyCreate(privateKeyBuf);
const signatureObj = secp256k1.sign(Buffer.from(url.query.k1, 'hex'), privateKeyBuf);
const derSignature = secp256k1.signatureExport(signatureObj.signature);
const reply = await this.fetchGet(`${url.href}&sig=${derSignature.toString('hex')}&key=${publicKey.toString('hex')}`);
if (reply.status === 'OK') {
resolve();
} else {
reject(reply.reason);
}
} catch (err) {
reject(err);
}
});
hmac.write(url.hostname);
hmac.end();
});
}
static isLightningAddress(address) {
// ensure only 1 `@` present:
if (address.split('@').length !== 2) return false;

View File

@ -29,7 +29,7 @@ export class AbstractHDWallet extends LegacyWallet {
constructor() {
super();
const Constructor = (this.constructor as unknown) as AbstractHDWalletStatics;
const Constructor = this.constructor as unknown as AbstractHDWalletStatics;
this.next_free_address_index = 0;
this.next_free_change_address_index = 0;
this.internal_addresses_cache = {}; // index => address
@ -133,7 +133,7 @@ export class AbstractHDWallet extends LegacyWallet {
let txs = [];
try {
txs = await BlueElectrum.getTransactionsByAddress(address);
} catch (Err) {
} catch (Err: any) {
console.warn('BlueElectrum.getTransactionsByAddress()', Err.message);
}
if (txs.length === 0) {
@ -171,7 +171,7 @@ export class AbstractHDWallet extends LegacyWallet {
let txs = [];
try {
txs = await BlueElectrum.getTransactionsByAddress(address);
} catch (Err) {
} catch (Err: any) {
console.warn('BlueElectrum.getTransactionsByAddress()', Err.message);
}
if (txs.length === 0) {

View File

@ -53,7 +53,7 @@ export class AbstractWallet {
masterFingerprint: number | false;
constructor() {
const Constructor = (this.constructor as unknown) as WalletStatics;
const Constructor = this.constructor as unknown as WalletStatics;
this.type = Constructor.type;
this.typeReadable = Constructor.typeReadable;
@ -84,7 +84,7 @@ export class AbstractWallet {
}
getID(): string {
const thisWithPassphrase = (this as unknown) as WalletWithPassphrase;
const thisWithPassphrase = this as unknown as WalletWithPassphrase;
const passphrase = thisWithPassphrase.getPassphrase ? thisWithPassphrase.getPassphrase() : '';
const path = this._derivationPath ?? '';
const string2hash = this.type + this.getSecret() + passphrase + path;

View File

@ -620,7 +620,7 @@ export class LegacyWallet extends AbstractWallet {
// undefined, true so it can verify Electrum signatures without errors
try {
return bitcoinMessage.verify(message, address, signature, undefined, true);
} catch (e) {
} catch (e: any) {
if (e.message === 'checkSegwitAlways can only be used with a compressed pubkey signature flagbyte') {
// If message created with uncompressed private key, it will throw this error
// in this case we should re-try with checkSegwitAlways flag off

View File

@ -667,6 +667,10 @@ export class LightningCustodianWallet extends LegacyWallet {
return false;
}
authenticate(lnurl) {
return lnurl.authenticate(this.secret);
}
}
/*

View File

@ -338,7 +338,7 @@ const styles = StyleSheet.create({
disabledButton: {
opacity: 0.5,
},
enabledButton: {
enabledButon: {
opacity: 1,
},
outdatedRateContainer: {

View File

@ -48,7 +48,7 @@ export const ArrowPicker = (props: ArrowPickerProps) => {
styles.wrapperCustom,
]}
>
<Icon size={24} name="chevron-left" type="ionicons" />
<Icon size={24} name="chevron-left" type="ionicons" tvParallaxProperties={undefined} />
</Pressable>
<View style={{ width: 200 }}>
<Text style={[styles.text, stylesHook.text]}>{props.isItemUnknown ? loc.send.fee_custom : keys[keyIndex]}</Text>
@ -72,7 +72,7 @@ export const ArrowPicker = (props: ArrowPickerProps) => {
styles.wrapperCustom,
]}
>
<Icon size={24} name="chevron-right" type="ionicons" />
<Icon size={24} name="chevron-right" type="ionicons" tvParallaxProperties={undefined} />
</Pressable>
</View>
);

View File

@ -61,9 +61,6 @@ const styles = StyleSheet.create({
nodeAlias: {
marginVertical: 16,
},
pending: {
marginVertical: 8,
},
canSendBar: {
height: 14,
maxHeight: 14,

View File

@ -16,37 +16,9 @@ const MultipleStepsListItem = props => {
checked = false,
} = props;
const stylesHook = StyleSheet.create({
root: {
flex: 1,
backgroundColor: colors.elevated,
},
textBtc: {
color: colors.buttonAlternativeTextColor,
},
textDestinationFirstFour: {
color: colors.buttonAlternativeTextColor,
},
textBtcUnitValue: {
color: colors.buttonAlternativeTextColor,
},
textDestination: {
color: colors.foregroundColor,
},
modalContentShort: {
backgroundColor: colors.elevated,
},
modalContent: {
backgroundColor: colors.elevated,
},
textFiat: {
color: colors.alternativeTextColor,
},
provideKeyButton: {
backgroundColor: colors.buttonDisabledBackgroundColor,
},
exportButton: {
backgroundColor: colors.buttonDisabledBackgroundColor,
},
provideKeyButtonText: {
color: colors.buttonTextColor,
},
@ -56,15 +28,9 @@ const MultipleStepsListItem = props => {
vaultKeyText: {
color: colors.alternativeTextColor,
},
feeFiatText: {
color: colors.alternativeTextColor,
},
vaultKeyCircleSuccess: {
backgroundColor: colors.msSuccessBG,
},
vaultKeyTextSigned: {
color: colors.msSuccessBG,
},
rowPartialLeftText: {
color: colors.alternativeTextColor,
},
@ -258,15 +224,6 @@ const styles = StyleSheet.create({
alignContent: 'center',
justifyContent: 'center',
},
grayButton: {
marginTop: 24,
marginLeft: 40,
height: 48,
borderRadius: 8,
justifyContent: 'center',
paddingHorizontal: 16,
marginBottom: 8,
},
activityIndicator: {
marginLeft: 40,
},
@ -281,15 +238,6 @@ const styles = StyleSheet.create({
rowPartialLeftText: {
textAlign: 'center',
},
vaultKeyTextSignedWrapper: { justifyContent: 'center', alignItems: 'center', paddingLeft: 16 },
vaultKeyTextSigned: { fontSize: 18, fontWeight: 'bold' },
exportButton: {
height: 48,
borderRadius: 8,
flex: 1,
justifyContent: 'center',
paddingHorizontal: 16,
},
});
export default MultipleStepsListItem;

View File

@ -2,24 +2,23 @@
import React, { useState, useMemo, useCallback, useContext, useEffect, useRef } from 'react';
import { Linking, StyleSheet, View } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import { BitcoinUnit } from '../models/bitcoinUnits';
import * as NavigationService from '../NavigationService';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation, useTheme } from '@react-navigation/native';
import { BitcoinUnit } from '../models/bitcoinUnits';
import * as NavigationService from '../NavigationService';
import loc, { formatBalanceWithoutSuffix, transactionTimeToReadable } from '../loc';
import Lnurl from '../class/lnurl';
import { BlueStorageContext } from '../blue_modules/storage-context';
import ToolTipMenu from './TooltipMenu';
import {
BlueListItem,
BlueTransactionExpiredIcon,
BlueTransactionIncomingIcon,
BlueTransactionOffchainIcon,
BlueTransactionOffchainIncomingIcon,
BlueTransactionOnchainIcon,
BlueTransactionOutgoingIcon,
BlueTransactionPendingIcon,
} from '../BlueComponents';
import { BlueListItem } from '../BlueComponents';
import TransactionExpiredIcon from '../components/icons/TransactionExpiredIcon';
import TransactionIncomingIcon from '../components/icons/TransactionIncomingIcon';
import TransactionOffchainIcon from '../components/icons/TransactionOffchainIcon';
import TransactionOffchainIncomingIcon from '../components/icons/TransactionOffchainIncomingIcon';
import TransactionOnchainIcon from '../components/icons/TransactionOnchainIcon';
import TransactionOutgoingIcon from '../components/icons/TransactionOutgoingIcon';
import TransactionPendingIcon from '../components/icons/TransactionPendingIcon';
export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUnit.BTC, walletID }) => {
const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1);
@ -114,7 +113,7 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
if (item.category === 'receive' && item.confirmations < 3) {
return (
<View style={styles.iconWidth}>
<BlueTransactionPendingIcon />
<TransactionPendingIcon />
</View>
);
}
@ -122,7 +121,7 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
if (item.type && item.type === 'bitcoind_tx') {
return (
<View style={styles.iconWidth}>
<BlueTransactionOnchainIcon />
<TransactionOnchainIcon />
</View>
);
}
@ -130,7 +129,7 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
// is it lightning offchain payment?
return (
<View style={styles.iconWidth}>
<BlueTransactionOffchainIcon />
<TransactionOffchainIcon />
</View>
);
}
@ -143,14 +142,14 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
if (invoiceExpiration < now) {
return (
<View style={styles.iconWidth}>
<BlueTransactionExpiredIcon />
<TransactionExpiredIcon />
</View>
);
}
} else {
return (
<View style={styles.iconWidth}>
<BlueTransactionOffchainIncomingIcon />
<TransactionOffchainIncomingIcon />
</View>
);
}
@ -159,19 +158,19 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
if (!item.confirmations) {
return (
<View style={styles.iconWidth}>
<BlueTransactionPendingIcon />
<TransactionPendingIcon />
</View>
);
} else if (item.value < 0) {
return (
<View style={styles.iconWidth}>
<BlueTransactionOutgoingIcon />
<TransactionOutgoingIcon />
</View>
);
} else {
return (
<View style={styles.iconWidth}>
<BlueTransactionIncomingIcon />
<TransactionIncomingIcon />
</View>
);
}

View File

@ -24,7 +24,6 @@ import { BlueStorageContext } from '../blue_modules/storage-context';
import { isHandset, isTablet, isDesktop } from '../blue_modules/environment';
const nStyles = StyleSheet.create({
root: {},
container: {
borderRadius: 10,
minHeight: Platform.OS === 'ios' ? 164 : 181,
@ -118,9 +117,6 @@ const iStyles = StyleSheet.create({
fontSize: 19,
writingDirection: I18nManager.isRTL ? 'rtl' : 'ltr',
},
activity: {
marginTop: 40,
},
balance: {
backgroundColor: 'transparent',
fontWeight: 'bold',
@ -258,17 +254,16 @@ WalletCarouselItem.propTypes = {
};
const cStyles = StyleSheet.create({
loading: {
position: 'absolute',
alignItems: 'center',
},
content: {
paddingTop: 16,
},
contentLargeScreen: {
paddingHorizontal: 16,
},
separatorStyle: { width: 16, height: 20 },
separatorStyle: {
width: 16,
height: 20,
},
});
const WalletsCarousel = forwardRef((props, ref) => {
@ -314,7 +309,7 @@ const WalletsCarousel = forwardRef((props, ref) => {
};
const { width } = useWindowDimensions();
const sliderHeight = 190;
const sliderHeight = 195;
const itemWidth = width * 0.82 > 375 ? 375 : width * 0.82;
return (
<FlatList
@ -332,7 +327,7 @@ const WalletsCarousel = forwardRef((props, ref) => {
showsHorizontalScrollIndicator={false}
initialNumToRender={10}
ListHeaderComponent={ListHeaderComponent}
style={props.horizontal ? { height: sliderHeight + 9 } : {}}
style={props.horizontal ? { minHeight: sliderHeight + 9 } : {}}
onScrollToIndexFailed={onScrollToIndexFailed}
{...props}
/>

View File

@ -0,0 +1,32 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { Avatar } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
ball: {
width: 30,
height: 30,
borderRadius: 15,
},
});
const PlusIcon = props => {
const { colors } = useTheme();
const stylesHook = StyleSheet.create({
ball: {
backgroundColor: colors.buttonBackgroundColor,
},
});
return (
<Avatar
rounded
containerStyle={[styles.ball, stylesHook.ball]}
icon={{ name: 'add', size: 22, type: 'ionicons', color: colors.foregroundColor }}
{...props}
/>
);
};
export default PlusIcon;

View File

@ -0,0 +1,39 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ballOutgoingExpired: {
width: 30,
height: 30,
borderRadius: 15,
justifyContent: 'center',
},
icon: {
left: 0,
top: 0,
},
});
const TransactionExpiredIcon = props => {
const { colors } = useTheme();
const stylesHooks = StyleSheet.create({
ballOutgoingExpired: {
backgroundColor: colors.ballOutgoingExpired,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ballOutgoingExpired, stylesHooks.ballOutgoingExpired]}>
<Icon name="clock" size={16} type="octicon" color="#9AA0AA" iconStyle={styles.icon} />
</View>
</View>
);
};
export default TransactionExpiredIcon;

View File

@ -0,0 +1,36 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ballIncoming: {
width: 30,
height: 30,
borderRadius: 15,
transform: [{ rotate: '-45deg' }],
justifyContent: 'center',
},
});
const TransactionIncomingIcon = props => {
const { colors } = useTheme();
const stylesHooks = StyleSheet.create({
ballIncoming: {
backgroundColor: colors.ballReceive,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ballIncoming, stylesHooks.ballIncoming]}>
<Icon name="arrow-down" size={16} type="font-awesome" color={colors.incomingForegroundColor} />
</View>
</View>
);
};
export default TransactionIncomingIcon;

View File

@ -0,0 +1,38 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ballOutgoingWithoutRotate: {
width: 30,
height: 30,
borderRadius: 15,
},
icon: {
left: 0,
marginTop: 6,
},
});
const TransactionOffchainIcon = props => {
const { colors } = useTheme();
const stylesHooks = StyleSheet.create({
ballOutgoingWithoutRotate: {
backgroundColor: colors.ballOutgoing,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ballOutgoingWithoutRotate, stylesHooks.ballOutgoingWithoutRotate]}>
<Icon name="bolt" size={16} type="font-awesome" color={colors.outgoingForegroundColor} iconStyle={styles.icon} />
</View>
</View>
);
};
export default TransactionOffchainIcon;

View File

@ -0,0 +1,38 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ballIncomingWithoutRotate: {
width: 30,
height: 30,
borderRadius: 15,
},
icon: {
left: 0,
marginTop: 6,
},
});
const TransactionOffchainIncomingIcon = props => {
const { colors } = useTheme();
const stylesHooks = StyleSheet.create({
ballIncomingWithoutRotate: {
backgroundColor: colors.ballReceive,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ballIncomingWithoutRotate, stylesHooks.ballIncomingWithoutRotate]}>
<Icon name="bolt" size={16} type="font-awesome" color={colors.incomingForegroundColor} iconStyle={styles.icon} />
</View>
</View>
);
};
export default TransactionOffchainIncomingIcon;

View File

@ -0,0 +1,41 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ballIncoming: {
width: 30,
height: 30,
borderRadius: 15,
transform: [{ rotate: '-45deg' }],
justifyContent: 'center',
},
icon: {
left: 0,
top: 0,
transform: [{ rotate: '-45deg' }],
},
});
const TransactionOnchainIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballIncoming: {
backgroundColor: colors.ballReceive,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ballIncoming, stylesBlueIconHooks.ballIncoming]}>
<Icon name="link" size={16} type="font-awesome" color={colors.incomingForegroundColor} iconStyle={styles.icon} />
</View>
</View>
);
};
export default TransactionOnchainIcon;

View File

@ -0,0 +1,36 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ballOutgoing: {
width: 30,
height: 30,
borderRadius: 15,
transform: [{ rotate: '225deg' }],
justifyContent: 'center',
},
});
const TransactionOutgoingIcon = props => {
const { colors } = useTheme();
const stylesBlueIconHooks = StyleSheet.create({
ballOutgoing: {
backgroundColor: colors.ballOutgoing,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ballOutgoing, stylesBlueIconHooks.ballOutgoing]}>
<Icon name="arrow-down" size={16} type="font-awesome" color={colors.outgoingForegroundColor} />
</View>
</View>
);
};
export default TransactionOutgoingIcon;

View File

@ -0,0 +1,38 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
boxIncoming: {
position: 'relative',
},
ball: {
width: 30,
height: 30,
borderRadius: 15,
},
icon: {
left: 0,
top: 7,
},
});
const TransactionPendingIcon = props => {
const { colors } = useTheme();
const stylesHook = StyleSheet.create({
ball: {
backgroundColor: colors.buttonBackgroundColor,
},
});
return (
<View style={styles.boxIncoming}>
<View style={[styles.ball, stylesHook.ball]}>
<Icon name="kebab-horizontal" size={16} type="octicon" color={colors.foregroundColor} iconStyle={styles.icon} />
</View>
</View>
);
};
export default TransactionPendingIcon;

View File

@ -45,83 +45,85 @@ const navigationStyle = (
},
formatter: OptionsFormatter,
): NavigationOptionsGetter => {
return theme => ({ navigation, route }) => {
let headerRight;
if (closeButton) {
const handleClose = closeButtonFunc
? () => closeButtonFunc({ navigation, route })
: () => {
Keyboard.dismiss();
navigation.goBack(null);
};
headerRight = () => (
<TouchableOpacity accessibilityRole="button" style={styles.button} onPress={handleClose} testID="NavigationCloseButton">
<Image source={theme.closeImage} />
</TouchableOpacity>
);
}
return theme =>
({ navigation, route }) => {
let headerRight;
if (closeButton) {
const handleClose = closeButtonFunc
? () => closeButtonFunc({ navigation, route })
: () => {
Keyboard.dismiss();
navigation.goBack(null);
};
headerRight = () => (
<TouchableOpacity accessibilityRole="button" style={styles.button} onPress={handleClose} testID="NavigationCloseButton">
<Image source={theme.closeImage} />
</TouchableOpacity>
);
}
let options: NavigationOptions = {
headerStyle: {
borderBottomWidth: 0,
elevation: 0,
shadowOpacity: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTitleStyle: {
fontWeight: '600',
color: theme.colors.foregroundColor,
},
headerRight: headerRight,
headerBackTitleVisible: false,
headerTintColor: theme.colors.foregroundColor,
...opts,
let options: NavigationOptions = {
headerStyle: {
borderBottomWidth: 0,
elevation: 0,
shadowOpacity: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTitleStyle: {
fontWeight: '600',
color: theme.colors.foregroundColor,
},
headerRight: headerRight,
headerBackTitleVisible: false,
headerTintColor: theme.colors.foregroundColor,
...opts,
};
if (formatter) {
options = formatter(options, { theme, navigation, route });
}
return options;
};
if (formatter) {
options = formatter(options, { theme, navigation, route });
}
return options;
};
};
export default navigationStyle;
export const navigationStyleTx = (opts: NavigationOptions, formatter: OptionsFormatter): NavigationOptionsGetter => {
return theme => ({ navigation, route }) => {
let options: NavigationOptions = {
headerStyle: {
borderBottomWidth: 0,
elevation: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTitleStyle: {
fontWeight: '600',
color: theme.colors.foregroundColor,
},
// headerBackTitle: null,
headerBackTitleVisible: false,
headerTintColor: theme.colors.foregroundColor,
headerLeft: () => (
<TouchableOpacity
accessibilityRole="button"
style={styles.button}
onPress={() => {
Keyboard.dismiss();
navigation.goBack(null);
}}
>
<Image source={theme.closeImage} />
</TouchableOpacity>
),
...opts,
return theme =>
({ navigation, route }) => {
let options: NavigationOptions = {
headerStyle: {
borderBottomWidth: 0,
elevation: 0,
shadowOffset: { height: 0, width: 0 },
},
headerTitleStyle: {
fontWeight: '600',
color: theme.colors.foregroundColor,
},
// headerBackTitle: null,
headerBackTitleVisible: false,
headerTintColor: theme.colors.foregroundColor,
headerLeft: () => (
<TouchableOpacity
accessibilityRole="button"
style={styles.button}
onPress={() => {
Keyboard.dismiss();
navigation.goBack(null);
}}
>
<Image source={theme.closeImage} />
</TouchableOpacity>
),
...opts,
};
if (formatter) {
options = formatter(options, { theme, navigation, route });
}
return options;
};
if (formatter) {
options = formatter(options, { theme, navigation, route });
}
return options;
};
};

View File

@ -0,0 +1,91 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import Animated, { interpolate, interpolateNode, multiply } from 'react-native-reanimated';
import { useDraggableFlatListContext } from '../context/draggableFlatListContext';
import { useNode } from '../hooks/useNode';
import { useOnCellActiveAnimation } from '../hooks/useOnCellActiveAnimation';
export { useOnCellActiveAnimation } from '../hooks/useOnCellActiveAnimation';
type ScaleProps = {
activeScale?: number;
children: React.ReactNode;
};
// support older versions of Reanimated v1 by using the old interpolate function
// if interpolateNode not available.
const interpolateFn = (interpolateNode || interpolate) as unknown as typeof interpolateNode;
export const ScaleDecorator = ({ activeScale = 1.1, children }: ScaleProps) => {
const { isActive, onActiveAnim } = useOnCellActiveAnimation({
animationConfig: { mass: 0.1, restDisplacementThreshold: 0.0001 },
});
const animScale = useNode(
interpolateFn(onActiveAnim, {
inputRange: [0, 1],
outputRange: [1, activeScale],
}),
);
const { horizontal } = useDraggableFlatListContext<any>();
const scale = isActive ? animScale : 1;
return (
<Animated.View style={[{ transform: [{ scaleX: scale }, { scaleY: scale }] }, horizontal && styles.horizontal]}>
{children}
</Animated.View>
);
};
type ShadowProps = {
children: React.ReactNode;
elevation?: number;
radius?: number;
color?: string;
opacity?: number;
};
export const ShadowDecorator = ({ elevation = 10, color = 'black', opacity = 0.25, radius = 5, children }: ShadowProps) => {
const { isActive, onActiveAnim } = useOnCellActiveAnimation();
const { horizontal } = useDraggableFlatListContext<any>();
const shadowOpacity = useNode(multiply(onActiveAnim, opacity));
const style = {
elevation: isActive ? elevation : 0,
shadowRadius: isActive ? radius : 0,
shadowColor: isActive ? color : 'transparent',
shadowOpacity: isActive ? shadowOpacity : 0,
};
return <Animated.View style={[style, horizontal && styles.horizontal]}>{children}</Animated.View>;
};
type OpacityProps = {
activeOpacity?: number;
children: React.ReactNode;
};
export const OpacityDecorator = ({ activeOpacity = 0.25, children }: OpacityProps) => {
const { isActive, onActiveAnim } = useOnCellActiveAnimation();
const { horizontal } = useDraggableFlatListContext<any>();
const opacity = useNode(
interpolateFn(onActiveAnim, {
inputRange: [0, 1],
outputRange: [1, activeOpacity],
}),
);
const style = {
opacity: isActive ? opacity : 1,
};
return <Animated.View style={[style, horizontal && styles.horizontal]}>{children}</Animated.View>;
};
const styles = StyleSheet.create({
horizontal: {
flexDirection: 'row',
flex: 1,
},
});

View File

@ -0,0 +1,132 @@
/* eslint-disable react-native/no-inline-styles */
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef } from 'react';
// @ts-ignore Ignore
import { findNodeHandle, LayoutChangeEvent, MeasureLayoutOnSuccessCallback, StyleProp, ViewStyle } from 'react-native';
import Animated, { cond, useValue } from 'react-native-reanimated';
import { useDraggableFlatListContext } from '../context/draggableFlatListContext';
import { isAndroid, isIOS, isReanimatedV2, isWeb } from '../constants';
import { useCellTranslate } from '../hooks/useCellTranslate';
import { typedMemo } from '../utils';
import { useRefs } from '../context/refContext';
import { useAnimatedValues } from '../context/animatedValueContext';
import CellProvider from '../context/cellContext';
type Props<T> = {
item: T;
index: number;
children: React.ReactNode;
onLayout: (e: LayoutChangeEvent) => void;
style?: StyleProp<ViewStyle>;
};
function CellRendererComponent<T>(props: Props<T>) {
const { item, index, onLayout, children } = props;
const currentIndexAnim = useValue(index);
useLayoutEffect(() => {
currentIndexAnim.setValue(index);
}, [index, currentIndexAnim]);
const viewRef = useRef<Animated.View>(null);
const { cellDataRef, propsRef, scrollOffsetRef, containerRef } = useRefs<T>();
const { horizontalAnim } = useAnimatedValues();
const { activeKey, keyExtractor, horizontal } = useDraggableFlatListContext<T>();
const key = keyExtractor(item, index);
const offset = useValue<number>(-1);
const size = useValue<number>(-1);
const translate = useCellTranslate({
cellOffset: offset,
cellSize: size,
cellIndex: currentIndexAnim,
});
useMemo(() => {
// prevent flicker on web
if (isWeb) translate.setValue(0);
}, [index]); // eslint-disable-line react-hooks/exhaustive-deps
const isActive = activeKey === key;
const style = useMemo(
() => ({
transform: [{ translateX: cond(horizontalAnim, translate, 0) }, { translateY: cond(horizontalAnim, 0, translate) }],
}),
[horizontalAnim, translate],
);
const updateCellMeasurements = useCallback(() => {
const onSuccess: MeasureLayoutOnSuccessCallback = (x, y, w, h) => {
if (isWeb && horizontal) x += scrollOffsetRef.current;
const cellOffset = horizontal ? x : y;
const cellSize = horizontal ? w : h;
cellDataRef.current.set(key, {
measurements: { size: cellSize, offset: cellOffset },
});
size.setValue(cellSize);
offset.setValue(cellOffset);
};
const onFail = () => {
if (propsRef.current?.debug) {
console.log(`## on measure fail, index: ${index}`);
}
};
// findNodeHandle is being deprecated. This is no longer necessary if using reanimated v2
// remove once v1 is no longer supported
const containerNode = containerRef.current;
const viewNode = isReanimatedV2 ? viewRef.current : viewRef.current?.getNode();
// @ts-ignore Ignore
const nodeHandle = isReanimatedV2 ? containerNode : findNodeHandle(containerNode);
if (viewNode && nodeHandle) {
// @ts-ignore Ignore
viewNode.measureLayout(nodeHandle, onSuccess, onFail);
}
}, [cellDataRef, horizontal, index, key, offset, propsRef, size, scrollOffsetRef, containerRef]);
useEffect(() => {
if (isWeb) {
// onLayout isn't called on web when the cell index changes, so we manually re-measure
updateCellMeasurements();
}
}, [index, updateCellMeasurements]);
const onCellLayout = useCallback(
(e: LayoutChangeEvent) => {
updateCellMeasurements();
onLayout(e);
},
[updateCellMeasurements, onLayout],
);
// changing zIndex crashes android:
// https://github.com/facebook/react-native/issues/28751
return (
<Animated.View
{...props}
ref={viewRef}
onLayout={onCellLayout}
style={[
isAndroid && { elevation: isActive ? 1 : 0 },
{ flexDirection: horizontal ? 'row' : 'column' },
(isWeb || isIOS) && { zIndex: isActive ? 999 : 0 },
]}
pointerEvents={activeKey ? 'none' : 'auto'}
>
<Animated.View
{...props}
// Including both animated styles and non-animated styles causes react-native-web
// to ignore updates in non-animated styles. Solution is to separate animated styles from non-animated styles
style={[props.style, style]}
>
<CellProvider isActive={isActive}>{children}</CellProvider>
</Animated.View>
</Animated.View>
);
}
export default typedMemo(CellRendererComponent);

View File

@ -0,0 +1,326 @@
/* eslint-disable react-hooks/exhaustive-deps */
// @ts-ignore: Ignore
import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react';
// @ts-ignore: Ignore
import { ListRenderItem, FlatListProps, NativeScrollEvent, NativeSyntheticEvent, LayoutChangeEvent } from 'react-native';
import {
PanGestureHandler,
State as GestureState,
FlatList,
PanGestureHandlerGestureEvent,
PanGestureHandlerStateChangeEvent,
} from 'react-native-gesture-handler';
import Animated, { and, block, call, cond, eq, event, greaterThan, neq, not, onChange, or, set, sub } from 'react-native-reanimated';
import CellRendererComponent from './CellRendererComponent';
import { DEFAULT_PROPS, isWeb } from '../constants';
import PlaceholderItem from './PlaceholderItem';
import RowItem from './RowItem';
import ScrollOffsetListener from './ScrollOffsetListener';
import { DraggableFlatListProps } from '../types';
import { useAutoScroll } from '../hooks/useAutoScroll';
import { useNode } from '../hooks/useNode';
import PropsProvider from '../context/propsContext';
import AnimatedValueProvider, { useAnimatedValues } from '../context/animatedValueContext';
import RefProvider, { useRefs } from '../context/refContext';
import DraggableFlatListProvider from '../context/draggableFlatListContext';
type RNGHFlatListProps<T> = Animated.AnimateProps<
FlatListProps<T> & {
ref: React.Ref<FlatList<T>>;
simultaneousHandlers?: React.Ref<any> | React.Ref<any>[];
}
>;
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList) as unknown as <T>(props: RNGHFlatListProps<T>) => React.ReactElement;
function DraggableFlatListInner<T>(props: DraggableFlatListProps<T>) {
const { cellDataRef, containerRef, flatListRef, isTouchActiveRef, keyToIndexRef, panGestureHandlerRef, propsRef, scrollOffsetRef } =
useRefs<T>();
const {
activationDistance,
activeCellOffset,
activeCellSize,
activeIndexAnim,
containerSize,
disabled,
panGestureState,
resetTouchedCell,
scrollOffset,
scrollViewSize,
spacerIndexAnim,
touchAbsolute,
touchInit,
} = useAnimatedValues();
const {
dragHitSlop = DEFAULT_PROPS.dragHitSlop,
scrollEnabled = DEFAULT_PROPS.scrollEnabled,
activationDistance: activationDistanceProp = DEFAULT_PROPS.activationDistance,
} = props;
const [activeKey, setActiveKey] = useState<string | null>(null);
const keyExtractor = useCallback(
(item: T, index: number) => {
if (propsRef.current.keyExtractor) return propsRef.current.keyExtractor(item, index);
else throw new Error('You must provide a keyExtractor to DraggableFlatList');
},
[propsRef],
);
useLayoutEffect(() => {
props.data.forEach((d, i) => {
const key = keyExtractor(d, i);
keyToIndexRef.current.set(key, i);
});
}, [props.data, keyExtractor, keyToIndexRef]);
const drag = useCallback(
(activeKey: string) => {
if (!isTouchActiveRef.current.js) return;
const index = keyToIndexRef.current.get(activeKey);
const cellData = cellDataRef.current.get(activeKey);
if (cellData) {
activeCellOffset.setValue(cellData.measurements.offset - scrollOffsetRef.current);
activeCellSize.setValue(cellData.measurements.size);
}
const { onDragBegin } = propsRef.current;
if (index !== undefined) {
spacerIndexAnim.setValue(index);
activeIndexAnim.setValue(index);
setActiveKey(activeKey);
onDragBegin?.(index);
}
},
[
isTouchActiveRef,
keyToIndexRef,
cellDataRef,
propsRef,
activeCellOffset,
scrollOffsetRef,
activeCellSize,
spacerIndexAnim,
activeIndexAnim,
],
);
const autoScrollNode = useAutoScroll();
const onContainerLayout = ({ nativeEvent: { layout } }: LayoutChangeEvent) => {
containerSize.setValue(props.horizontal ? layout.width : layout.height);
};
const onListContentSizeChange = (w: number, h: number) => {
scrollViewSize.setValue(props.horizontal ? w : h);
props.onContentSizeChange?.(w, h);
};
const onContainerTouchStart = () => {
isTouchActiveRef.current.js = true;
isTouchActiveRef.current.native.setValue(1);
return false;
};
const onContainerTouchEnd = () => {
isTouchActiveRef.current.js = false;
isTouchActiveRef.current.native.setValue(0);
};
let dynamicProps = {};
if (activationDistanceProp) {
const activeOffset = [-activationDistanceProp, activationDistanceProp];
dynamicProps = props.horizontal ? { activeOffsetX: activeOffset } : { activeOffsetY: activeOffset };
}
const extraData = useMemo(
() => ({
activeKey,
extraData: props.extraData,
}),
[activeKey, props.extraData],
);
const renderItem: ListRenderItem<T> = useCallback(
// @ts-ignore: Ignore
({ item, index }) => {
const key = keyExtractor(item, index);
if (index !== keyToIndexRef.current.get(key)) keyToIndexRef.current.set(key, index);
return <RowItem item={item} itemKey={key} renderItem={props.renderItem} drag={drag} extraData={props.extraData} />;
},
[props.renderItem, props.extraData, drag, keyExtractor],
);
const resetHoverState = useCallback(() => {
activeIndexAnim.setValue(-1);
spacerIndexAnim.setValue(-1);
touchAbsolute.setValue(0);
disabled.setValue(0);
requestAnimationFrame(() => {
setActiveKey(null);
});
}, [activeIndexAnim, spacerIndexAnim, touchAbsolute, disabled]);
const onRelease = ([index]: readonly number[]) => {
// This shouldn't be necessary but seems to fix a bug where sometimes
// native values wouldn't update
isTouchActiveRef.current.native.setValue(0);
props.onRelease?.(index);
};
const onDragEnd = useCallback(
([from, to]: readonly number[]) => {
const { onDragEnd, data } = propsRef.current;
if (onDragEnd) {
const newData = [...data];
if (from !== to) {
newData.splice(from, 1);
newData.splice(to, 0, data[from]);
}
onDragEnd({ from, to, data: newData });
}
resetHoverState();
},
[resetHoverState, propsRef],
);
const onGestureRelease = useNode(
cond(
greaterThan(activeIndexAnim, -1),
[set(disabled, 1), set(isTouchActiveRef.current.native, 0), call([activeIndexAnim], onRelease)],
[call([activeIndexAnim], resetHoverState), resetTouchedCell],
),
);
const onPanStateChange = useMemo(
() =>
event([
{
nativeEvent: ({ state, x, y }: PanGestureHandlerStateChangeEvent['nativeEvent']) =>
block([
cond(and(neq(state, panGestureState), not(disabled)), [
cond(
or(
eq(state, GestureState.BEGAN), // Called on press in on Android, NOT on ios!
// GestureState.BEGAN may be skipped on fast swipes
and(eq(state, GestureState.ACTIVE), neq(panGestureState, GestureState.BEGAN)),
),
[set(touchAbsolute, props.horizontal ? x : y), set(touchInit, touchAbsolute)],
),
cond(eq(state, GestureState.ACTIVE), [
set(activationDistance, sub(props.horizontal ? x : y, touchInit)),
set(touchAbsolute, props.horizontal ? x : y),
]),
]),
cond(neq(panGestureState, state), [
set(panGestureState, state),
cond(or(eq(state, GestureState.END), eq(state, GestureState.CANCELLED), eq(state, GestureState.FAILED)), onGestureRelease),
]),
]),
},
]),
[activationDistance, props.horizontal, panGestureState, disabled, onGestureRelease, touchAbsolute, touchInit],
);
const onPanGestureEvent = useMemo(
() =>
event([
{
nativeEvent: ({ x, y }: PanGestureHandlerGestureEvent['nativeEvent']) =>
cond(and(greaterThan(activeIndexAnim, -1), eq(panGestureState, GestureState.ACTIVE), not(disabled)), [
set(touchAbsolute, props.horizontal ? x : y),
]),
},
]),
[activeIndexAnim, disabled, panGestureState, props.horizontal, touchAbsolute],
);
const scrollHandler = useMemo(() => {
// Web doesn't seem to like animated events
const webOnScroll = ({
nativeEvent: {
contentOffset: { x, y },
},
}: NativeSyntheticEvent<NativeScrollEvent>) => {
scrollOffset.setValue(props.horizontal ? x : y);
};
const mobileOnScroll = event([
{
nativeEvent: ({ contentOffset }: NativeScrollEvent) =>
block([set(scrollOffset, props.horizontal ? contentOffset.x : contentOffset.y), autoScrollNode]),
},
]);
return isWeb ? webOnScroll : mobileOnScroll;
}, [autoScrollNode, props.horizontal, scrollOffset]);
return (
<DraggableFlatListProvider activeKey={activeKey} onDragEnd={onDragEnd} keyExtractor={keyExtractor} horizontal={!!props.horizontal}>
<PanGestureHandler
ref={panGestureHandlerRef}
hitSlop={dragHitSlop}
onHandlerStateChange={onPanStateChange}
onGestureEvent={onPanGestureEvent}
simultaneousHandlers={props.simultaneousHandlers}
{...dynamicProps}
>
<Animated.View
style={props.containerStyle}
ref={containerRef}
onLayout={onContainerLayout}
onTouchEnd={onContainerTouchEnd}
onStartShouldSetResponderCapture={onContainerTouchStart}
// @ts-ignore Ignore
onClick={onContainerTouchEnd}
>
<ScrollOffsetListener
scrollOffset={scrollOffset}
onScrollOffsetChange={([offset]) => {
scrollOffsetRef.current = offset;
props.onScrollOffsetChange?.(offset);
}}
/>
{!!props.renderPlaceholder && <PlaceholderItem renderPlaceholder={props.renderPlaceholder} />}
<AnimatedFlatList
{...props}
CellRendererComponent={CellRendererComponent}
ref={flatListRef}
onContentSizeChange={onListContentSizeChange}
scrollEnabled={!activeKey && scrollEnabled}
renderItem={renderItem}
extraData={extraData}
keyExtractor={keyExtractor}
onScroll={scrollHandler}
scrollEventThrottle={16}
simultaneousHandlers={props.simultaneousHandlers}
removeClippedSubviews={false}
/>
<Animated.Code dependencies={[]}>
{() => block([onChange(isTouchActiveRef.current.native, cond(not(isTouchActiveRef.current.native), onGestureRelease))])}
</Animated.Code>
</Animated.View>
</PanGestureHandler>
</DraggableFlatListProvider>
);
}
function DraggableFlatList<T>(props: DraggableFlatListProps<T>, ref: React.ForwardedRef<FlatList<T>>) {
return (
<PropsProvider {...props}>
<AnimatedValueProvider>
<RefProvider flatListRef={ref}>
<DraggableFlatListInner {...props} />
</RefProvider>
</AnimatedValueProvider>
</PropsProvider>
);
}
// Generic forwarded ref type assertion taken from:
// https://fettblog.eu/typescript-react-generic-forward-refs/#option-1%3A-type-assertion
export default React.forwardRef(DraggableFlatList) as <T>(
props: DraggableFlatListProps<T> & { ref?: React.ForwardedRef<FlatList<T>> },
) => ReturnType<typeof DraggableFlatList>;

View File

@ -0,0 +1,75 @@
// @ts-ignore: Ignore
import React, { useCallback, useState } from 'react';
import { StyleSheet } from 'react-native';
import Animated, { call, useCode, onChange, greaterThan, cond, sub, block } from 'react-native-reanimated';
import { useAnimatedValues } from '../context/animatedValueContext';
import { useDraggableFlatListContext } from '../context/draggableFlatListContext';
import { useProps } from '../context/propsContext';
import { useRefs } from '../context/refContext';
import { useNode } from '../hooks/useNode';
import { RenderPlaceholder } from '../types';
import { typedMemo } from '../utils';
type Props<T> = {
renderPlaceholder?: RenderPlaceholder<T>;
};
function PlaceholderItem<T>({ renderPlaceholder }: Props<T>) {
const { activeCellSize, placeholderOffset, spacerIndexAnim, scrollOffset } = useAnimatedValues();
const [placeholderSize, setPlaceholderSize] = useState(0);
const { keyToIndexRef, propsRef } = useRefs<T>();
const { activeKey } = useDraggableFlatListContext();
const { horizontal } = useProps();
const onPlaceholderIndexChange = useCallback(
(index: number) => {
propsRef.current.onPlaceholderIndexChange?.(index);
},
[propsRef],
);
useCode(
() =>
block([
onChange(
activeCellSize,
call([activeCellSize], ([size]) => {
// Using animated values to set height caused a bug where item wouldn't correctly update
// so instead we mirror the animated value in component state.
setPlaceholderSize(size);
}),
),
onChange(
spacerIndexAnim,
call([spacerIndexAnim], ([i]) => {
onPlaceholderIndexChange(i);
if (i === -1) setPlaceholderSize(0);
}),
),
]),
[],
);
const translateKey = horizontal ? 'translateX' : 'translateY';
const sizeKey = horizontal ? 'width' : 'height';
const opacity = useNode(cond(greaterThan(spacerIndexAnim, -1), 1, 0));
const activeIndex = activeKey ? keyToIndexRef.current.get(activeKey) : undefined;
const activeItem = activeIndex === undefined ? null : propsRef.current?.data[activeIndex];
const animStyle = {
opacity,
[sizeKey]: placeholderSize,
transform: [{ [translateKey]: sub(placeholderOffset, scrollOffset) }] as unknown as Animated.AnimatedTransform,
};
return (
<Animated.View pointerEvents={activeKey ? 'auto' : 'none'} style={[StyleSheet.absoluteFill, animStyle]}>
{!activeItem || activeIndex === undefined ? null : renderPlaceholder?.({ item: activeItem, index: activeIndex })}
</Animated.View>
);
}
export default typedMemo(PlaceholderItem);

View File

@ -0,0 +1,61 @@
/* eslint-disable react/no-unused-prop-types */
// @ts-ignore: Ignore
import React, { useCallback, useRef } from 'react';
import { useDraggableFlatListContext } from '../context/draggableFlatListContext';
import { useRefs } from '../context/refContext';
import { RenderItem } from '../types';
import { typedMemo } from '../utils';
type Props<T> = {
extraData?: any;
drag: (itemKey: string) => void;
item: T;
renderItem: RenderItem<T>;
itemKey: string;
debug?: boolean;
};
function RowItem<T>(props: Props<T>) {
const propsRef = useRef(props);
propsRef.current = props;
const { activeKey } = useDraggableFlatListContext();
const activeKeyRef = useRef(activeKey);
activeKeyRef.current = activeKey;
const { keyToIndexRef } = useRefs();
const drag = useCallback(() => {
const { drag, itemKey, debug } = propsRef.current;
if (activeKeyRef.current) {
// already dragging an item, noop
if (debug) console.log('## attempt to drag item while another item is already active, noop');
}
drag(itemKey);
}, []);
const { renderItem, item, itemKey } = props;
return (
<MemoizedInner
isActive={activeKey === itemKey}
drag={drag}
renderItem={renderItem}
item={item}
index={keyToIndexRef.current.get(itemKey)}
/>
);
}
export default typedMemo(RowItem);
type InnerProps<T> = {
isActive: boolean;
item: T;
index?: number;
drag: () => void;
renderItem: RenderItem<T>;
};
function Inner<T>({ isActive, item, drag, index, renderItem }: InnerProps<T>) {
return renderItem({ isActive, item, drag, index }) as JSX.Element;
}
const MemoizedInner = typedMemo(Inner);

View File

@ -0,0 +1,14 @@
import Animated, { call, onChange, useCode } from 'react-native-reanimated';
import { typedMemo } from '../utils';
type Props = {
scrollOffset: Animated.Value<number>;
onScrollOffsetChange: (offset: readonly number[]) => void;
};
const ScrollOffsetListener = ({ scrollOffset, onScrollOffsetChange }: Props) => {
useCode(() => onChange(scrollOffset, call([scrollOffset], onScrollOffsetChange)), []);
return null;
};
export default typedMemo(ScrollOffsetListener);

View File

@ -0,0 +1,37 @@
// @ts-ignore: Ignore
import { Platform } from 'react-native';
import { PanGestureHandlerProperties } from 'react-native-gesture-handler';
// @ts-ignore: Ignore
import { useSharedValue, WithSpringConfig } from 'react-native-reanimated';
// Fire onScrollComplete when within this many px of target offset
export const SCROLL_POSITION_TOLERANCE = 2;
export const DEFAULT_ANIMATION_CONFIG: WithSpringConfig = {
damping: 20,
mass: 0.2,
stiffness: 100,
overshootClamping: false,
restSpeedThreshold: 0.2,
restDisplacementThreshold: 0.2,
};
export const DEFAULT_PROPS = {
autoscrollThreshold: 30,
autoscrollSpeed: 100,
animationConfig: DEFAULT_ANIMATION_CONFIG,
scrollEnabled: true,
dragHitSlop: 0 as PanGestureHandlerProperties['hitSlop'],
activationDistance: 0,
dragItemOverflow: false,
};
export const isIOS = Platform.OS === 'ios';
export const isAndroid = Platform.OS === 'android';
export const isWeb = Platform.OS === 'web';
// Is there a better way to check for v2?
export const isReanimatedV2 = !!useSharedValue;
if (!isReanimatedV2) {
console.warn('Your version of react-native-reanimated is too old for react-native-draggable-flatlist. It may not work as expected.');
}

View File

@ -0,0 +1,121 @@
import React, { useContext, useMemo } from 'react';
import { add, and, block, greaterThan, max, min, set, sub, useValue } from 'react-native-reanimated';
import { State as GestureState } from 'react-native-gesture-handler';
import { useNode } from '../hooks/useNode';
import { useProps } from './propsContext';
if (!useValue) {
throw new Error('Incompatible Reanimated version (useValue not found)');
}
const AnimatedValueContext = React.createContext<ReturnType<typeof useSetupAnimatedValues> | undefined>(undefined);
export default function AnimatedValueProvider({ children }: { children: React.ReactNode }) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const value = useSetupAnimatedValues();
return <AnimatedValueContext.Provider value={value}>{children}</AnimatedValueContext.Provider>;
}
export function useAnimatedValues() {
const value = useContext(AnimatedValueContext);
if (!value) {
throw new Error('useAnimatedValues must be called from within AnimatedValueProvider!');
}
return value;
}
function useSetupAnimatedValues<T>() {
const props = useProps<T>();
const containerSize = useValue<number>(0);
const touchInit = useValue<number>(0); // Position of initial touch
const activationDistance = useValue<number>(0); // Distance finger travels from initial touch to when dragging begins
const touchAbsolute = useValue<number>(0); // Finger position on screen, relative to container
const panGestureState = useValue<GestureState>(GestureState.UNDETERMINED);
const isTouchActiveNative = useValue<number>(0);
const disabled = useValue<number>(0);
const horizontalAnim = useValue(props.horizontal ? 1 : 0);
const activeIndexAnim = useValue<number>(-1); // Index of hovering cell
const spacerIndexAnim = useValue<number>(-1); // Index of hovered-over cell
const activeCellSize = useValue<number>(0); // Height or width of acctive cell
const activeCellOffset = useValue<number>(0); // Distance between active cell and edge of container
const isDraggingCell = useNode(and(isTouchActiveNative, greaterThan(activeIndexAnim, -1)));
const scrollOffset = useValue<number>(0);
const scrollViewSize = useValue<number>(0);
const touchCellOffset = useNode(sub(touchInit, activeCellOffset));
const hoverAnimUnconstrained = useNode(sub(sub(touchAbsolute, activationDistance), touchCellOffset));
const hoverAnimConstrained = useNode(min(sub(containerSize, activeCellSize), max(0, hoverAnimUnconstrained)));
const hoverAnim = props.dragItemOverflow ? hoverAnimUnconstrained : hoverAnimConstrained;
const hoverOffset = useNode(add(hoverAnim, scrollOffset));
const placeholderOffset = useValue<number>(0);
// Note: this could use a refactor as it combines touch state + cell animation
const resetTouchedCell = useNode(block([set(touchAbsolute, 0), set(touchInit, 0), set(activeCellOffset, 0), set(activationDistance, 0)]));
const value = useMemo(
() => ({
activationDistance,
activeCellOffset,
activeCellSize,
activeIndexAnim,
containerSize,
disabled,
horizontalAnim,
hoverAnim,
hoverAnimConstrained,
hoverAnimUnconstrained,
hoverOffset,
isDraggingCell,
isTouchActiveNative,
panGestureState,
placeholderOffset,
resetTouchedCell,
scrollOffset,
scrollViewSize,
spacerIndexAnim,
touchAbsolute,
touchCellOffset,
touchInit,
}),
[
activationDistance,
activeCellOffset,
activeCellSize,
activeIndexAnim,
containerSize,
disabled,
horizontalAnim,
hoverAnim,
hoverAnimConstrained,
hoverAnimUnconstrained,
hoverOffset,
isDraggingCell,
isTouchActiveNative,
panGestureState,
placeholderOffset,
resetTouchedCell,
scrollOffset,
scrollViewSize,
spacerIndexAnim,
touchAbsolute,
touchCellOffset,
touchInit,
],
);
return value;
}

View File

@ -0,0 +1,30 @@
import React, { useContext, useMemo } from 'react';
type CellContextValue = {
isActive: boolean;
};
const CellContext = React.createContext<CellContextValue | undefined>(undefined);
type Props = {
isActive: boolean;
children: React.ReactNode;
};
export default function CellProvider({ isActive, children }: Props) {
const value = useMemo(
() => ({
isActive,
}),
[isActive],
);
return <CellContext.Provider value={value}>{children}</CellContext.Provider>;
}
export function useIsActive() {
const value = useContext(CellContext);
if (!value) {
throw new Error('useIsActive must be called from within CellProvider!');
}
return value.isActive;
}

View File

@ -0,0 +1,35 @@
import React, { useContext, useMemo } from 'react';
type Props<T> = {
activeKey: string | null;
onDragEnd: ([from, to]: readonly number[]) => void;
keyExtractor: (item: T, index: number) => string;
horizontal: boolean;
children: React.ReactNode;
};
type DraggableFlatListContextValue<T> = Omit<Props<T>, 'children'>;
const DraggableFlatListContext = React.createContext<DraggableFlatListContextValue<any> | undefined>(undefined);
export default function DraggableFlatListProvider<T>({ activeKey, onDragEnd, keyExtractor, horizontal, children }: Props<T>) {
const value = useMemo(
() => ({
activeKey,
keyExtractor,
onDragEnd,
horizontal,
}),
[activeKey, onDragEnd, keyExtractor, horizontal],
);
return <DraggableFlatListContext.Provider value={value}>{children}</DraggableFlatListContext.Provider>;
}
export function useDraggableFlatListContext<T>() {
const value = useContext(DraggableFlatListContext);
if (!value) {
throw new Error('useDraggableFlatListContext must be called within DraggableFlatListProvider');
}
return value as DraggableFlatListContextValue<T>;
}

View File

@ -0,0 +1,18 @@
import React, { useContext } from 'react';
import { DraggableFlatListProps } from '../types';
const PropsContext = React.createContext<DraggableFlatListProps<any> | undefined>(undefined);
type Props<T> = DraggableFlatListProps<T> & { children: React.ReactNode };
export default function PropsProvider<T>({ children, ...props }: Props<T>) {
return <PropsContext.Provider value={props}>{children}</PropsContext.Provider>;
}
export function useProps<T>() {
const value = useContext(PropsContext) as DraggableFlatListProps<T> | undefined;
if (!value) {
throw new Error('useProps must be called from within PropsProvider!');
}
return value;
}

View File

@ -0,0 +1,89 @@
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-use-before-define */
import React, { useContext, useMemo, useRef } from 'react';
import { FlatList, PanGestureHandler } from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated';
import { DEFAULT_PROPS } from '../constants';
import { useProps } from './propsContext';
import { useAnimatedValues } from './animatedValueContext';
import { CellData, DraggableFlatListProps } from '../types';
type RefContextValue<T> = {
propsRef: React.MutableRefObject<DraggableFlatListProps<T>>;
animationConfigRef: React.MutableRefObject<Animated.SpringConfig>;
cellDataRef: React.MutableRefObject<Map<string, CellData>>;
keyToIndexRef: React.MutableRefObject<Map<string, number>>;
containerRef: React.RefObject<Animated.View>;
flatListRef: React.RefObject<FlatList<T>> | React.ForwardedRef<FlatList<T>>;
panGestureHandlerRef: React.RefObject<PanGestureHandler>;
scrollOffsetRef: React.MutableRefObject<number>;
isTouchActiveRef: React.MutableRefObject<{
native: Animated.Value<number>;
js: boolean;
}>;
};
const RefContext = React.createContext<RefContextValue<any> | undefined>(undefined);
export default function RefProvider<T>({
children,
flatListRef,
}: {
children: React.ReactNode;
flatListRef: React.ForwardedRef<FlatList<T>>;
}) {
const value = useSetupRefs<T>({ flatListRef });
return <RefContext.Provider value={value}>{children}</RefContext.Provider>;
}
export function useRefs<T>() {
const value = useContext(RefContext);
if (!value) {
throw new Error('useRefs must be called from within a RefContext.Provider!');
}
return value as RefContextValue<T>;
}
function useSetupRefs<T>({ flatListRef: flatListRefProp }: { flatListRef: React.ForwardedRef<FlatList<T>> }) {
const props = useProps<T>();
const { animationConfig = DEFAULT_PROPS.animationConfig } = props;
const { isTouchActiveNative } = useAnimatedValues();
const propsRef = useRef(props);
propsRef.current = props;
const animConfig = {
...DEFAULT_PROPS.animationConfig,
...animationConfig,
} as Animated.SpringConfig;
const animationConfigRef = useRef(animConfig);
animationConfigRef.current = animConfig;
const cellDataRef = useRef(new Map<string, CellData>());
const keyToIndexRef = useRef(new Map<string, number>());
const containerRef = useRef<Animated.View>(null);
const flatListRefInner = useRef<FlatList<T>>(null);
const flatListRef = flatListRefProp || flatListRefInner;
const panGestureHandlerRef = useRef<PanGestureHandler>(null);
const scrollOffsetRef = useRef(0);
const isTouchActiveRef = useRef({
native: isTouchActiveNative,
js: false,
});
const refs = useMemo(
() => ({
animationConfigRef,
cellDataRef,
containerRef,
flatListRef,
isTouchActiveRef,
keyToIndexRef,
panGestureHandlerRef,
propsRef,
scrollOffsetRef,
}),
[],
);
return refs;
}

View File

@ -0,0 +1,183 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { useRef } from 'react';
import {
abs,
add,
and,
block,
call,
cond,
eq,
greaterOrEq,
lessOrEq,
max,
not,
onChange,
or,
set,
sub,
useCode,
useValue,
} from 'react-native-reanimated';
import { FlatList, State as GestureState } from 'react-native-gesture-handler';
import { DEFAULT_PROPS, SCROLL_POSITION_TOLERANCE } from '../constants';
import { useNode } from '../hooks/useNode';
import { useProps } from '../context/propsContext';
import { useAnimatedValues } from '../context/animatedValueContext';
import { useRefs } from '../context/refContext';
export function useAutoScroll<T>() {
const { flatListRef } = useRefs<T>();
const { autoscrollThreshold = DEFAULT_PROPS.autoscrollThreshold, autoscrollSpeed = DEFAULT_PROPS.autoscrollSpeed } = useProps();
const { scrollOffset, scrollViewSize, containerSize, hoverAnim, isDraggingCell, activeCellSize, panGestureState } = useAnimatedValues();
const isScrolledUp = useNode(lessOrEq(sub(scrollOffset, SCROLL_POSITION_TOLERANCE), 0));
const isScrolledDown = useNode(greaterOrEq(add(scrollOffset, containerSize, SCROLL_POSITION_TOLERANCE), scrollViewSize));
const distToTopEdge = useNode(max(0, hoverAnim));
const distToBottomEdge = useNode(max(0, sub(containerSize, add(hoverAnim, activeCellSize))));
const isAtTopEdge = useNode(lessOrEq(distToTopEdge, autoscrollThreshold));
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const isAtBottomEdge = useNode(lessOrEq(distToBottomEdge, autoscrollThreshold!));
const isAtEdge = useNode(or(isAtBottomEdge, isAtTopEdge));
const autoscrollParams = [distToTopEdge, distToBottomEdge, scrollOffset, isScrolledUp, isScrolledDown];
const targetScrollOffset = useValue<number>(0);
const resolveAutoscroll = useRef<(params: readonly number[]) => void>();
const isAutoScrollInProgressNative = useValue<number>(0);
const isAutoScrollInProgress = useRef({
js: false,
native: isAutoScrollInProgressNative,
});
const isDraggingCellJS = useRef(false);
useCode(
() =>
block([
onChange(
isDraggingCell,
call([isDraggingCell], ([v]) => {
isDraggingCellJS.current = !!v;
}),
),
]),
[],
);
// Ensure that only 1 call to autoscroll is active at a time
const autoscrollLooping = useRef(false);
const onAutoscrollComplete = (params: readonly number[]) => {
isAutoScrollInProgress.current.js = false;
resolveAutoscroll.current?.(params);
};
const scrollToAsync = (offset: number): Promise<readonly number[]> =>
new Promise(resolve => {
resolveAutoscroll.current = resolve;
targetScrollOffset.setValue(offset);
isAutoScrollInProgress.current.native.setValue(1);
isAutoScrollInProgress.current.js = true;
function getFlatListNode(): FlatList<T> | null {
if (!flatListRef || !('current' in flatListRef) || !flatListRef.current) return null;
if ('scrollToOffset' in flatListRef.current) return flatListRef.current as FlatList<T>;
if ('getNode' in flatListRef.current) {
// @ts-ignore backwards compat
return flatListRef.current.getNode();
}
return null;
}
const flatListNode = getFlatListNode();
flatListNode?.scrollToOffset?.({ offset });
});
const getScrollTargetOffset = (
distFromTop: number,
distFromBottom: number,
scrollOffset: number,
isScrolledUp: boolean,
isScrolledDown: boolean,
) => {
if (isAutoScrollInProgress.current.js) return -1;
const scrollUp = distFromTop < autoscrollThreshold!;
const scrollDown = distFromBottom < autoscrollThreshold!;
if (!(scrollUp || scrollDown) || (scrollUp && isScrolledUp) || (scrollDown && isScrolledDown)) return -1;
const distFromEdge = scrollUp ? distFromTop : distFromBottom;
const speedPct = 1 - distFromEdge / autoscrollThreshold!;
const offset = speedPct * autoscrollSpeed;
const targetOffset = scrollUp ? Math.max(0, scrollOffset - offset) : scrollOffset + offset;
return targetOffset;
};
const autoscroll = async (params: readonly number[]) => {
if (autoscrollLooping.current) {
return;
}
autoscrollLooping.current = true;
try {
let shouldScroll = true;
let curParams = params;
while (shouldScroll) {
const [distFromTop, distFromBottom, scrollOffset, isScrolledUp, isScrolledDown] = curParams;
const targetOffset = getScrollTargetOffset(distFromTop, distFromBottom, scrollOffset, !!isScrolledUp, !!isScrolledDown);
const scrollingUpAtTop = !!(isScrolledUp && targetOffset <= scrollOffset);
const scrollingDownAtBottom = !!(isScrolledDown && targetOffset >= scrollOffset);
shouldScroll = targetOffset >= 0 && isDraggingCellJS.current && !scrollingUpAtTop && !scrollingDownAtBottom;
if (shouldScroll) {
try {
curParams = await scrollToAsync(targetOffset);
} catch (err) {}
}
}
} finally {
autoscrollLooping.current = false;
}
};
const checkAutoscroll = useNode(
cond(
and(
isAtEdge,
not(and(isAtTopEdge, isScrolledUp)),
not(and(isAtBottomEdge, isScrolledDown)),
eq(panGestureState, GestureState.ACTIVE),
not(isAutoScrollInProgress.current.native),
),
call(autoscrollParams, autoscroll),
),
);
useCode(() => checkAutoscroll, []);
const onScrollNode = useNode(
cond(
and(
isAutoScrollInProgress.current.native,
or(
// We've scrolled to where we want to be
lessOrEq(abs(sub(targetScrollOffset, scrollOffset)), SCROLL_POSITION_TOLERANCE),
// We're at the start, but still want to scroll farther up
and(isScrolledUp, lessOrEq(targetScrollOffset, scrollOffset)),
// We're at the end, but still want to scroll further down
and(isScrolledDown, greaterOrEq(targetScrollOffset, scrollOffset)),
),
),
[
// Finish scrolling
set(isAutoScrollInProgress.current.native, 0),
call(autoscrollParams, onAutoscrollComplete),
],
),
);
return onScrollNode;
}

View File

@ -0,0 +1,84 @@
import Animated, { add, block, call, clockRunning, cond, eq, onChange, stopClock, useCode, useValue } from 'react-native-reanimated';
import { useAnimatedValues } from '../context/animatedValueContext';
import { useRefs } from '../context/refContext';
import { setupCell, springFill } from '../procs';
import { useSpring } from './useSpring';
import { useNode } from '../hooks/useNode';
import { useDraggableFlatListContext } from '../context/draggableFlatListContext';
type Params = {
cellIndex: Animated.Value<number>;
cellSize: Animated.Value<number>;
cellOffset: Animated.Value<number>;
};
export function useCellTranslate({ cellIndex, cellSize, cellOffset }: Params) {
const {
activeIndexAnim,
activeCellSize,
hoverAnim,
scrollOffset,
spacerIndexAnim,
placeholderOffset,
isDraggingCell,
resetTouchedCell,
disabled,
} = useAnimatedValues();
const { animationConfigRef } = useRefs();
const { onDragEnd } = useDraggableFlatListContext();
const cellSpring = useSpring({ config: animationConfigRef.current });
const { clock, state, config } = cellSpring;
const isAfterActive = useValue(0);
const isClockRunning = useNode(clockRunning(clock));
const runSpring = useNode(springFill(clock, state, config));
// Even though this is the same value as hoverOffset passed via context
// the android context value lags behind the actual value on autoscroll
const cellHoverOffset = useNode(add(hoverAnim, scrollOffset));
const onFinished = useNode(
cond(isClockRunning, [
stopClock(clock),
cond(eq(cellIndex, activeIndexAnim), [resetTouchedCell, call([activeIndexAnim, spacerIndexAnim], onDragEnd)]),
]),
);
const prevTrans = useValue<number>(0);
const prevSpacerIndex = useValue<number>(-1);
const prevIsDraggingCell = useValue<number>(0);
const cellTranslate = useNode(
setupCell(
cellIndex,
cellSize,
cellOffset,
isAfterActive,
prevTrans,
prevSpacerIndex,
activeIndexAnim,
activeCellSize,
cellHoverOffset,
spacerIndexAnim,
// @ts-ignore Ignore
config.toValue,
state.position,
state.time,
state.finished,
runSpring,
onFinished,
isDraggingCell,
placeholderOffset,
prevIsDraggingCell,
clock,
disabled,
),
);
// This is a workaround required to continually evaluate values
useCode(() => block([onChange(cellTranslate, []), onChange(prevTrans, []), onChange(cellSize, []), onChange(cellOffset, [])]), []);
return state.position;
}

View File

@ -0,0 +1,10 @@
import { useRef } from 'react';
import Animated from 'react-native-reanimated';
export function useNode<T>(node: Animated.Node<T>) {
const ref = useRef<Animated.Node<T> | null>(null);
if (ref.current === null) {
ref.current = node;
}
return ref.current;
}

View File

@ -0,0 +1,38 @@
// @ts-ignore: Ignore
import Animated, { block, clockRunning, cond, onChange, set, startClock, stopClock, useCode } from 'react-native-reanimated';
import { useAnimatedValues } from '../context/animatedValueContext';
import { useIsActive } from '../context/cellContext';
import { springFill } from '../procs';
import { useSpring } from './useSpring';
type Params = {
animationConfig: Partial<Animated.SpringConfig>;
};
export function useOnCellActiveAnimation({ animationConfig }: Params = { animationConfig: {} }) {
const { clock, state, config } = useSpring({ config: animationConfig });
const { isDraggingCell } = useAnimatedValues();
const isActive = useIsActive();
useCode(
() =>
block([
onChange(isDraggingCell, [
// @ts-ignore Ignore
set(config.toValue, cond(isDraggingCell, 1, 0)),
startClock(clock),
]),
cond(clockRunning(clock), [
springFill(clock, state, config),
cond(state.finished, [stopClock(clock), set(state.finished, 0), set(state.time, 0), set(state.velocity, 0)]),
]),
]),
[],
);
return {
isActive,
onActiveAnim: state.position,
};
}

View File

@ -0,0 +1,45 @@
import { useMemo } from 'react';
import Animated, { Clock, useValue } from 'react-native-reanimated';
import { DEFAULT_ANIMATION_CONFIG } from '../constants';
type Params = {
config: Partial<Animated.SpringConfig>;
};
export function useSpring({ config: configParam }: Params = { config: DEFAULT_ANIMATION_CONFIG }) {
const toValue = useValue<number>(0);
const clock = useMemo(() => new Clock(), []);
const finished = useValue<number>(0);
const velocity = useValue<number>(0);
const position = useValue<number>(0);
const time = useValue<number>(0);
const state = useMemo(
() => ({
finished,
velocity,
position,
time,
}),
[finished, velocity, position, time],
);
const config = useMemo(
() => ({
...DEFAULT_ANIMATION_CONFIG,
...configParam,
toValue,
}),
[configParam, toValue],
) as Animated.SpringConfig;
return useMemo(
() => ({
clock,
state,
config,
}),
[clock, state, config],
);
}

View File

@ -0,0 +1,4 @@
import DraggableFlatList from './components/DraggableFlatList';
export * from './components/CellDecorators';
export * from './types';
export default DraggableFlatList;

View File

@ -0,0 +1,222 @@
import Animated, { clockRunning, not, startClock, stopClock } from 'react-native-reanimated';
import { isWeb } from './constants';
const { set, cond, add, sub, block, eq, neq, and, divide, greaterThan, greaterOrEq, Value, spring, lessThan, lessOrEq, multiply } =
Animated;
if (!Animated.proc) {
throw new Error('Incompatible Reanimated version (proc not found)');
}
// clock procs don't seem to work in web, not sure if there's a perf benefit to web procs anyway?
const proc = isWeb ? <T>(cb: T) => cb : Animated.proc;
export const getIsAfterActive = proc((currentIndex: Animated.Node<number>, activeIndex: Animated.Node<number>) =>
greaterThan(currentIndex, activeIndex),
);
export const hardReset = proc(
(position: Animated.Value<number>, finished: Animated.Value<number>, time: Animated.Value<number>, toValue: Animated.Value<number>) =>
block([set(position, 0), set(finished, 0), set(time, 0), set(toValue, 0)]),
);
/**
* The in react-native-reanimated.d.ts definition of `proc` only has generics
* for up to 10 arguments. We cast it to accept any params to avoid errors when
* type-checking.
*/
type RetypedProc = (cb: (...params: any) => Animated.Node<number>) => typeof cb;
export const setupCell = proc(
(
currentIndex: Animated.Value<number>,
size: Animated.Node<number>,
offset: Animated.Node<number>,
isAfterActive: Animated.Value<number>,
prevToValue: Animated.Value<number>,
prevSpacerIndex: Animated.Value<number>,
activeIndex: Animated.Node<number>,
activeCellSize: Animated.Node<number>,
hoverOffset: Animated.Node<number>,
spacerIndex: Animated.Value<number>,
toValue: Animated.Value<number>,
position: Animated.Value<number>,
time: Animated.Value<number>,
finished: Animated.Value<number>,
runSpring: Animated.Node<number>,
onFinished: Animated.Node<number>,
isDraggingCell: Animated.Node<number>,
placeholderOffset: Animated.Value<number>,
prevIsDraggingCell: Animated.Value<number>,
clock: Animated.Clock,
disabled: Animated.Node<number>,
) =>
block([
cond(
greaterThan(activeIndex, -1),
[
// Only update spacer if touch is not disabled.
// Fixes android bugs where state would update with invalid touch values on touch end.
cond(not(disabled), [
// Determine whether this cell is after the active cell in the list
set(isAfterActive, getIsAfterActive(currentIndex, activeIndex)),
// Determining spacer index is hard to visualize, see diagram: https://i.imgur.com/jRPf5t3.jpg
cond(
isAfterActive,
[
cond(
and(
greaterOrEq(add(hoverOffset, activeCellSize), offset),
lessThan(add(hoverOffset, activeCellSize), add(offset, divide(size, 2))),
),
set(spacerIndex, sub(currentIndex, 1)),
),
cond(
and(
greaterOrEq(add(hoverOffset, activeCellSize), add(offset, divide(size, 2))),
lessThan(add(hoverOffset, activeCellSize), add(offset, size)),
),
set(spacerIndex, currentIndex),
),
],
cond(lessThan(currentIndex, activeIndex), [
cond(
and(lessThan(hoverOffset, add(offset, size)), greaterOrEq(hoverOffset, add(offset, divide(size, 2)))),
set(spacerIndex, add(currentIndex, 1)),
),
cond(
and(greaterOrEq(hoverOffset, offset), lessThan(hoverOffset, add(offset, divide(size, 2)))),
set(spacerIndex, currentIndex),
),
]),
),
// Set placeholder offset
cond(eq(spacerIndex, currentIndex), [
set(placeholderOffset, cond(isAfterActive, add(sub(offset, activeCellSize), size), offset)),
]),
]),
cond(
eq(currentIndex, activeIndex),
[
// If this cell is the active cell
cond(
isDraggingCell,
[
// Set its position to the drag position
set(position, sub(hoverOffset, offset)),
],
[
// Active item, not pressed in
// Set value hovering element will snap to once released
cond(prevIsDraggingCell, [
set(toValue, sub(placeholderOffset, offset)),
// The clock starts automatically when toValue changes, however, we need to handle the
// case where the item should snap back to its original location and toValue doesn't change
cond(eq(prevToValue, toValue), [
cond(clockRunning(clock), stopClock(clock)),
set(time, 0),
set(finished, 0),
startClock(clock),
]),
]),
],
),
],
[
// Not the active item
// Translate cell down if it is before active index and active cell has passed it.
// Translate cell up if it is after the active index and active cell has passed it.
set(
toValue,
cond(
cond(isAfterActive, lessOrEq(currentIndex, spacerIndex), greaterOrEq(currentIndex, spacerIndex)),
cond(isAfterActive, multiply(activeCellSize, -1), activeCellSize),
0,
),
),
],
),
// If this cell should animate somewhere new, reset its state and start its clock
cond(neq(toValue, prevToValue), [cond(clockRunning(clock), stopClock(clock)), set(time, 0), set(finished, 0), startClock(clock)]),
cond(neq(prevSpacerIndex, spacerIndex), [
cond(eq(spacerIndex, -1), [
// Hard reset to prevent stale state bugs
cond(clockRunning(clock), stopClock(clock)),
hardReset(position, finished, time, toValue),
]),
]),
cond(finished, [onFinished, set(time, 0), set(finished, 0)]),
set(prevSpacerIndex, spacerIndex),
set(prevToValue, toValue),
set(prevIsDraggingCell, isDraggingCell),
cond(clockRunning(clock), runSpring),
],
[
// // Reset the spacer index when drag ends
cond(neq(spacerIndex, -1), set(spacerIndex, -1)),
cond(neq(position, 0), set(position, 0)),
],
),
position,
]),
);
const betterSpring = (proc as RetypedProc)(
(
finished: Animated.Value<number>,
velocity: Animated.Value<number>,
position: Animated.Value<number>,
time: Animated.Value<number>,
prevPosition: Animated.Value<number>,
toValue: Animated.Value<number>,
damping: Animated.Value<number>,
mass: Animated.Value<number>,
stiffness: Animated.Value<number>,
overshootClamping: Animated.SpringConfig['overshootClamping'],
restSpeedThreshold: Animated.Value<number>,
restDisplacementThreshold: Animated.Value<number>,
clock: Animated.Clock,
) =>
spring(
clock,
{
finished,
velocity,
position,
time,
// @ts-ignore -- https://github.com/software-mansion/react-native-reanimated/blob/master/src/animations/spring.js#L177
prevPosition,
},
{
toValue,
damping,
mass,
stiffness,
overshootClamping,
restDisplacementThreshold,
restSpeedThreshold,
},
),
);
export function springFill(clock: Animated.Clock, state: Animated.SpringState, config: Animated.SpringConfig) {
return betterSpring(
state.finished,
state.velocity,
state.position,
state.time,
new Value(0),
config.toValue,
config.damping,
config.mass,
config.stiffness,
config.overshootClamping,
config.restSpeedThreshold,
config.restDisplacementThreshold,
clock,
);
}

View File

@ -0,0 +1,64 @@
import React from 'react';
import { FlatListProps, StyleProp, ViewStyle } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated';
import { DEFAULT_PROPS } from './constants';
export type DragEndParams<T> = {
data: T[];
from: number;
to: number;
};
type Modify<T, R> = Omit<T, keyof R> & R;
type DefaultProps = Readonly<typeof DEFAULT_PROPS>;
export type DraggableFlatListProps<T> = Modify<
FlatListProps<T>,
{
data: T[];
activationDistance?: number;
animationConfig?: Partial<Animated.SpringConfig>;
autoscrollSpeed?: number;
autoscrollThreshold?: number;
containerStyle?: StyleProp<ViewStyle>;
debug?: boolean;
dragItemOverflow?: boolean;
keyExtractor: (item: T, index: number) => string;
onDragBegin?: (index: number) => void;
onDragEnd?: (params: DragEndParams<T>) => void;
onPlaceholderIndexChange?: (placeholderIndex: number) => void;
onRelease?: (index: number) => void;
onScrollOffsetChange?: (scrollOffset: number) => void;
renderItem: RenderItem<T>;
renderPlaceholder?: RenderPlaceholder<T>;
simultaneousHandlers?: React.Ref<any> | React.Ref<any>[];
} & Partial<DefaultProps>
>;
export type RenderPlaceholder<T> = (params: { item: T; index: number }) => JSX.Element;
export type RenderItemParams<T> = {
item: T;
index?: number; // This is technically a "last known index" since cells don't necessarily rerender when their index changes
drag: () => void;
isActive: boolean;
};
export type RenderItem<T> = (params: RenderItemParams<T>) => React.ReactNode;
export type AnimatedFlatListType = <T>(
props: Animated.AnimateProps<
FlatListProps<T> & {
ref: React.Ref<FlatList<T>>;
simultaneousHandlers?: React.Ref<any> | React.Ref<any>[];
}
>,
) => React.ReactElement;
export type CellData = {
measurements: {
size: number;
offset: number;
};
};

View File

@ -0,0 +1,5 @@
import React from 'react';
// Fixes bug with useMemo + generic types:
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/37087#issuecomment-542793243
export const typedMemo: <T>(c: T) => T = React.memo;

View File

@ -1372,7 +1372,7 @@
CODE_SIGN_ENTITLEMENTS = BlueWallet/BlueWallet.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = A7W54YZ4WU;
ENABLE_BITCODE = NO;
@ -1393,7 +1393,7 @@
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -1421,7 +1421,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEVELOPMENT_TEAM = A7W54YZ4WU;
ENABLE_BITCODE = NO;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
@ -1436,7 +1436,7 @@
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -1466,7 +1466,7 @@
CODE_SIGN_ENTITLEMENTS = "TodayExtension/BlueWallet - Bitcoin Price.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1477,7 +1477,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
@ -1505,7 +1505,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1516,7 +1516,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
PRODUCT_NAME = "BlueWallet - Bitcoin Price";
@ -1542,13 +1542,13 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Stickers/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.Stickers;
@ -1574,13 +1574,13 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Stickers/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.Stickers;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1607,7 +1607,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1618,7 +1618,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
@ -1652,7 +1652,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1663,7 +1663,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1709,7 +1709,7 @@
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@ -1766,7 +1766,7 @@
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@ -1798,7 +1798,7 @@
CODE_SIGN_ENTITLEMENTS = "BlueWalletWatch Extension/BlueWalletWatch Extension.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1808,7 +1808,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
@ -1838,7 +1838,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1848,7 +1848,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
PRODUCT_NAME = "${TARGET_NAME}";
@ -1877,13 +1877,13 @@
CODE_SIGN_ENTITLEMENTS = BlueWalletWatch/BlueWalletWatch.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
IBSC_MODULE = BlueWalletWatch_Extension;
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
@ -1915,13 +1915,13 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 700;
CURRENT_PROJECT_VERSION = 702;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
IBSC_MODULE = BlueWalletWatch_Extension;
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
MARKETING_VERSION = 6.2.17;
MARKETING_VERSION = 6.2.19;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -116,7 +116,6 @@
<string>bluewallet</string>
<string>lapp</string>
<string>blue</string>
<string>aopp</string>
</array>
</dict>
</array>

View File

@ -22,6 +22,10 @@ RCT_EXPORT_MODULE();
return sharedInstance;
}
- (void)removeListeners:(double)count {
}
- (instancetype)init {
sharedInstance = [super init];
return sharedInstance;

View File

@ -16,9 +16,10 @@ target 'BlueWallet' do
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
use_flipper!()
use_flipper!({ "Flipper-DoubleConversion" => "1.1.7" })
post_install do |installer|
react_native_post_install(installer)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
pod 'Bugsnag'
plugin 'cocoapods-bugsnag'
installer.pods_project.targets.each do |target|

View File

@ -1,270 +1,290 @@
PODS:
- boost-for-react-native (1.63.0)
- BugsnagReactNative (7.14.2):
- boost (1.76.0)
- BugsnagReactNative (7.16.1):
- React-Core
- BVLinearGradient (2.5.6):
- React
- CocoaAsyncSocket (7.6.5)
- DoubleConversion (1.1.6)
- FBLazyVector (0.64.2)
- FBReactNativeSpec (0.64.2):
- RCT-Folly (= 2020.01.13.00)
- RCTRequired (= 0.64.2)
- RCTTypeSafety (= 0.64.2)
- React-Core (= 0.64.2)
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- Flipper (0.75.1):
- Flipper-Folly (~> 2.5)
- Flipper-RSocket (~> 1.3)
- FBLazyVector (0.67.2)
- FBReactNativeSpec (0.67.2):
- RCT-Folly (= 2021.06.28.00-v2)
- RCTRequired (= 0.67.2)
- RCTTypeSafety (= 0.67.2)
- React-Core (= 0.67.2)
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- Flipper (0.99.0):
- Flipper-Folly (~> 2.6)
- Flipper-RSocket (~> 1.4)
- Flipper-Boost-iOSX (1.76.0.1.11)
- Flipper-DoubleConversion (1.1.7)
- Flipper-Folly (2.5.3):
- boost-for-react-native
- Flipper-Fmt (7.1.7)
- Flipper-Folly (2.6.7):
- Flipper-Boost-iOSX
- Flipper-DoubleConversion
- Flipper-Fmt (= 7.1.7)
- Flipper-Glog
- libevent (~> 2.1.12)
- OpenSSL-Universal (= 1.1.180)
- Flipper-Glog (0.3.6)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.3.1):
- Flipper-Folly (~> 2.5)
- FlipperKit (0.75.1):
- FlipperKit/Core (= 0.75.1)
- FlipperKit/Core (0.75.1):
- Flipper (~> 0.75.1)
- Flipper-RSocket (1.4.3):
- Flipper-Folly (~> 2.6)
- FlipperKit (0.99.0):
- FlipperKit/Core (= 0.99.0)
- FlipperKit/Core (0.99.0):
- Flipper (~> 0.99.0)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- FlipperKit/CppBridge (0.75.1):
- Flipper (~> 0.75.1)
- FlipperKit/FBCxxFollyDynamicConvert (0.75.1):
- Flipper-Folly (~> 2.5)
- FlipperKit/FBDefines (0.75.1)
- FlipperKit/FKPortForwarding (0.75.1):
- FlipperKit/CppBridge (0.99.0):
- Flipper (~> 0.99.0)
- FlipperKit/FBCxxFollyDynamicConvert (0.99.0):
- Flipper-Folly (~> 2.6)
- FlipperKit/FBDefines (0.99.0)
- FlipperKit/FKPortForwarding (0.99.0):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.75.1)
- FlipperKit/FlipperKitLayoutPlugin (0.75.1):
- FlipperKit/FlipperKitHighlightOverlay (0.99.0)
- FlipperKit/FlipperKitLayoutHelpers (0.99.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- FlipperKit/FlipperKitLayoutIOSDescriptors (0.99.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutHelpers
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.75.1)
- FlipperKit/FlipperKitNetworkPlugin (0.75.1):
- FlipperKit/FlipperKitLayoutPlugin (0.99.0):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.75.1):
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutHelpers
- FlipperKit/FlipperKitLayoutIOSDescriptors
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.99.0)
- FlipperKit/FlipperKitNetworkPlugin (0.99.0):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.75.1):
- FlipperKit/FlipperKitReactPlugin (0.99.0):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.75.1):
- FlipperKit/FlipperKitUserDefaultsPlugin (0.99.0):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.99.0):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- fmt (6.2.1)
- GCDWebServer (3.5.4):
- GCDWebServer/Core (= 3.5.4)
- GCDWebServer/Core (3.5.4)
- glog (0.3.5)
- libevent (2.1.12)
- lottie-ios (3.1.9)
- lottie-react-native (4.0.2):
- lottie-ios (~> 3.1.8)
- lottie-ios (3.2.3)
- lottie-react-native (5.0.1):
- lottie-ios (~> 3.2.3)
- React-Core
- OpenSSL-Universal (1.1.180)
- PasscodeAuth (1.0.0):
- React
- RCT-Folly (2020.01.13.00):
- boost-for-react-native
- RCT-Folly (2021.06.28.00-v2):
- boost
- DoubleConversion
- fmt (~> 6.2.1)
- glog
- RCT-Folly/Default (= 2021.06.28.00-v2)
- RCT-Folly/Default (2021.06.28.00-v2):
- boost
- DoubleConversion
- fmt (~> 6.2.1)
- glog
- RCTRequired (0.67.2)
- RCTTypeSafety (0.67.2):
- FBLazyVector (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- RCTRequired (= 0.67.2)
- React-Core (= 0.67.2)
- React (0.67.2):
- React-Core (= 0.67.2)
- React-Core/DevSupport (= 0.67.2)
- React-Core/RCTWebSocket (= 0.67.2)
- React-RCTActionSheet (= 0.67.2)
- React-RCTAnimation (= 0.67.2)
- React-RCTBlob (= 0.67.2)
- React-RCTImage (= 0.67.2)
- React-RCTLinking (= 0.67.2)
- React-RCTNetwork (= 0.67.2)
- React-RCTSettings (= 0.67.2)
- React-RCTText (= 0.67.2)
- React-RCTVibration (= 0.67.2)
- React-callinvoker (0.67.2)
- React-Core (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default (= 0.67.2)
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/CoreModulesHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/Default (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/DevSupport (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default (= 0.67.2)
- React-Core/RCTWebSocket (= 0.67.2)
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-jsinspector (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTActionSheetHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTAnimationHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTBlobHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTImageHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTLinkingHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTNetworkHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTSettingsHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTTextHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTVibrationHeaders (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-Core/RCTWebSocket (0.67.2):
- glog
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/Default (= 0.67.2)
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsiexecutor (= 0.67.2)
- React-perflogger (= 0.67.2)
- Yoga
- React-CoreModules (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- RCTTypeSafety (= 0.67.2)
- React-Core/CoreModulesHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- React-RCTImage (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-cxxreact (0.67.2):
- boost (= 1.76.0)
- DoubleConversion
- glog
- RCT-Folly/Default (= 2020.01.13.00)
- RCT-Folly/Default (2020.01.13.00):
- boost-for-react-native
- RCT-Folly (= 2021.06.28.00-v2)
- React-callinvoker (= 0.67.2)
- React-jsi (= 0.67.2)
- React-jsinspector (= 0.67.2)
- React-logger (= 0.67.2)
- React-perflogger (= 0.67.2)
- React-runtimeexecutor (= 0.67.2)
- React-jsi (0.67.2):
- boost (= 1.76.0)
- DoubleConversion
- glog
- RCTRequired (0.64.2)
- RCTTypeSafety (0.64.2):
- FBLazyVector (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- RCTRequired (= 0.64.2)
- React-Core (= 0.64.2)
- React (0.64.2):
- React-Core (= 0.64.2)
- React-Core/DevSupport (= 0.64.2)
- React-Core/RCTWebSocket (= 0.64.2)
- React-RCTActionSheet (= 0.64.2)
- React-RCTAnimation (= 0.64.2)
- React-RCTBlob (= 0.64.2)
- React-RCTImage (= 0.64.2)
- React-RCTLinking (= 0.64.2)
- React-RCTNetwork (= 0.64.2)
- React-RCTSettings (= 0.64.2)
- React-RCTText (= 0.64.2)
- React-RCTVibration (= 0.64.2)
- React-callinvoker (0.64.2)
- React-Core (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default (= 0.64.2)
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/CoreModulesHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/Default (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/DevSupport (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default (= 0.64.2)
- React-Core/RCTWebSocket (= 0.64.2)
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-jsinspector (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTActionSheetHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTAnimationHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTBlobHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTImageHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTLinkingHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTNetworkHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTSettingsHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTTextHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTVibrationHeaders (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-Core/RCTWebSocket (0.64.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-Core/Default (= 0.64.2)
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsiexecutor (= 0.64.2)
- React-perflogger (= 0.64.2)
- Yoga
- React-CoreModules (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.2)
- React-Core/CoreModulesHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- React-RCTImage (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-cxxreact (0.64.2):
- boost-for-react-native (= 1.63.0)
- RCT-Folly (= 2021.06.28.00-v2)
- React-jsi/Default (= 0.67.2)
- React-jsi/Default (0.67.2):
- boost (= 1.76.0)
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-callinvoker (= 0.64.2)
- React-jsi (= 0.64.2)
- React-jsinspector (= 0.64.2)
- React-perflogger (= 0.64.2)
- React-runtimeexecutor (= 0.64.2)
- React-jsi (0.64.2):
- boost-for-react-native (= 1.63.0)
- RCT-Folly (= 2021.06.28.00-v2)
- React-jsiexecutor (0.67.2):
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-jsi/Default (= 0.64.2)
- React-jsi/Default (0.64.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- RCT-Folly (= 2021.06.28.00-v2)
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-perflogger (= 0.67.2)
- React-jsinspector (0.67.2)
- React-logger (0.67.2):
- glog
- RCT-Folly (= 2020.01.13.00)
- React-jsiexecutor (0.64.2):
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-perflogger (= 0.64.2)
- React-jsinspector (0.64.2)
- react-native-blue-crypto (1.0.0):
- React
- react-native-camera (4.2.1):
@ -281,7 +301,7 @@ PODS:
- React
- react-native-idle-timer (2.1.6):
- React-Core
- react-native-image-picker (4.7.0):
- react-native-image-picker (4.7.3):
- React-Core
- react-native-ios-context-menu (1.3.0):
- React-Core
@ -292,84 +312,85 @@ PODS:
- react-native-tcp-socket (5.5.0):
- CocoaAsyncSocket
- React-Core
- react-native-tor (0.1.7):
- react-native-tor (0.1.8):
- React
- react-native-webview (11.16.0):
- react-native-webview (11.17.2):
- React-Core
- react-native-widget-center (0.0.7):
- React
- React-perflogger (0.64.2)
- React-RCTActionSheet (0.64.2):
- React-Core/RCTActionSheetHeaders (= 0.64.2)
- React-RCTAnimation (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.2)
- React-Core/RCTAnimationHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-RCTBlob (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.64.2)
- React-Core/RCTWebSocket (= 0.64.2)
- React-jsi (= 0.64.2)
- React-RCTNetwork (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-RCTImage (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.2)
- React-Core/RCTImageHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- React-RCTNetwork (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-RCTLinking (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- React-Core/RCTLinkingHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-RCTNetwork (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.2)
- React-Core/RCTNetworkHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-RCTSettings (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.64.2)
- React-Core/RCTSettingsHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-RCTText (0.64.2):
- React-Core/RCTTextHeaders (= 0.64.2)
- React-RCTVibration (0.64.2):
- FBReactNativeSpec (= 0.64.2)
- RCT-Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.64.2)
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (= 0.64.2)
- React-runtimeexecutor (0.64.2):
- React-jsi (= 0.64.2)
- ReactCommon/turbomodule/core (0.64.2):
- React-perflogger (0.67.2)
- React-RCTActionSheet (0.67.2):
- React-Core/RCTActionSheetHeaders (= 0.67.2)
- React-RCTAnimation (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- RCTTypeSafety (= 0.67.2)
- React-Core/RCTAnimationHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-RCTBlob (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/RCTBlobHeaders (= 0.67.2)
- React-Core/RCTWebSocket (= 0.67.2)
- React-jsi (= 0.67.2)
- React-RCTNetwork (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-RCTImage (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- RCTTypeSafety (= 0.67.2)
- React-Core/RCTImageHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- React-RCTNetwork (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-RCTLinking (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- React-Core/RCTLinkingHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-RCTNetwork (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- RCTTypeSafety (= 0.67.2)
- React-Core/RCTNetworkHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-RCTSettings (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- RCTTypeSafety (= 0.67.2)
- React-Core/RCTSettingsHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-RCTText (0.67.2):
- React-Core/RCTTextHeaders (= 0.67.2)
- React-RCTVibration (0.67.2):
- FBReactNativeSpec (= 0.67.2)
- RCT-Folly (= 2021.06.28.00-v2)
- React-Core/RCTVibrationHeaders (= 0.67.2)
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (= 0.67.2)
- React-runtimeexecutor (0.67.2):
- React-jsi (= 0.67.2)
- ReactCommon/turbomodule/core (0.67.2):
- DoubleConversion
- glog
- RCT-Folly (= 2020.01.13.00)
- React-callinvoker (= 0.64.2)
- React-Core (= 0.64.2)
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-perflogger (= 0.64.2)
- RealmJS (10.11.0):
- RCT-Folly (= 2021.06.28.00-v2)
- React-callinvoker (= 0.67.2)
- React-Core (= 0.67.2)
- React-cxxreact (= 0.67.2)
- React-jsi (= 0.67.2)
- React-logger (= 0.67.2)
- React-perflogger (= 0.67.2)
- RealmJS (10.12.0):
- GCDWebServer
- React
- RemobileReactNativeQrcodeLocalImage (1.0.4):
- React
- rn-ldk (0.6.4):
- React-Core
- RNCAsyncStorage (1.15.15):
- RNCAsyncStorage (1.16.1):
- React-Core
- RNCClipboard (1.9.0):
- React-Core
@ -377,17 +398,17 @@ PODS:
- React-Core
- RNDefaultPreference (1.4.3):
- React
- RNDeviceInfo (8.4.8):
- RNDeviceInfo (8.4.9):
- React-Core
- RNFS (2.18.0):
- React
- RNGestureHandler (1.10.3):
- RNGestureHandler (2.2.0):
- React-Core
- RNHandoff (0.0.3):
- React
- RNKeychain (8.0.0):
- React-Core
- RNLocalize (2.1.7):
- RNLocalize (2.1.9):
- React-Core
- RNPrivacySnapshot (1.0.0):
- React
@ -426,12 +447,12 @@ PODS:
- React-RCTVibration
- ReactCommon/turbomodule/core
- Yoga
- RNScreens (3.10.1):
- RNScreens (3.11.0):
- React-Core
- React-RCTImage
- RNSecureKeyStore (1.0.0):
- React
- RNShare (7.3.2):
- RNShare (7.3.5):
- React-Core
- RNSVG (12.1.1):
- React
@ -445,34 +466,38 @@ PODS:
- Yoga (~> 1.14)
DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
- Bugsnag
- "BugsnagReactNative (from `../node_modules/@bugsnag/react-native`)"
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- Flipper (~> 0.75.1)
- Flipper (= 0.99.0)
- Flipper-Boost-iOSX (= 1.76.0.1.11)
- Flipper-DoubleConversion (= 1.1.7)
- Flipper-Folly (~> 2.5.3)
- Flipper-Fmt (= 7.1.7)
- Flipper-Folly (= 2.6.7)
- Flipper-Glog (= 0.3.6)
- Flipper-PeerTalk (~> 0.0.4)
- Flipper-RSocket (~> 1.3)
- FlipperKit (~> 0.75.1)
- FlipperKit/Core (~> 0.75.1)
- FlipperKit/CppBridge (~> 0.75.1)
- FlipperKit/FBCxxFollyDynamicConvert (~> 0.75.1)
- FlipperKit/FBDefines (~> 0.75.1)
- FlipperKit/FKPortForwarding (~> 0.75.1)
- FlipperKit/FlipperKitHighlightOverlay (~> 0.75.1)
- FlipperKit/FlipperKitLayoutPlugin (~> 0.75.1)
- FlipperKit/FlipperKitLayoutTextSearchable (~> 0.75.1)
- FlipperKit/FlipperKitNetworkPlugin (~> 0.75.1)
- FlipperKit/FlipperKitReactPlugin (~> 0.75.1)
- FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.75.1)
- FlipperKit/SKIOSNetworkPlugin (~> 0.75.1)
- Flipper-PeerTalk (= 0.0.4)
- Flipper-RSocket (= 1.4.3)
- FlipperKit (= 0.99.0)
- FlipperKit/Core (= 0.99.0)
- FlipperKit/CppBridge (= 0.99.0)
- FlipperKit/FBCxxFollyDynamicConvert (= 0.99.0)
- FlipperKit/FBDefines (= 0.99.0)
- FlipperKit/FKPortForwarding (= 0.99.0)
- FlipperKit/FlipperKitHighlightOverlay (= 0.99.0)
- FlipperKit/FlipperKitLayoutPlugin (= 0.99.0)
- FlipperKit/FlipperKitLayoutTextSearchable (= 0.99.0)
- FlipperKit/FlipperKitNetworkPlugin (= 0.99.0)
- FlipperKit/FlipperKitReactPlugin (= 0.99.0)
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.99.0)
- FlipperKit/SKIOSNetworkPlugin (= 0.99.0)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- lottie-ios (from `../node_modules/lottie-ios`)
- lottie-react-native (from `../node_modules/lottie-react-native`)
- OpenSSL-Universal (= 1.1.180)
- PasscodeAuth (from `../node_modules/react-native-passcode-auth`)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
@ -487,6 +512,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-blue-crypto (from `../node_modules/react-native-blue-crypto`)
- react-native-camera (from `../node_modules/react-native-camera`)
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
@ -541,21 +567,25 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- boost-for-react-native
- CocoaAsyncSocket
- Flipper
- Flipper-Boost-iOSX
- Flipper-DoubleConversion
- Flipper-Fmt
- Flipper-Folly
- Flipper-Glog
- Flipper-PeerTalk
- Flipper-RSocket
- FlipperKit
- fmt
- GCDWebServer
- libevent
- OpenSSL-Universal
- YogaKit
EXTERNAL SOURCES:
boost:
:podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
BugsnagReactNative:
:path: "../node_modules/@bugsnag/react-native"
BVLinearGradient:
@ -596,6 +626,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-blue-crypto:
:path: "../node_modules/react-native-blue-crypto"
react-native-camera:
@ -706,91 +738,95 @@ CHECKOUT OPTIONS:
:git: https://github.com/swiftsocket/SwiftSocket.git
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BugsnagReactNative: 74c4786cdf6eca1e9c41509f60f6600761189e11
boost: a7c83b31436843459a1961bfd74b96033dc77234
BugsnagReactNative: bd1c905fb868fae8448a913b87356dbf2b02dc80
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
FBReactNativeSpec: d1904f6d1468c2411b99af1a8b3db52f828475b7
Flipper: d3da1aa199aad94455ae725e9f3aa43f3ec17021
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: 244195e30d63d7f564c55da4410b9a24e8fbceaa
FBReactNativeSpec: c94002c1d93da3658f4d5119c6994d19961e3d52
Flipper: 30e8eeeed6abdc98edaf32af0cda2f198be4b733
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: 755929a4f851b2fb2c347d533a23f191b008554c
Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b
Flipper-Folly: 83af37379faa69497529e414bd43fbfc7cae259a
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 127954abe8b162fcaf68d2134d34dc2bd7076154
FlipperKit: 8a20b5c5fcf9436cac58551dc049867247f64b00
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
FlipperKit: d8d346844eca5d9120c17d441a2f38596e8ed2b9
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
glog: 85ecdd10ee8d8ec362ef519a6a45ff9aa27b2e85
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
lottie-ios: 3a3758ef5a008e762faec9c9d50a39842f26d124
lottie-react-native: 4dff8fe8d10ddef9e7880e770080f4a56121397e
lottie-ios: c058aeafa76daa4cf64d773554bccc8385d0150e
lottie-react-native: a029a86e1689c86a07169c520ae770e84348cd20
OpenSSL-Universal: 1aa4f6a6ee7256b83db99ec1ccdaa80d10f9af9b
PasscodeAuth: 3e88093ff46c31a952d8b36c488240de980517be
RCT-Folly: ec7a233ccc97cc556cf7237f0db1ff65b986f27c
RCTRequired: 6d3e854f0e7260a648badd0d44fc364bc9da9728
RCTTypeSafety: c1f31d19349c6b53085766359caac425926fafaa
React: bda6b6d7ae912de97d7a61aa5c160db24aa2ad69
React-callinvoker: 9840ea7e8e88ed73d438edb725574820b29b5baa
React-Core: b5e385da7ce5f16a220fc60fd0749eae2c6120f0
React-CoreModules: 17071a4e2c5239b01585f4aa8070141168ab298f
React-cxxreact: 9be7b6340ed9f7c53e53deca7779f07cd66525ba
React-jsi: 67747b9722f6dab2ffe15b011bcf6b3f2c3f1427
React-jsiexecutor: 80c46bd381fd06e418e0d4f53672dc1d1945c4c3
React-jsinspector: cc614ec18a9ca96fd275100c16d74d62ee11f0ae
RCT-Folly: 803a9cfd78114b2ec0f140cfa6fa2a6bafb2d685
RCTRequired: cd47794163052d2b8318c891a7a14fcfaccc75ab
RCTTypeSafety: 393bb40b3e357b224cde53d3fec26813c52428b1
React: dec6476bc27155b250eeadfc11ea779265f53ebf
React-callinvoker: e5047929e80aea942e6fdd96482504ef0189ca63
React-Core: e382655566b2b9a6e3b4f641d777b7bfdbe52358
React-CoreModules: cf262e82fa101c0aee022b6f90d1a5b612038b64
React-cxxreact: 69d53de3b30c7c161ba087ca1ecdffed9ccb1039
React-jsi: ce9a2d804adf75809ce2fe2374ba3fbbf5d59b03
React-jsiexecutor: 52beb652bbc61201bd70cbe4f0b8edb607e8da4f
React-jsinspector: 595f76eba2176ebd8817a1fffd47b84fbdab9383
React-logger: 23de8ea0f44fa00ee77e96060273225607fd4d78
react-native-blue-crypto: 23f1558ad3d38d7a2edb7e2f6ed1bc520ed93e56
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
react-native-document-picker: ec07866a30707f23660c0f3ae591d669d3e89096
react-native-fingerprint-scanner: ac6656f18c8e45a7459302b84da41a44ad96dbbe
react-native-idle-timer: f7f651542b39dce9b9473e4578cb64a255075f17
react-native-image-picker: 4b090b73077c3a71b91fddc739a594feebd00184
react-native-image-picker: 4e6008ad8c2321622affa2c85432a5ebd02d480c
react-native-ios-context-menu: 1ccf4d6aa1c0e7dc596613eb9a36f8c0c23ca56f
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-safe-area-context: 584dc04881deb49474363f3be89e4ca0e854c057
react-native-tcp-socket: 199889cd48b07a0238e0feb53549607de5207116
react-native-tor: 6a64351e96ccd6a49941989703f63ec81fc1ae7c
react-native-webview: 28a8636d97ee641f2ee8f20492d7a6c269c1d703
react-native-tor: 3b14e9160b2eb7fa3f310921b2dee71a5171e5b7
react-native-webview: 380c1a03ec94b7ed764dac8db1e7c9952d08c93a
react-native-widget-center: 5e63193fce272aa3c2aa4f1a33e129b06a962f47
React-perflogger: 25373e382fed75ce768a443822f07098a15ab737
React-RCTActionSheet: af7796ba49ffe4ca92e7277a5d992d37203f7da5
React-RCTAnimation: 6a2e76ab50c6f25b428d81b76a5a45351c4d77aa
React-RCTBlob: 02a2887023e0eed99391b6445b2e23a2a6f9226d
React-RCTImage: ce5bf8e7438f2286d9b646a05d6ab11f38b0323d
React-RCTLinking: ccd20742de14e020cb5f99d5c7e0bf0383aefbd9
React-RCTNetwork: dfb9d089ab0753e5e5f55fc4b1210858f7245647
React-RCTSettings: b14aef2d83699e48b410fb7c3ba5b66cd3291ae2
React-RCTText: 41a2e952dd9adc5caf6fb68ed46b275194d5da5f
React-RCTVibration: 24600e3b1aaa77126989bc58b6747509a1ba14f3
React-runtimeexecutor: a9904c6d0218fb9f8b19d6dd88607225927668f9
ReactCommon: 149906e01aa51142707a10665185db879898e966
RealmJS: de65cc7c3ea041750d66beaa28b30585222c3d94
React-perflogger: 3c9bb7372493e49036f07a82c44c8cf65cbe88db
React-RCTActionSheet: 052606483045a408693aa7e864410b4a052f541a
React-RCTAnimation: 08d4cac13222bb1348c687a0158dfd3b577cdb63
React-RCTBlob: 928ad1df65219c3d9e2ac80983b943a75b5c3629
React-RCTImage: 524d7313b142a39ee0e20fa312b67277917fe076
React-RCTLinking: 44036ea6f13a2e46238be07a67566247fee35244
React-RCTNetwork: 9b6faacf1e0789253e319ca53b1f8d92c2ac5455
React-RCTSettings: ecd8094f831130a49581d5112a8607220e5d12a5
React-RCTText: 14ba976fb48ed283cfdb1a754a5d4276471e0152
React-RCTVibration: 99c7f67fba7a5ade46e98e870c6ff2444484f995
React-runtimeexecutor: 2450b43df7ffe8e805a0b3dcb2abd4282f1f1836
ReactCommon: d98c6c96b567f9b3a15f9fd4cc302c1eda8e3cf2
RealmJS: b6097dab8af3bcf1cd5fa0ac39a4e4c54980c719
RemobileReactNativeQrcodeLocalImage: 57aadc12896b148fb5e04bc7c6805f3565f5c3fa
rn-ldk: 94bc90bf928598dd2684a58e6949e40bb3d45c7b
RNCAsyncStorage: 0bef6a21517c0254bd6bd59a3672963abfa0d18e
RNCAsyncStorage: b49b4e38a1548d03b74b30e558a1d18465b94be7
RNCClipboard: 99fc8ad669a376b756fbc8098ae2fd05c0ed0668
RNCPushNotificationIOS: 87b8d16d3ede4532745e05b03c42cff33a36cc45
RNDefaultPreference: 2f8d6d54230edbd78708ada8d63bb275e5a8415b
RNDeviceInfo: 0400a6d0c94186d1120c3cbd97b23abc022187a9
RNDeviceInfo: 4944cf8787b9c5bffaf301fda68cc1a2ec003341
RNFS: 3ab21fa6c56d65566d1fb26c2228e2b6132e5e32
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNGestureHandler: bf572f552ea324acd5b5464b8d30755b2d8c1de6
RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa
RNKeychain: 4f63aada75ebafd26f4bc2c670199461eab85d94
RNLocalize: f567ea0e35116a641cdffe6683b0d212d568f32a
RNLocalize: 291e5e21b53cd30b5205c10ed95d31b0dc9b8d63
RNPrivacySnapshot: 71919dde3c6a29dd332115409c2aec564afee8f4
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
RNRate: 94f57c773e155ca0d0aeeba9c10a32bce9030daf
RNReactNativeHapticFeedback: b83bfb4b537bdd78eb4f6ffe63c6884f7b049ead
RNReanimated: 024eff8202342abf4b24e11575a16afc441dabfe
RNScreens: 522705f2e5c9d27efb17f24aceb2bf8335bc7b8e
RNReanimated: e28dfaa950064b674fde0a9b736e62b9dff500a7
RNScreens: fd535547baa4ef8aeaee1a8b1e3ffd17b8df44a4
RNSecureKeyStore: f1ad870e53806453039f650720d2845c678d89c8
RNShare: d76b8c9c6e6ffb38fc18f40b4338c9d867592ed3
RNShare: 730a2773b1e0007425f2f111dcf75208a919c902
RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f
RNVectorIcons: 4143ba35feebab8fdbe6bc43d1e776b393d47ac8
RNWatch: 99637948ec9b5c9ec5a41920642594ad5ba07e80
SwiftSocket: c8d482e867ae4d3eb4c769e9382e123c1f1f833b
Yoga: 575c581c63e0d35c9a83f4b46d01d63abc1100ac
Yoga: 9b6696970c3289e8dea34b3eda93f23e61fb8121
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: 39afb2c1727531c14ee301938165dcf7a6f6ca0f
PODFILE CHECKSUM: 53c058f42bf11a3d01891a40676ea8f9c6a9ecf9
COCOAPODS: 1.10.1

View File

@ -1 +1 @@
BlueWallet Cartera de Bitcoin
BlueWallet - Cartera de Bitcoin

View File

@ -1 +1 @@
BlueWallet portefeuille
BlueWallet - portefeuille Bitcoin

View File

@ -40,14 +40,14 @@ A partire da 1 Satoshi. Deciso da te, l'utente
Replace-By-Fee
(RBF) Velocizza le tue transazioni aumentando le commissioni (BIP125)
Watch-only wallets
Watch-only wallets allow you to keep an eye on your cold storage without touching the hardware.
Portafoglio watch-only
Il portafoglio watch-only ti permette di visualizzare il tuo cold wallet senza dover inserire la seed phrase o usare l'hardware wallet
Lightning Network
Wallet per Lightning Network con zero configurazioni necessarie. Per transazioni incredibilmente economiche e veloci con la miglior esperienza utente.
Acquista Bitcoin
Enter in the open financial revolution with the ability to buy Bitcoin directly in your wallet.
Partecipa alla rivoluzione finanziaria con la possibilità di comprare Bitcoin direttamente dal tuo wallet.
Local Trader
A p2p Bitcoin Trading platform, that allows you to buy and sell bitcoin directly to other users without 3rd parties.
Una piattaforma Bitcoin p2p, che ti permette di comprare e vendere bitcoin direttamente ad altri utenti senza il bisogno di 3º parti.

View File

@ -1 +1 @@
BlueWallet Bitcoin portomonnee
BlueWallet - Bitcoin portomonnee

View File

@ -120,7 +120,7 @@
"placeholder": "فاتورة",
"open_channel": "فتح قناة",
"funding_amount_placeholder": "مبلغ التمويل، على سبيل المثال 0.001",
"opening_channnel_for_from":"جاري فتح قناة للمحفظة {forWalletLabel} بتمويل من {fromWalletLabel}",
"opening_channnel_for_from":"جارِ فتح قناة للمحفظة {forWalletLabel} بتمويل من {fromWalletLabel}",
"are_you_sure_open_channel": "هل أنت متأكد أنك تريد فتح هذه القناة؟",
"are_you_sure_exit_without_new_channel": "هل أنت متأكد أنك تريد الخروج دون فتح قناة؟",
"public": "علني",
@ -525,6 +525,7 @@
"no_ln_wallet_error": "قبل دفع فاتورة برق (Lightning) ، يجب عليك أولاً إضافة محفظة برق (Lightning).",
"looks_like_bip38": "يبدوا ان هذا مفتاح خاص محمي بكلمة مرور (BIP38).",
"reorder_title": "إعادة ترتيب المحافظ",
"reorder_instructions": "اضغط باستمرار على اي محفظة لتحريكها عبر القائمة",
"please_continue_scanning": "الرجاء متابعة الفحص.",
"scan_error": "خطأ في الفحص",
"select_no_bitcoin": "لا توجد محافظ Bitcoin متاحة حاليًا.",
@ -625,6 +626,7 @@
"cc": {
"change": "تغيير",
"coins_selected": "العملات المحددة ({number})",
"selected_summ": "{value} مختاره",
"empty": "لا تحتوي هذه المحفظة على أي عملات في الوقت الحالي.",
"freeze": "تجميد",
"freezeLabel": "تجميد",
@ -651,17 +653,10 @@
"sign_placeholder_address": "العنوان",
"sign_placeholder_message": "الرسالة",
"sign_placeholder_signature": "التوقيع",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "هل تريد إرسال رسالة موقعة إلى {hostname}؟",
"addresses_title": "العنوان",
"type_change": "تغيير",
"type_receive": "استلام",
"type_used": "مستخدم",
"transactions": "الحوالات"
},
"aopp": {
"title": "اختر عنوانًا",
"send_success": "تم إرسال التوقيع بنجاح",
"send_error": "خطأ في إرسال التوقيع"
}
}

View File

@ -525,6 +525,7 @@
"no_ln_wallet_error": "Před zaplacením Lightning faktury musíte nejprve přidat Lightning peněženku.",
"looks_like_bip38": "Tohle vypadá jako soukromý klíč chráněný heslem (BIP38)",
"reorder_title": "Seřadit peěženky",
"reorder_instructions": "Klepněte a podržte peněženku a přetáhněte ji po seznamu.",
"please_continue_scanning": "Pokračujte ve skenování",
"scan_error": "Chyba skenování",
"select_no_bitcoin": "V současné době nejsou k dispozici žádné bitcoinové peněženky.",
@ -625,6 +626,7 @@
"cc": {
"change": "změnit",
"coins_selected": "Vybrané mince ({number})",
"selected_summ": "{value} vybráno",
"empty": "Tato peněženka nemá v tuto chvíli žádné mince",
"freeze": "zmrazit",
"freezeLabel": "Zmrazit",
@ -651,17 +653,10 @@
"sign_placeholder_address": "Adresa",
"sign_placeholder_message": "Zpráva",
"sign_placeholder_signature": "Podpis",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Chcete odeslat podepsanou zprávu na adresu {hostname}?",
"addresses_title": "Adresy",
"type_change": "Změnit",
"type_receive": "Příjmout",
"type_used": "Použité",
"transactions": "Transakce"
},
"aopp": {
"title": "Vybrat adresu",
"send_success": "Podpis byl úspěšně odeslán",
"send_error": "Chyba při odesílání podpisu"
}
}

View File

@ -284,8 +284,5 @@
"addresses_title": "Cyfeiriadau",
"type_change": "Newid",
"type_receive": "Derbyn"
},
"aopp": {
"title": "Dewis Cyfeiriad"
}
}

View File

@ -525,6 +525,7 @@
"no_ln_wallet_error": "Vor Bezahlung einer Lightning Rechnung zuerst ein Lightning wallet eröffnen.",
"looks_like_bip38": "Passwortgeschützter Privatschlüssel (BIP38) erkannt.",
"reorder_title": "Wallets neu ordnen",
"reorder_instructions": "Tippen und halten Sie eine Wallet, um sie umzuplatzieren.",
"please_continue_scanning": "Bitte Scanvorgang fortsetzten",
"scan_error": "Scanfehler",
"select_no_bitcoin": "Es sind momentan keine Bitcoin Wallets verfügbar.",
@ -625,6 +626,7 @@
"cc": {
"change": "Ändern",
"coins_selected": "Anz. gewählte Münzen ({number})",
"selected_summ": "{value} ausgewählt",
"empty": "Dieses Wallet hat aktuell keine Münzen",
"freeze": "einfrieren",
"freezeLabel": "Einfrieren",
@ -651,17 +653,26 @@
"sign_placeholder_address": "Adresse",
"sign_placeholder_message": "Meldung",
"sign_placeholder_signature": "Signatur",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Senden der signierten Nachricht nach {hostname}?",
"addresses_title": "Adressen",
"type_change": "Wechsel",
"type_receive": "Empfang",
"type_used": "Verwendet",
"transactions": "Transaktionen"
},
"aopp": {
"title": "Adresse wählen",
"send_success": "Signatur erfolgreich gesendet",
"send_error": "Fehler beim Senden der Signatur"
"lnurl_auth": {
"register_question_part_1": "Möchten Sie ein Konto bei",
"register_question_part_2": "mit Ihrem LN-Wallet registrieren?",
"register_answer": "Konto bei {hostname} erfolgreich registriert!",
"login_question_part_1": "Möchten Sie sich mit Ihrem LN-Wallet auf",
"login_question_part_2": "anmelden?",
"login_answer": "Erfolgreich angemeldet bei {hostname}!",
"link_question_part_1": "Möchten Sie Ihr Konto auf",
"link_question_part_2": "mit Ihrem LN-Wallet verknüpfen?",
"link_answer": "Ihr LN-Wallet wurde erfolgreich mit Ihrem Konto bei {hostname} verknüpft!",
"auth_question_part_1": "Möchten Sie sich mit Ihrem LN-Wallet bei",
"auth_question_part_2": "authentifizieren?",
"auth_answer": "Erfolgreich authentifiziert bei {hostname}!",
"could_not_auth": "Authentifizierung bei {hostname} fehlgeschlagen.",
"authenticate": "Authentifizieren"
}
}

View File

@ -525,6 +525,7 @@
"no_ln_wallet_error": "Before paying a Lightning invoice, you must first add a Lightning wallet.",
"looks_like_bip38": "This looks like a password-protected private key (BIP38).",
"reorder_title": "Re-order Wallets",
"reorder_instructions": "Tap and hold a wallet to drag it across the list.",
"please_continue_scanning": "Please continue scanning.",
"scan_error": "Scan Error",
"select_no_bitcoin": "There are currently no Bitcoin wallets available.",
@ -625,6 +626,7 @@
"cc": {
"change": "Change",
"coins_selected": "Coins Selected ({number})",
"selected_summ": "{value} selected",
"empty": "This wallet doesnt have any coins at the moment.",
"freeze": "Freeze",
"freezeLabel": "Freeze",
@ -651,17 +653,26 @@
"sign_placeholder_address": "Address",
"sign_placeholder_message": "Message",
"sign_placeholder_signature": "Signature",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Do you want to send a signed message to {hostname}?",
"addresses_title": "Addresses",
"type_change": "Change",
"type_receive": "Receive",
"type_used": "Used",
"transactions": "Transactions"
},
"aopp": {
"title": "Select Address",
"send_success": "Signature sent successfully",
"send_error": "Signature sending error"
"lnurl_auth": {
"register_question_part_1": "Do you want to register an account at ",
"register_question_part_2": "using your LN wallet?",
"register_answer": "Sucessfully registered an account at {hostname}!",
"login_question_part_1": "Do you want to login at ",
"login_question_part_2": "using your LN wallet?",
"login_answer": "Sucessfully logged in at {hostname}!",
"link_question_part_1": "Link your account at ",
"link_question_part_2": "to your LN wallet?",
"link_answer": "Your LN wallet was sucessfully linked to your account at {hostname}!",
"auth_question_part_1": "Do you want to authenticate at ",
"auth_question_part_2": "using your LN wallet?",
"auth_answer": "Sucessfully authenticated at {hostname}!",
"could_not_auth": "Could not authenticate to {hostname}.",
"authenticate": "Authenticate"
}
}

View File

@ -648,17 +648,10 @@
"sign_placeholder_address": "Dirección",
"sign_placeholder_message": "Mensaje",
"sign_placeholder_signature": "Firma",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "¿Quieres enviar un mensaje firmado a {hostname}?",
"addresses_title": "Direcciones",
"type_change": "Cambio",
"type_receive": "Recibir",
"type_used": "Usado",
"transactions": "Transacciones"
},
"aopp": {
"title": "Selecciona la dirección",
"send_success": "Firma enviada correctamente",
"send_error": "Error al enviar la firma"
}
}

View File

@ -525,6 +525,7 @@
"no_ln_wallet_error": "Antes de pagar una factura Lightning, primero debes agregar una billetera Lightning.",
"looks_like_bip38": "Esto parece una clave privada protegida por contraseña (BIP38).",
"reorder_title": "Reorganizar Billeteras",
"reorder_instructions": "Toca y mantén presionada una billetera para arrastrarla por la lista.",
"please_continue_scanning": "Por favor continúa escaneando.",
"scan_error": "Error de Escaneo",
"select_no_bitcoin": "Actualmente no hay billeteras Bitcoin disponibles.",
@ -625,6 +626,7 @@
"cc": {
"change": "Cambio",
"coins_selected": "Monedas Seleccionadas ({number})",
"selected_summ": "{value} seleccionado",
"empty": "Esta billetera no tiene monedas en este momento.",
"freeze": "Congelar",
"freezeLabel": "Congelar",
@ -651,17 +653,10 @@
"sign_placeholder_address": "Dirección",
"sign_placeholder_message": "Mensaje",
"sign_placeholder_signature": "Firma",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "¿Quieres enviar un mensaje firmado a {hostname}?",
"addresses_title": "Direcciones",
"type_change": "Cambio",
"type_receive": "Recibir",
"type_used": "Usado",
"transactions": "Transacciones"
},
"aopp": {
"title": "Seleccionar dirección",
"send_success": "Firma enviada con éxito",
"send_error": "Error de envío de firma"
}
}

View File

@ -185,7 +185,7 @@
"header": "دریافت"
},
"send": {
"provided_address_is_invoice": "به‌نظر می‌آید این آدرس یک صورت‌حساب لایتنینگی است. جهت پرداخت این صورت‌حساب لطفاً به کیف پول لایتنینگ خود بروید.",
"provided_address_is_invoice": "به‌نظر می‌آید این آدرس یک صورت‌حساب لایتنینگ است. جهت پرداخت این صورت‌حساب لطفاً به کیف پول لایتنینگ خود بروید.",
"broadcastButton": "انتشار",
"broadcastError": "خطا",
"broadcastNone": "هگزادسیمال تراکنش را وارد کنید",
@ -525,6 +525,7 @@
"no_ln_wallet_error": "قبل از پرداخت یک صورت‌حساب لایتنینگ، ابتدا باید یک کیف پول لایتنینگ اضافه کنید.",
"looks_like_bip38": "این به کلید خصوصی محافظت‌شده با گذرواژه (BIP38) شباهت دارد.",
"reorder_title": "بازچینی کیف پول‌ها",
"reorder_instructions": "روی یک کیف پول بزنید و نگه دارید تا آن را در لیست جابه‌جا کنید.",
"please_continue_scanning": "لطفاً به اسکن‌کردن ادامه دهید.",
"scan_error": "خطا در اسکن",
"select_no_bitcoin": "هیچ کیف پول بیت‌کوینی درحال‌حاضر دردسترس نیست.",
@ -625,6 +626,7 @@
"cc": {
"change": "باقی‌مانده (change)",
"coins_selected": "کوین‌های انتخاب‌شده ({number})",
"selected_summ": "انتخاب‌شده: {value}",
"empty": "این کیف پول درحال‌حاضر هیچ کوینی ندارد.",
"freeze": "مسدود",
"freezeLabel": "مسدودکردن",
@ -651,17 +653,26 @@
"sign_placeholder_address": "آدرس",
"sign_placeholder_message": "پیام",
"sign_placeholder_signature": "امضا",
"sign_aopp_title": "پروتکل اثبات مالکیت آدرس (AOPP)",
"sign_aopp_confirm": "آیا مایل به ارسال پیام امضاشده به {hostname} هستید؟",
"addresses_title": "آدرس‌ها",
"type_change": "باقی‌مانده",
"type_receive": "دریافت",
"type_used": "استفاده‌شده",
"transactions": "تراکنش‌ها"
},
"aopp": {
"title": "انتخاب آدرس",
"send_success": "امضا با موفقیت ارسال شد.",
"send_error": "خطا در ارسال امضا"
"lnurl_auth": {
"register_question_part_1": "آیا می‌خواهید حسابی در",
"register_question_part_2": "با استفاده از کیف پول لایتنینگ خود بسازید؟",
"register_answer": "حساب در {hostname} با موفقیت ساخته شد!",
"login_question_part_1": "آیا می‌خواهید در",
"login_question_part_2": "با استفاده از کیف پول لایتنینگ خود وارد شوید؟",
"login_answer": "با موفقیت در {hostname} وارد شدید!",
"link_question_part_1": "حسابتان در",
"link_question_part_2": "به کیف پول لایتنینگ شما متصل شود؟",
"link_answer": "کیف پول لایتنینگ شما با موفقیت به حسابتان در {hostname} متصل شد!",
"auth_question_part_1": "آیا می‌خواهید در",
"auth_question_part_2": "با استفاده از کیف پول لایتنینگ خود احراز کنید؟",
"auth_answer": "احراز در {hostname} با موفقیت انجام شد!",
"could_not_auth": "احراز در {hostname} انجام نشد.",
"authenticate": "احراز"
}
}

View File

@ -3,8 +3,10 @@
"bad_password": "Väärä salasana, yritä uudelleen.",
"cancel": "Peruuta",
"continue": "Jatka",
"clipboard": "Leikepöytä",
"enter_password": "Anna salasana",
"never": "ei koskaan",
"disabled": "Poissa käytöstä",
"of": "{number} / {total}",
"ok": "OK",
"storage_is_encrypted": "Tallennustilasi on salattu. Sen purkamiseksi vaaditaan salasana",
@ -16,10 +18,18 @@
"seed": "Siemen",
"success": "Onnistui",
"wallet_key": "Lompakkoavain",
"invalid_animated_qr_code_fragment": "Virheellinen animoitu QRCode-fragmentti, yritä uudelleen",
"invalid_animated_qr_code_fragment" : "Virheellinen animoitu QRCode-fragmentti, yritä uudelleen",
"file_saved": "Tiedosto {filePath} on talletettu sinun {destination}.",
"file_save_title": "Tallenna tiedosto",
"file_save_location": "Valitse tallennus sijainti {filePath}",
"downloads_folder": "Lataukset-kansio",
"external_storage": "Ulkoinen tallennuslaite",
"discard_changes": "Hylkää muutokset?",
"discard_changes_detail": "Sinulla on tallentamattomia muutoksia. Haluatko varmasti hylätä ne ja poistut näytöltä? "
},
"alert": {
"default": "Hälytys"
},
"azteco": {
"codeIs": "Kuponkikoodisi on",
"errorBeforeRefeem": "Ennen lunastamista sinun on ensin lisättävä Bitcoin-lompakko",
@ -92,20 +102,45 @@
"p2p": "Osta Bitcoinia p2p-pörssistä "
},
"lnd": {
"active":"Aktiivinen",
"inactive":"Passiivinen",
"channels": "Kanavat",
"no_channels": "Ei kanavia",
"claim_balance": "Lunasta saldo {balance}",
"close_channel": "Sulje kanava",
"new_channel" : "Uusi kanava",
"errorInvoiceExpired": "Lasku vanheni",
"exchange": "Vaihto",
"force_close_channel": "Pakota kanavan sulku?",
"expired": "Erääntynyt",
"node_alias": "Solmun lempinimi",
"expiredLow": "erääntynyt",
"expiresIn": "Vanhenee {time} minuutissa",
"payButton": "Maksa",
"placeholder": "Lasku",
"open_channel": "Avaa kanava",
"funding_amount_placeholder": "Rahoitettava määrä, esimerkiksi 0.001",
"opening_channnel_for_from":"Ota rahoitus {fromWalletLabel}:sta kanavan avaamiseksi lompakkoon {forWalletLabel}",
"are_you_sure_open_channel": "Oletko varma että haluat avata tämän kanavan?",
"are_you_sure_exit_without_new_channel": "Oletko varma että haluat poistua avaamatta kanavaa?",
"public": "Julkinen",
"public_description": "Verkkoon näkyvä: Se voi olla reitittävä solmu ja kerätä maksuja",
"private": "Yksityinen",
"private_description": "Verkossa näkymätön: Se suojaa maksujesi yksityisyyttä.",
"local_reserve": "Paikallinen varanto",
"potentialFee": "Mahdollinen siirtokulu: {fee}",
"remote_host": "Etäpalvelin",
"refill": "Täytä",
"refill_card": "Täytä pankkikortilla",
"reconnect_peer": "Palauta yhteys naapuriin",
"refill_create": "Jatka luomalla Bitcoin-lompakko, jolla voit täyttää sen.",
"refill_external": "Täytä ulkoisella lompakolla",
"refill_lnd_balance": "Täytä Lightning-lompakon saldoa",
"sameWalletAsInvoiceError": "Et voi maksaa laskua samalla lompakolla, jolla se on luotu.",
"title": "hallinnoi varoja"
"title": "hallinnoi varoja",
"can_send": "Lähetettävissä",
"can_receive": "Vastaanotettavissa",
"view_logs": "Näytä lokitiedot"
},
"lndViewInvoice": {
"additional_info": "Lisäinformaatio",
@ -113,6 +148,7 @@
"lightning_invoice": "Lightning-lasku",
"has_been_paid": "Tämä lasku on maksettu",
"open_direct_channel": "Avaa suora kanava tällä solmulla:",
"please_pay_between_and": "Maksa vähintään {min} ja enintään {max}",
"please_pay": "Ole hyvä ja maksa",
"preimage": "Alkukuva",
"sats": "sattia",
@ -134,8 +170,12 @@
"ask": "Oletko tallentanut lompakon varmuuskopion? Tämä varmuuskopio vaaditaan varojen käyttämiseen, jos kadotat tämän laitteen. Ilman varmuuskopiota varat menetetään lopullisesti.",
"ask_no": "Ei, en ole",
"ask_yes": "Kyllä, olen",
"ok": "OK, kirjoitin sen ylös",
"ok_lnd": "OK, Olen tallettanut sen",
"text": "Varaa hetki aikaa ja kirjoita palautuslause (mnemonic) talteen paperille.\nSe on varmuuskopiosi ja voit käyttää sitä lompakon palauttamiseen.",
"text_lnd": "Tallenna tämä lompakon varmuuskopio. Sen avulla voit palauttaa lompakon, jos lompakko katoaa.",
"text_lnd2": "Tätä lompakkoa ylläpitää BlueWallet."
"text_lnd2": "Tätä lompakkoa ylläpitää BlueWallet.",
"title": "Lompakkosi on luotu"
},
"receive": {
"details_create": "Luo",
@ -145,6 +185,7 @@
"header": "Vastaanota"
},
"send": {
"provided_address_is_invoice": "Tämä osoite vaikuttaa olevan Lightning-lasku. Maksun suorittamiseksi, siirry Lightning-lompakkoosi.",
"broadcastButton": "LÄHETÄ",
"broadcastError": "virhe",
"broadcastNone": "Syötä siirtotapahtuman tiiviste",
@ -158,7 +199,7 @@
"create_details": "Tarkemmat tiedot",
"create_fee": "Siirtokulu",
"create_memo": "Muistio",
"create_satoshi_per_byte": "Satoshia per tavu",
"create_satoshi_per_vbyte": "satoshia per vbyte",
"create_this_is_hex": "Tämä on siirtotapahtuman hex, allekirjoitettu ja valmis lähetettävksi verkkoon.",
"create_to": "Vastaanottaja",
"create_tx_size": "Siirtotapahtuman koko",
@ -170,17 +211,22 @@
"details_adv_fee_bump": "Salli Siirtokulun Nosto",
"details_adv_full": "Käytä koko saldo",
"details_adv_full_sure": "Haluatko varmasti käyttää lompakon koko saldon tähän siirtotapahtumaan?",
"details_adv_full_sure_frozen": "Haluatko varmasti käyttää koko lompakkosi saldon tähän tapahtumaan? Huomioithan että jäädytetyt kolikot jäävät tapahtuman ulkopuolelle.",
"details_adv_import": "Tuo Siirtotapahtuma",
"details_adv_import_qr": "Tuo tapahtuma (QR)",
"details_amount_field_is_not_valid": "Määrä ei kelpaa",
"details_amount_field_is_less_than_minimum_amount_sat": "Määritetty määrä on liian pieni. Anna summa, joka on yli 500 sattia. ",
"details_create": "Luo Lasku",
"details_error_decode": "Bitcoin-osoitetta ei voida dekoodata ",
"details_fee_field_is_not_valid": "Siirtokulukenttä ei ole pätevä",
"details_frozen": "{amount} BTC on jäädytetty",
"details_next": "Seuraava",
"details_no_signed_tx": "Valittu tiedosto ei sisällä tuotavaa siirtotapahtumaa.",
"details_note_placeholder": "muistiinpano itselle",
"details_scan": "Skannaa",
"details_scan_hint": "Scannaa tai tuo tupla-napauttamalla",
"details_total_exceeds_balance": "Lähetettävä summa ylittää katteen",
"details_total_exceeds_balance_frozen": "Lähetettävä määrä ylittää käytettävissä olevan saldon. Huomioithan että jäädytetyt kolikot jäävät tapahtuman ulkopuolelle.",
"details_unrecognized_file_format": "Tunnistamaton tiedostomuoto ",
"details_wallet_before_tx": "Ennen siirtotapahtuman luomista, sinun on ensin lisättävä Bitcoin-lompakko.",
"dynamic_init": "Alustaa",
@ -194,8 +240,8 @@
"fee_custom": "Mukautettu",
"fee_fast": "Nopea",
"fee_medium": "Keskitaso",
"fee_replace_min": "Maksettavan kokonaiskulun (satoshia tavua kohti) tulisi olla korkeampi kuin {min} sat/tavu",
"fee_satbyte": "sat/tavu",
"fee_replace_minvb": "Kulujen maksimimäärä (satoshia / vByte) jonka olet valmis maksamaan, tulee olla enemmän kuin {min} satoshia / vByte.",
"fee_satvbyte": "sat/vByte",
"fee_slow": "Hidas",
"header": "Lähetä",
"input_clear": "Tyhjää",
@ -208,15 +254,19 @@
"open_settings": "Avaa Asetukset",
"permission_storage_later": "Kysy Minulta Myöhemmin",
"permission_storage_message": "BlueWallet tarvitsee lupasi käyttääkseen tallennustilaasi tämän tiedoston tallentamiseksi.",
"permission_storage_denied_message": "BlueWallet ei voi tallentaa tätä tiedostoa. Avaa laitteen asetukset ja ota Tallennusoikeus käyttöön.",
"permission_storage_denied_message": "BlueWallet ei voinut tallettaa tätä tiedostoa. Aseta laitteesi sallimaan tallentaminen kyttkemällä Storage Permission päälle.",
"permission_storage_title": "Tallennustilan käyttöoikeus",
"psbt_clipboard": "Kopioi Leikepöydälle",
"psbt_this_is_psbt": "Tämä on osittain allekirjoitettu bitcoin-siirtotapahtuma (PSBT). Ole hyvä ja allekirjoita se hardware-lompakolla.",
"psbt_tx_export": "Vie tiedostoon",
"no_tx_signing_in_progress": "Siirtotapahtuman allekirjoittamista ei ole käynnissä",
"outdated_rate": "Vaihtokurssi päivitettiin viimeksi: {date}",
"psbt_tx_open": "Avaa Allekirjoitettu Siirtotapahtuma",
"psbt_tx_scan": "Skannaa Allekirjoitettu Siirtotapahtuma",
"qr_error_no_qrcode": "Kuvasta ei löytynyt QR-koodia. Varmista että kuva sisältää ainoastaan QR-koodin eikä muita tietoja kuten tekstia tai nappeja.",
"qr_error_no_wallet": "Valittu tiedosto ei sisällä tuotavaa lompakkoa.",
"reset_amount": "Nollaa määrä",
"reset_amount_confirm": "Haluaisitko nollata määrän?",
"success_done": "Valmis",
"txSaved": "Siirtotapahtumatiedosto ({filePath}) on tallennettu Lataukset-kansioon.",
"problem_with_psbt": "Ongelma PSBT:n kanssa"
@ -230,6 +280,7 @@
"about_release_notes": "Julkaisutiedot",
"about_review": "Jätä meille arvostelu",
"about_selftest": "Suorita itsetestaus",
"about_selftest_electrum_disabled": "Electrum Self-Test toimintoa ei ole mahdollista käyttää offline-tilassa. Siirry pois offline-tilasta ja yritä uudelleen",
"about_selftest_ok": "Kaikki sisäiset testit on läpäisty onnistuneesti. Lompakko toimii hyvin. ",
"about_sm_github": "GitHub",
"about_sm_discord": "Discord-serveri",
@ -243,16 +294,26 @@
"biom_remove_decrypt": "Kaikki lompakot poistetaan ja tallennustilasi puretaan. Haluatko varmasti jatkaa?",
"currency": "Valuutta",
"currency_source": "Hinnat saadaan",
"currency_fetch_error": "Valitu valuutan vaihtokurssin hakemisessa tapahtui virhe.",
"default_desc": "Kun on pois käytöstä, BlueWallet avaa valitun lompakon heti käynnistettäessä.",
"default_info": "Oletustiedot",
"default_title": "Käynnistettäessä",
"default_wallets": "Näytä Kaikki Lompakot",
"electrum_connected": "Yhdistetty",
"electrum_connected_not": "Ei yhteyttä",
"electrum_connnected_not_description": "Lompakon tuonti edellyttää Electrum-palvelinyhteyttä. Kytke yhteys päälle Asetuksien Verkko -osiosta.",
"electrum_error_connect": "Ei voida yhdistää tarjottuun Electrum-palvelimeen",
"lndhub_uri": "esim, {example}",
"electrum_host": "esim, {example}",
"electrum_offline_mode": "Offline-tila",
"electrum_offline_description": "Jos tämä on valittuna, niin bitcoin-lompakkojen saldoja ja tapahtumia ei yritetä hakea.",
"electrum_port": "Portti, yleensä {example}",
"use_ssl": "Käytä SSL",
"electrum_saved": "Muutoksesi on tallennettu onnistuneesti. Uudelleenkäynnistys voi olla tarpeen, jotta muutokset tulevat voimaan.",
"set_electrum_server_as_default": "Asetetaanko {server} oletus Electrum-palvelimeksi?",
"set_lndhub_as_default": "Asetetaanko {url} oletus LNDHub-palvelimeksi?",
"electrum_settings_server": "Electrum-palvelin",
"electrum_settings_explain": "Jos haluat käyttää oletusta, jätä tämä tyhjäksi.",
"electrum_status": "Tila",
"electrum_clear_alert_title": "Tyhjennä historia?",
"electrum_clear_alert_message": "Haluatko tyhjentää Electrum-palvelinten historian?",
@ -264,6 +325,8 @@
"electrum_history": "Palvelimen historia",
"electrum_reset_to_default": "Haluatko varmasti palauttaa Electrumin asetukset oletusarvoihin? ",
"electrum_clear": "Tyhjennä",
"tor_supported": "Tor on tuettu",
"tor_unsupported": "Tor yhteyksiä ei tueta",
"encrypt_decrypt": "Pura tallennustilan salaus",
"encrypt_decrypt_q": "Haluatko varmasti purkaa tallennustilan salauksen? Tämä mahdollistaa lompakkoihisi pääsyn ilman salasanaa.",
"encrypt_del_uninstall": "Poista, jos BlueWallet poistetaan",
@ -271,7 +334,7 @@
"encrypt_title": "Tietoturva",
"encrypt_tstorage": "tallennustila",
"encrypt_use": "Käytä {type}",
"encrypt_use_expl": "{type} käytetään henkilöllisyytesi vahvistamiseen ennen siirtotapahtuman tekemistä, lompakon lukituksen avaamista, vientiä tai poistamista. {type} ei käytetä salatun tallennustilan lukituksen avaamiseen.",
"encrypt_use_expl": "Ennen tapahtumia, avaamista vientiä tai lompakon poistoa identiteettis varmistetaan {type}:lla. {type} ei kuitenkaan voi käyttää salatun tallennustilan avaamiseen.",
"general": "Yleinen",
"general_adv_mode": "Lisäasetukset",
"general_adv_mode_e": "Kun tämä asetus on käytössä, näet lisäasetukset, kuten erilaiset lompakkotyypit, kyvyn määrittää LNDHub-instanssi, johon haluat muodostaa yhteyden ja mukautetun entropian lompakon luomisen aikana.",
@ -280,16 +343,19 @@
"groundcontrol_explanation": "GroundControl on ilmainen avoimen lähdekoodin push-ilmoituspalvelin bitcoin-lompakoille. Voit asentaa oman GroundControl-palvelimen ja laittaa sen URL-osoitteen tähän, jotta et luota BlueWallet-infrastruktuuriin. Jätä tyhjäksi käyttääksesi oletusasetusta",
"header": "asetukset",
"language": "Kieli",
"last_updated": "Päivitetty viimeksi",
"language_isRTL": "BlueWallet on käynnistettävä uudelleen, jotta kielisuuntaus tulee voimaan.",
"lightning_error_lndhub_uri": "LndHub-URI ei kelpaa",
"lightning_error_lndhub_uri": "Virheellinen LNDHub URI",
"lightning_saved": "Muutoksesi on tallennettu onnistuneesti",
"lightning_settings": "Lightning-Asetukset",
"tor_settings": "Tor-asetukset",
"lightning_settings_explain": "Oman LND-solmun käyttö edellyttää että, siihen on asennettu LNDHub-ohjelmisto ja sen URL on määritelty tähän. Kentän ollessa tyhjä on käytössä BleaWallet:in oma LNDHub (lndhub.io). Huomaathan että asetusten tallettamisen jälkeen luodut lompakot yhdistäytyvät määriteltyyn solmuun.",
"network": "Verkko",
"network_broadcast": "Lähetä siirtotapahtuma",
"network_electrum": "Electrum-palvelin",
"not_a_valid_uri": "URI ei kelpaa",
"not_a_valid_uri": "Virheellinen URI",
"notifications": "Ilmoitukset",
"open_link_in_explorer": "Avaa linkki selaimessa",
"open_link_in_explorer" : "Avaa linkki selaimessa",
"password": "Salasana",
"password_explain": "Luo salasana, jota käytät tallennustilan salauksen purkamiseen",
"passwords_do_not_match": "Salasanat eivät täsmää",
@ -301,12 +367,15 @@
"privacy_quickactions": "Lompakon Pikanäppäimet",
"privacy_quickactions_explanation": "Kosketa ja pidä Aloitusnäytön BlueWallet-sovelluskuvaketta nähdäksesi nopeasti lompakon saldon.",
"privacy_clipboard_explanation": "Toimita pikakuvakkeet, jos leikepöydältä löytyy osoite tai lasku.",
"privacy_do_not_track": "Poista analytiikka käytöstä",
"privacy_do_not_track_explanation": "Suorituskyky- ja luotettavuustietoja ei lähtetä analysoitavaksi.",
"push_notifications": "Push-ilmoitukset",
"rate": "Vaihtokurssi",
"retype_password": "Salasana uudelleen",
"selfTest": "Itsetestaus ",
"save": "Tallenna",
"saved": "Tallennettu",
"success_transaction_broadcasted": "Onnistui! Siirtotapahtumasi on lähetetty!",
"success_transaction_broadcasted" : "Tapahtumasi on lähetetty onnistuneesti.",
"total_balance": "Kokonaissaldo",
"total_balance_explanation": "Näytä kaikkien lompakoiden kokonaissaldo aloitusnäytön widgeteissä.",
"widgets": "Widgetit",
@ -322,9 +391,8 @@
"cancel_no": "Tämä siirtotapahtuma ei ole vaihdettavissa",
"cancel_title": "Peruuta tämä siirtotapahtuma (RBF)",
"confirmations_lowercase": "{confirmations} vahvistukset",
"note": "Huomautus",
"copy_link": "Kopioi linkki",
"expand_note": "Laajenna huomautus",
"block_explorer_link": "Lohkoselain-linkki",
"cpfp_create": "Luo",
"cpfp_exp": "Luomme toisen siirtotapahtuman, joka kuluttaa vahvistamattoman siirtotapahtuman. Kokonaiskulu on suurempi kuin alkuperäinen siirtokulu, joten sen pitäisi olla louhittu nopeammin. Tätä kutsutaan CPFP - Child Pays For Parent - Lapsi Maksaa Vanhemmalle.",
"cpfp_no_bump": "Tämä siirtotapahtuma ei ole nostettavissa",
@ -333,6 +401,10 @@
"details_balance_show": "Näytä Saldo",
"details_block": "Lohkon järjestysnumero",
"details_copy": "Kopioi",
"details_copy_amount": "Kopioi määrä",
"details_copy_block_explorer_link": "Kopioi linkki lohkoketjuselaimeen",
"details_copy_note": "Kopioi muistiinpanot",
"details_copy_txid": "Kopioi tapahtumatunnus",
"details_from": "Syöte",
"details_inputs": "Syötteet",
"details_outputs": "Ulostulot",
@ -345,7 +417,13 @@
"enable_offline_signing": "Tätä lompakkoa ei käytetä offline-allekirjoituksen yhteydessä. Haluatko ottaa sen käyttöön nyt? ",
"list_conf": "conf: {number}",
"pending": "Odottaa",
"pending_with_amount": "Odottaa {amt1} ({amd2})",
"received_with_amount": "+{amt1} ({amd2})",
"eta_10m": "Saapuu n.10 minuutissa",
"eta_3h": "Saapuu n.3 tunnissa",
"eta_1d": "Saapuu noin vuorokaudessa",
"list_title": "siirtotapahtumat",
"open_url_error": "URL-osoiteen avaaminen oletusselaimella ei onnistunut. Vaihda käyttämäsi selaimen oletusasetus ja yritä uudelleen.",
"rbf_explain": "Korvaamme tämän siirtotapahtuman toisella jossa on korkeammat siirtokulut, joten se pitäisi olla louhittu nopeammin. Tätä kutsutaan RBF - Replace By Fee - Korvattavissa korkeammilla kuluilla.",
"rbf_title": "Nosta siirtokuluja (RBF)",
"status_bump": "Nosta siirtokuluja",
@ -365,12 +443,14 @@
"add_lightning": "Lightning",
"add_lightning_explain": "Käytetään välittömiin siirtotapahtumiin",
"add_lndhub": "Yhdistä LNDHub:iisi",
"add_lndhub_error": "Annettu solmun osoite ei ole kelvollinen LNDHub-solmu.",
"add_lndhub_error": "Annettu solmun osoite ei ole kelvollinen LNDHub solmu",
"add_lndhub_placeholder": "solmusi osoite",
"add_or": "tai",
"add_placeholder": "minun lompakkoni",
"add_title": "lisää lompakko",
"add_wallet_name": "nimi",
"add_wallet_type": "tyyppi",
"balance": "Saldo",
"clipboard_bitcoin": "Sinulla on leikepöydällä Bitcoin-osoite. Haluatko käyttää sitä siirtotapahtumaan?",
"clipboard_lightning": "Leikepöydälläsi on Lightning Invoice. Haluatko käyttää sitä siirtotapahtumaan?",
"details_address": "Osoite",
@ -378,7 +458,7 @@
"details_are_you_sure": "Oletko varma?",
"details_connected_to": "Yhdistetty",
"details_del_wb_err": "Annettu saldo ei vastaa tämän lompakon saldoa. Yritä uudelleen",
"details_del_wb_q": "Tällä lompakolla on saldoa. Ennen kuin jatkat, huomaa, että et voi palauttaa varoja ilman tämän lompakon siemenlauseketta. Syötä lompakkosi saldo {balance} satoshia välttääksesi vahingossa tämän lompakon poistamisen.",
"details_del_wb_q": "Lompakossa on varoja. Ennenkuin jatkat, ymmärrä että tarvitset lompakon palautukseen tulevaisuudeessa palautuslauseen. Varmistaaksemme ettet tuhoa lompakkoa vahingossa, tulee sinun syöttää saldosi {balance} satosheina.",
"details_delete": "Poista",
"details_delete_wallet": "Poista lompakko",
"details_derivation_path": "johdantopolku",
@ -393,6 +473,7 @@
"details_no_cancel": "Ei, peruuta",
"details_save": "Tallenna",
"details_show_xpub": "Näytä lompakon XPUB",
"details_show_addresses": "Näytä osoitteet",
"details_title": "Lompakko",
"details_type": "Tyyppi",
"details_use_with_hardware_wallet": "Käytä hardware-lompakon kanssa",
@ -401,15 +482,28 @@
"enter_bip38_password": "Syötä salasana salauksen purkamiseksi",
"export_title": "lompakon vienti",
"import_do_import": "Tuo",
"import_passphrase": "tunnuslause",
"import_passphrase_title": "tunnuslause",
"import_passphrase_message": "Anna tunnuslause, mikäli olet käyttänyt sellaista",
"import_error": "Tuonti epäonnistui. Varmista, että annettu tieto on oikein",
"import_explanation": "Kirjoita siemensanasi, julkinen avain, WIF tai mikä tahansa sinulla on. BlueWallet tekee parhaansa arvatakseen oikean formaatin ja tuodakseen lompakkosi. ",
"import_file": "Tuo tiedosto",
"import_imported": "Tuotu",
"import_placeholder_fail": "Lompakon tuonti",
"import_placeholder_inprogress": "Tuodaan lompakkoa...",
"import_scan_qr": "Skannaa tai tuo tiedosto",
"import_success": "Lompakkosi tuonti onnistui.",
"import_search_accounts": "Hae tilejä",
"import_title": "tuo",
"import_discovery_title": "Etsiminen",
"import_discovery_subtitle": "Valitse löydetty lompakko",
"import_discovery_derivation": "Vaihtoehtoinen derivation path",
"import_discovery_no_wallets": "Lompakkoja ei löytynyt",
"import_derivation_found": "löytyi",
"import_derivation_found_not": "ei löytynyt",
"import_derivation_loading": "ladataan...",
"import_derivation_subtitle": "Syötä vaihtoehtoinen derivation path, niin yritämme etsiä lompakkosi",
"import_derivation_title": "Derivation path",
"import_derivation_unknown": "tuntematon",
"import_wrong_path": "Väärä derivation path",
"list_create_a_button": "Lisää nyt",
"list_create_a_wallet": "Lisää lompakko",
"list_create_a_wallet_text": "Se on ilmainen ja voit luoda\nniin monta kuin haluat",
@ -418,7 +512,6 @@
"list_empty_txs2": "Aloita lompakostasi. ",
"list_empty_txs2_lightning": "Aloita lompakon käyttäminen napsauttamalla \"hallinnoi varoja\" ja lisää saldoasi.\n",
"list_header": "Lompakko edustaa avainparia, yhtä yksityistä ja yhtä, jonka voit jakaa vastaanottaaksesi varoja.",
"list_import_error": "Tämän lompakon tuomisessa tapahtui virhe.",
"list_import_problem": "Tämän lompakon tuomisessa oli ongelma",
"list_latest_transaction": "viimeisin siirto",
"list_ln_browser": "LApp-selain",
@ -432,6 +525,7 @@
"no_ln_wallet_error": "Ennen kuin maksat Lightning-laskun, sinun on ensin lisättävä Lightning-lompakko.",
"looks_like_bip38": "Tämä näyttää salasanalla suojatulta yksityiseltä avaimelta (BIP38)",
"reorder_title": "Järjestele Lompakot",
"reorder_instructions": "Siirrä listalla, ensin napauttamalla ja pitämällä, sitten vetäen.",
"please_continue_scanning": "Jatka skannausta",
"scan_error": "Skannausvirhe ",
"select_no_bitcoin": "Bitcoin-lompakkoa ei tällä hetkellä ole saatavana.",
@ -486,7 +580,7 @@
"wallet_type": "Lompakon tyyppi",
"view_key": "näkymä",
"invalid_mnemonics": "Tämä muistilauseke ei näytä olevan pätevä",
"invalid_cosigner": "Ei kelvollisia allekirjoitustietoja",
"invalid_cosigner": "Virheellinen kanssa-allekirjoittajan tieto",
"not_a_multisignature_xpub": "Tämä ei ole xpub multisignature-lompakosta!",
"invalid_cosigner_format": "Virheellinen allekirjoittaja: tämä ei ole muodon {format} allekirjoittaja",
"create_new_key": "Luo Uusi",
@ -513,9 +607,9 @@
"ms_help_title1": "Useita laitteita suositellaan",
"ms_help_1": "Vault toimii muiden BlueWallet-sovellusten ja PSBT-yhteensopivien lompakoiden kanssa, kuten Electrum, Spectre, Coldcard, Cobo vault jne.",
"ms_help_title2": "Avainten Muokkaus",
"ms_help_2": "Voit luoda kaikki Vault-avaimet tälle laitteelle ja poistaa tai muokata niitä myöhemmin. Pitämällä kaikki avaimet samalla laitteella on vastaavanlainen suojaus kuin tavallisella Bitcoin-lompakolla.",
"ms_help_2": "Voit luoda holvi-avaimia tässä laitteessa. Ja sitten myöhemmin poistaa ja muokate niitä. Kaikkien avaimien pitäminen samassa laitteessa on yhtä turvallista kuin tavallisessa Bitcoin-lompakossakin.",
"ms_help_title3": "Vault-varmuuskopiot",
"ms_help_3": "Lompakon vaihtoehdoista löydät Vault-varmuuskopion ja vain-lukuoikeus varmuuskopion. Tämä varmuuskopio on kuin kartta lompakkoosi. Se on välttämätöntä lompakon palauttamiseksi, jos menetät yhden siemenistäsi.",
"ms_help_3": "Holvi- ja katselu varmuuskopiot löydät lompakon asetuksista. Tämä varmuuskopio on kartta lompakollesi. Se on välttämätön lompakon palauttamiseksi, mikäli ole hukannut yhdenkään siemensanan tai lauseen.",
"ms_help_title4": "Tuodaan Vault:ia",
"ms_help_4": "Voit tuoda multisig:in käyttämällä varmuuskopiotiedostoasi ja Tuo-ominaisuutta. Jos sinulla on vain laajennettuja avaimia ja siemensanoja, voit käyttää yksittäistä Tuo-näppäintä, kun luot Vault -avaimia.",
"ms_help_title5": "Lisäasetukset",
@ -526,11 +620,13 @@
"owns": "{label} omistaa {address}",
"enter_address": "Syötä osoite",
"check_address": "Tarkista osoite",
"no_wallet_owns_address": "Mikään käytettävissä olevista lompakoista ei omista annettua osoitetta."
"no_wallet_owns_address": "Mikään käytettävissä olevista lompakoista ei omista annettua osoitetta.",
"view_qrcode": "Näytä QR-koodi"
},
"cc": {
"change": "vaihto",
"coins_selected": "Kolikot valittu ({number})",
"selected_summ": "{value} valittuna",
"empty": "Tässä lompakossa ei ole tällä hetkellä kolikoita",
"freeze": "jäädytä",
"freezeLabel": "Jäädytä",
@ -543,18 +639,24 @@
"units": {
"BTC": "BTC",
"MAX": "MAX",
"sat_byte": "sat/bitti",
"sat_vbyte": "sat/tavu",
"sats": "sattia"
},
"addresses": {
"sign_title": "Allekirjoita/Varmenna viesti",
"sign_help": "Täällä voit luoda tai varmentaa kryptografisen allekirjoituksen Bitcoin-osoitteen perusteella ",
"sign_sign": "Allekirjoita",
"sign_sign_submit": "Allekirjoita ja toimita",
"sign_verify": "Varmenna",
"sign_signature_correct": "Varmennus onnistui!",
"sign_signature_incorrect": "Varmennus epäonnistui!",
"sign_placeholder_address": "Osoite",
"sign_placeholder_message": "Viesti",
"sign_placeholder_signature": "Allekirjoitus"
"sign_placeholder_signature": "Allekirjoitus",
"addresses_title": "Osoitteet",
"type_change": "muuta",
"type_receive": "vastaanota",
"type_used": "Käytetty",
"transactions": "tapahtumat"
}
}

View File

@ -641,17 +641,10 @@
"sign_placeholder_address": "Adresse",
"sign_placeholder_message": "Message",
"sign_placeholder_signature": "Signature",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Voulez vous envoyer un message signé a {hostname}?",
"addresses_title": "Adresses",
"type_change": "Monnaie",
"type_receive": "Réception",
"type_used": "Utilisé",
"transactions": "Transactions"
},
"aopp": {
"title": "Sélectionner l'adresse",
"send_success": "Signature envoyée avec succès",
"send_error": "Erreur lors de l'envoi de la signature"
}
}

View File

@ -637,16 +637,10 @@
"sign_placeholder_address": "כתובת",
"sign_placeholder_message": "הודעה",
"sign_placeholder_signature": "חתימה",
"sign_aopp_confirm": "האם ברצונך לשלוח הודעה חתומה אל {hostname}?",
"addresses_title": "כתובות",
"type_change": "עודף",
"type_receive": "קבלה",
"type_used": "שומש",
"transactions": "פעולות"
},
"aopp": {
"title": "בחירת כתובת",
"send_success": "חתימה נשלחה בהצלחה",
"send_error": "שגיאת שליחת חתימה"
}
}

View File

@ -18,7 +18,7 @@
"seed": "jelszó sorozat",
"success": "Sikeres",
"wallet_key": "Tárca kulcs",
"invalid_animated_qr_code_fragment": "Érvénytelen animált QR kód részlet, próbáld újra!",
"invalid_animated_qr_code_fragment" : "Érvénytelen animált QR kód részlet, próbáld újra!",
"file_saved": "{filePath} elmentve a kijelölt helyen: {destination}.",
"file_save_title": "Fájl Mentése",
"file_save_location": "Jelölje ki hova mentsen {filePath}",
@ -102,13 +102,13 @@
"p2p": "p2p átváltás"
},
"lnd": {
"active": "Aktív",
"inactive": "Inaktív",
"active":"Aktív",
"inactive":"Inaktív",
"channels": "Csatornák",
"no_channels": "Nincsenek csatornák",
"claim_balance": "Egyenleg lefoglalása {balance}",
"close_channel": "Csatorna zárása",
"new_channel": "Új csatorna",
"new_channel" : "Új csatorna",
"errorInvoiceExpired": "A számla lejárt",
"exchange": "Átváltás",
"force_close_channel": "Csatorna erőltetett zárása?",
@ -119,10 +119,14 @@
"payButton": "Fizess",
"placeholder": "Számla",
"open_channel": "Csatorna nyitása",
"opening_channnel_for_from": "Csatornanyitás a {forWalletLabel} tárca számára, {fromWalletLabel} által finanszírozva.",
"funding_amount_placeholder": "Feltöltési mennyiség, például 0.001",
"opening_channnel_for_from":"Csatornanyitás a {forWalletLabel} tárca számára, {fromWalletLabel} által finanszírozva.",
"are_you_sure_open_channel": "Biztosan meg akarja nyitni ezt a csatornát?",
"are_you_sure_exit_without_new_channel": "Biztosan ki akar lépni anélkül, hogy csatornát nyit?",
"public": "Nyilvános",
"public_description": "Látható a hálózaton: Lehet útválasztó node és díjakat tud felszámolni.",
"private": "Privát",
"private_description": "Láthatatlan a hálózaton: Megóvja az ön privát adatait amikor átutalásokat teljesít.",
"local_reserve": "Helyi tartalék",
"potentialFee": "Várható díj: {fee}",
"remote_host": "Távoli host",
@ -181,6 +185,7 @@
"header": "Fogadás"
},
"send": {
"provided_address_is_invoice": "Ez a cím Villám számlának tűnik. Kérem, mennyen be a Villám tárcájába és ott próbálkozzon ezen számla fizetésével.",
"broadcastButton": "Küldés",
"broadcastError": "hiba",
"broadcastNone": "Bejövő tranzakciós hash",
@ -206,6 +211,7 @@
"details_adv_fee_bump": "Kiváltás díjjal engedélyezve",
"details_adv_full": "Használd a teljes egyenleget",
"details_adv_full_sure": "Biztosan használni akarod a tárca teljes egyenlegét ehhez a tranzakcióhoz?",
"details_adv_full_sure_frozen": "Biztosan fel akarja használna a teljes egyenleget ehhez a tranzakcióhoz? Lefagyasztott érmék nem lesznek felhasználva.",
"details_adv_import": "Tranzakció importálása",
"details_adv_import_qr": "Tranzakció Importálása (QR)",
"details_amount_field_is_not_valid": "Érvénytelen összeg",
@ -213,12 +219,14 @@
"details_create": "Készíts számlát",
"details_error_decode": "Nem lehet dekódolni a bitcoin címet",
"details_fee_field_is_not_valid": "Èrvénytelen tranzakciós díj",
"details_frozen": "{amount} BTC fagyasztva áll",
"details_next": "Következő",
"details_no_signed_tx": "A kiválasztott fájl nem tartalmaz importálható tranzakciót.",
"details_note_placeholder": "saját megjegyzés",
"details_scan": "Szkennelés",
"details_scan_hint": "Dupla érintéssel szkennelhet, vagy betölthet uticélt",
"details_total_exceeds_balance": "A megadott összeg nagyobb, mint a tárca elérhető egyenlege",
"details_total_exceeds_balance_frozen": "A küldeni kívánt össze meghaladja az elérhető egyenlegét. Lefagyasztott érmék nem voltak használva.",
"details_unrecognized_file_format": "Nemismert fálj formátum",
"details_wallet_before_tx": "Tranzakció előtt, először adj meg egy Bitcoin tárcát.",
"dynamic_init": "Előkészítés",
@ -232,6 +240,8 @@
"fee_custom": "beállított",
"fee_fast": "Gyors",
"fee_medium": "Közepes",
"fee_replace_minvb": "A fizetendő teljes díj mértékének (satoshi per vbyte) magasabbnak kell lennie, mint {min} sat/vbyte.",
"fee_satvbyte": "sat/vByte-ban",
"fee_slow": "Lassú",
"header": "Küldés",
"input_clear": "Törlés",
@ -244,11 +254,13 @@
"open_settings": "Beállítások megnyitása",
"permission_storage_later": "Később",
"permission_storage_message": "A fájl elmentéséhez engedélyezned kell a BlueWallet hozzáférését a háttértárhoz.",
"permission_storage_denied_message": "BlueWallet nem képes elmenteni ezt a fájlt. Kérem nyissa meg a beállításokat és engedélyezze a tárhely hozzáférést az eszközén.",
"permission_storage_title": "Háttértár hozzáférés engedélyezés",
"psbt_clipboard": "Másolás vágólapra",
"psbt_this_is_psbt": "Ez egy részlegesen aláírt Bitcoin tranzakció (PSBT). Befejezheted a hardver tárcád aláírásával. ",
"psbt_tx_export": "Exportálás fájlba",
"no_tx_signing_in_progress": "Tranzakció aláírás nincs folyamatban",
"outdated_rate": "A ráta utoljára frissítve: {date}",
"psbt_tx_open": "Aláírt tranzakció megnyitása",
"psbt_tx_scan": "Aláírt tranzakció szkennelése",
"qr_error_no_qrcode": "Nem találtunk QR kódot a kiválasztott képen. Győződjön meg arról, hogy a kép csak QR kódot tartalmaz, és nem tartalmaz további tartalmat, például szöveget vagy gombokat.",
@ -282,6 +294,7 @@
"biom_remove_decrypt": "Minden pénztárcáját eltávolítjuk, és a tárolójáról visszafejtjük a titkosítást. Biztosan folytatja?",
"currency": "Valuta",
"currency_source": "Árak forrása",
"currency_fetch_error": "Hibatörtént a ráta lekérdezésekor a kijelölt fiat pénznél.",
"default_desc": "Ha le van tiltva, a BlueWallet azonnal megnyitja a kiválasztott tárcát indításkor. ",
"default_info": "Alapértelmezett információ",
"default_title": "Indításkor ",
@ -290,6 +303,8 @@
"electrum_connected_not": "Nincs kapcsolat",
"electrum_connnected_not_description": "A pénztárca importálásához aktív Electrum kapcsolat szükséges. A kapcsolat létrejöttét a Beállításokon belül a Hálózat menüpontban ellenőrizheti.",
"electrum_error_connect": "Nem tud csatlakozni a kiválasztott Electrum szerverhez",
"lndhub_uri": "P.l., {example}",
"electrum_host": "P.l., {example}",
"electrum_offline_mode": "Offline Mód",
"electrum_offline_description": "Ha engedélyezve van, a Bitcoin pénztárcájai nem kísérelnek meg egyenlegek vagy tranzakciók lekérdezésével.",
"electrum_port": "Port, álltalában {example}",
@ -340,7 +355,7 @@
"network_electrum": "Electrum szerver",
"not_a_valid_uri": "Nem megfelelő URI",
"notifications": "Megjegyzések",
"open_link_in_explorer": "Link megnyitása explorerben",
"open_link_in_explorer" : "Link megnyitása explorerben",
"password": "Jelszó",
"password_explain": "Add meg a jelszót, amivel majd dekódolhatod a tárhelyet",
"passwords_do_not_match": "A megadott jelszavak különböznek!",
@ -360,7 +375,7 @@
"selfTest": "Önteszt",
"save": "Ment",
"saved": "Elmentve",
"success_transaction_broadcasted": "Sikeres! A tranzakciója továbbítva!",
"success_transaction_broadcasted" : "Sikeres! A tranzakciója továbbítva!",
"total_balance": "Teljes egyenleg",
"total_balance_explanation": "Jelenítse meg az összes pénztárca egyenlegét a kezdőképernyő moduljain.",
"widgets": "Widgetek",
@ -386,7 +401,10 @@
"details_balance_show": "Egyenleg mutatása",
"details_block": "Blokkszámláló",
"details_copy": "Másolás",
"details_copy_amount": "Mennyiség Másolása",
"details_copy_block_explorer_link": "Blokk Böngésző Link Másolása",
"details_copy_note": "Megjegyzés Másolása",
"details_copy_txid": "Tranzakciós ID Másolása",
"details_from": "Bejövő utalás",
"details_inputs": "Bejövő utalások",
"details_outputs": "Kimenő utalások",
@ -405,6 +423,7 @@
"eta_3h": "ETA: ~3 órán belül",
"eta_1d": "ETA: ~1 napon belül",
"list_title": "tranzakciók",
"open_url_error": "Nem lehetett megnyitni a URL-t az alapértelmezett böngészővel. Kérem változtassa meg a böngészőjét és próbálkozzon meg újra.",
"rbf_explain": "Kiváltjuk ezt a tranzakciót egy magasabb tranzakciós díjjal járó tranzakcióval, így hamarabb teljesül. Ezt a megoldást Tranzakciós Díj Pótlásnak hívjuk, angolul RBF - Replace by Fee.",
"rbf_title": "Kiváltási díj (RBF)",
"status_bump": "Kiváltási díj",
@ -439,6 +458,7 @@
"details_are_you_sure": "Biztos vagy benne?",
"details_connected_to": "Kapcsolódva: ",
"details_del_wb_err": "A megadott egyenleg összege nem egyezik a tárca egyenlegével. Próbáld újra. ",
"details_del_wb_q": "Ennek a tárcának van egyenlege. Mielőtt tovább lép, tudnia kell, hogy nem fogja tudni vissza szerezni ezen összeget ha nem rendelkezik ezen tárca biztonsági szavaival. A véletlen eltávolítások elkerülése érdekéven kérem adja meg a tárcán található {balance} egyenleget satoshiban.",
"details_delete": "Törlés",
"details_delete_wallet": "Tárca törlése",
"details_derivation_path": "derivációs út",
@ -474,11 +494,13 @@
"import_search_accounts": "Fiókok keresése",
"import_title": "importálás",
"import_discovery_title": "Felfedezés",
"import_discovery_subtitle": "Már felfedezett tárca választása",
"import_discovery_derivation": "Egyedi derivációs útvonal használata",
"import_discovery_no_wallets": "Nem található tárca.",
"import_derivation_found": "megtalálva",
"import_derivation_found_not": "nem található",
"import_derivation_loading": "töltés...",
"import_derivation_subtitle": "Egyedi derivációs útvonal beírása és mi megpróbáljuk felfedezni a tárcáját",
"import_derivation_title": "Derivációs útvonal",
"import_derivation_unknown": "ismeretlen",
"import_wrong_path": "hibás derivációs útvonal",
@ -503,6 +525,7 @@
"no_ln_wallet_error": "Mielőtt tudnál fizetni a villámhálózaton, először egy Lightning tárcát kell létrehoznod vagy betöltened.",
"looks_like_bip38": "Ez egy jelszó védett privát kulcsnak (BIP38) tűnik",
"reorder_title": "Tárcák rendezése",
"reorder_instructions": "Érintse meg és tartsa lenyomva, hogy át húzzhassa a listán.",
"please_continue_scanning": "Kérem szkenneljen folyamatosan.",
"scan_error": "Szkennelési Hiba",
"select_no_bitcoin": "Jelenleg nincs elérhető Bitcoin tárca.",
@ -584,6 +607,7 @@
"ms_help_title1": "Több eszköz használata javasolt.",
"ms_help_1": "A Vault működőképes más BlueWallet applikációkkal és PSBT kompatibilis tárcákkal mint például az Electrum, Specter, Coldcard, KeystoneWallet, stb.",
"ms_help_title2": "Kulcsok szerkesztése",
"ms_help_2": "Az összes Vault-kulcsot létrehozhatja ezen az eszközön, majd később eltávolíthatja vagy szerkesztheti azokat. Ha minden kulcs ugyanazon az eszközön van, az egyenértékű egy hagyományos Bitcoin pénztárca biztonságával.",
"ms_help_title3": "Széf Biztonsági Másolat",
"ms_help_3": "A pénztárca beállításainál megtalálhatja a Vault biztonsági másolatát és a csak megtekintésre kész biztonsági másolatot. Ez a biztonsági mentés olyan, mint egy térkép a pénztárcájához. A biztonsági mentés elengedhetetlen a pénztárca helyreállításához.",
"ms_help_title4": "Széf Importálása",
@ -602,6 +626,7 @@
"cc": {
"change": "váltás",
"coins_selected": "Érmék kiválasztva ({number})",
"selected_summ": "{value} kijelölve",
"empty": "Ez a tárca jelenleg üres.",
"freeze": "zárolás",
"freezeLabel": "zárolás",
@ -628,16 +653,10 @@
"sign_placeholder_address": "Cím",
"sign_placeholder_message": "Üzenet",
"sign_placeholder_signature": "Szignatúra",
"sign_aopp_title": "AOPP",
"addresses_title": "Címek",
"type_change": "Váltópénz",
"type_receive": "Fogadás",
"type_used": "Használt",
"transactions": "Tranzakciók"
},
"aopp": {
"title": "Cím kiválasztása",
"send_success": "Szignatúra sikeresen elküldve",
"send_error": "Hiba a szignatúra küldésekor"
}
}

View File

@ -105,11 +105,14 @@
"inactive": "Inattivo",
"channels": "Canali",
"no_channels": "Nessun canale",
"claim_balance": "Richiedi il saldo {balance}",
"close_channel": "Chiudi il canale",
"new_channel": "Nuovo canale",
"errorInvoiceExpired": "Fattura scaduta",
"exchange": "Exchange",
"force_close_channel": "Forza la chiusura del canale?",
"expired": "Scaduto",
"node_alias": "Alias del nodo",
"expiredLow": "Scaduto",
"expiresIn": "Scade tra {time} minuti",
"payButton": "Paga",
@ -119,9 +122,11 @@
"opening_channnel_for_from": "Apri canale per il wallet {forWalletLabel}, caricando fondi da {fromWalletLabel}",
"are_you_sure_open_channel": "Sei sicuro di voler aprie questo canale?",
"are_you_sure_exit_without_new_channel": "Sei sicuro di voler uscire senza aprire un canale?",
"public": "Pubblico",
"public_description": "Visibile sulla rete: può essere un nodo di routing e guadagnare le commissioni.",
"private": "Privato",
"private_description": "Invisibile sulla rete: preserverà la privacy dei tuoi pagamenti.",
"local_reserve": "Risorse locali",
"potentialFee": "Commissioni potenziali: {fee}",
"remote_host": "Host remoto",
"refill": "Ricarica",
@ -133,7 +138,8 @@
"sameWalletAsInvoiceError": "Non puoi pagare una fattura con lo stesso portafoglio utilizzato per crearla.",
"title": "Gestisci fondi",
"can_send": "Puoi inviare",
"can_receive": "Puoi ricevere"
"can_receive": "Puoi ricevere",
"view_logs": "Visualizza i log"
},
"lndViewInvoice": {
"additional_info": "Ulteriori Informazioni",
@ -204,6 +210,7 @@
"details_adv_fee_bump": "Permetti l'aumento della commissione",
"details_adv_full": "Utilizza tutti i fondi",
"details_adv_full_sure": "Desideri veramente usare tutti i fondi in questo portafoglio per questa transazione?",
"details_adv_full_sure_frozen": "Sei sicuro di voler usare tutto il saldo del tuo wallet per questa transazione? Notare che il saldo congelato è escluso.",
"details_adv_import": "Importa Transazione",
"details_adv_import_qr": "Importa Transazione (QR)",
"details_amount_field_is_not_valid": "Importo non valido",
@ -211,12 +218,14 @@
"details_create": "Crea",
"details_error_decode": "Impossibile decodificare l'indirizzo Bitcoin",
"details_fee_field_is_not_valid": "Commissione non valida",
"details_frozen": "{amount} BTC sono congelati",
"details_next": "Avanti",
"details_no_signed_tx": "Il file selezionato non contiene una transazione che può essere importata.",
"details_note_placeholder": "Nota",
"details_scan": "Scansiona",
"details_scan_hint": "Tocca due volte per scannerizzare o importare una destinazione",
"details_total_exceeds_balance": "L'importo da inviare eccede i fondi disponibili.",
"details_total_exceeds_balance_frozen": "Il saldo che si vuole inviare è superiore al saldo disponibile. Notare che il saldo congelato è escluso.",
"details_unrecognized_file_format": "Formato sconosciuto",
"details_wallet_before_tx": "Prima di creare una transazione devi prima creare un portafoglio Bitcoin.",
"dynamic_init": "Avviamento",
@ -250,6 +259,7 @@
"psbt_this_is_psbt": "Questa è una Transazione Bitcoin Parzialmente Firmata (PSBT). Per favore termina di firmarla con il tuo portafoglio hardware.",
"psbt_tx_export": "Esporta in un file",
"no_tx_signing_in_progress": "Non c'è nessuna firma di transazione in corso.",
"outdated_rate": "La tariffa è stata aggiornata il: {data}",
"psbt_tx_open": "Apri una transazione firmata",
"psbt_tx_scan": "Scansiona una transazione firmata",
"qr_error_no_qrcode": "Non siamo stati in grado di trovare un QR Code nell'immagine selezionata. Assicurati che l'immagine contenga solo un QR Code e nessun altro contenuto in aggiunta, quale testo o pulsanti.",
@ -283,6 +293,7 @@
"biom_remove_decrypt": "Tutti i tuoi portafogli saranno rimossi e la memoria sarà decriptata. Sei sicuro di voler procedere?",
"currency": "Valuta",
"currency_source": "I prezzi sono ottenuti da",
"currency_fetch_error": "Errore durante la ricezione della tariffa per la valuta selezionata",
"default_desc": "Se disabilitato, BlueWallet aprirà immediatamente il portafoglio selezionato al lancio.",
"default_info": "Informazioni predefinite",
"default_title": "All'avvio",
@ -358,6 +369,7 @@
"privacy_do_not_track": "Disattiva Analytics",
"privacy_do_not_track_explanation": "Le informazioni circa la performance e l'affidabilità non saranno inviati per l'analisi.",
"push_notifications": "Notifiche Push",
"rate": "Tariffa",
"retype_password": "Reinserisci password",
"selfTest": "Auto-Test",
"save": "Salva",
@ -378,6 +390,7 @@
"cancel_no": "Questa transazione non può essere sostituita.",
"cancel_title": "Cancella questa transazione (RBF)",
"confirmations_lowercase": "{confirmations} conferme",
"copy_link": "Copia link",
"expand_note": "Espandi Nota",
"cpfp_create": "Crea",
"cpfp_exp": "Creeremo una nuova transazione che spende la tua transazione non ancora confermata. Le commissioni totali saranno più elevate rispetto alla transazione originale, quindi dovrebbe venir confermata pi?u rapidamente. Questa tecnica si chiama CPFP—Child Pays for Parent.",
@ -388,7 +401,9 @@
"details_block": "Altezza del blocco",
"details_copy": "Copia",
"details_copy_amount": "Copia importo",
"details_copy_block_explorer_link": "Copia link del Block Explorer",
"details_copy_note": "Copia Nota",
"details_copy_txid": "Copia ID di transazione",
"details_from": "Da",
"details_inputs": "Input",
"details_outputs": "Output",
@ -406,6 +421,7 @@
"eta_3h": "ETA: In ~3 ore",
"eta_1d": "ETA: In ~1 giorno",
"list_title": "Transazioni",
"open_url_error": "Impossibile aprire URL con il browser di default. È necessario cambiare il browser di default nelle impostazioni e riprovare.",
"rbf_explain": "Sostituiremo questa transazione con una con una commissione più elevata in modo che venga confermata più rapidamente. Questa tecnica è chiamata RBF—Replace by Fee.",
"rbf_title": "Aumenta la commissione (RBF)",
"status_bump": "Aumenta la commissione",
@ -423,19 +439,24 @@
"add_entropy_remain": "{gen} byte di entropia generata. I restanti {rem} byte saranno ottenuti da generatore di numeri casuali del sistema operativo.",
"add_import_wallet": "Importa Portafoglio",
"add_lightning": "Lightning",
"add_lightning_explain": "Per invio con transazioni istantanee",
"add_lndhub": "Connetti al tuo LNDHub",
"add_lndhub_error": "L'indirizzo fornito è un nodo LNDHub invalido.",
"add_lndhub_placeholder": "L'indirizzo del tuo nodo",
"add_or": "o",
"add_placeholder": "Il mio primo wallet",
"add_title": "Aggiungi Portafoglio",
"add_wallet_name": "Nome Portafoglio",
"add_wallet_type": "Tipo",
"balance": "Saldo",
"clipboard_bitcoin": "Negli appunti è presente un indirizzo Bitcoin. Desideri usarlo per una transazione?",
"clipboard_lightning": "Negli appunti è presente una fattura Lightning. Desideri usarla per una transazione?",
"details_address": "Indirizzo",
"details_advanced": "Avanzato",
"details_are_you_sure": "Sei sicuro?",
"details_connected_to": "Connesso a",
"details_del_wb_err": "Il saldo fornito non coincide con il saldo di questo wallet. Si prega di riprovare.",
"details_del_wb_q": "Attenzione: questo wallet non è vuoto, non sarà possibile recuperare i fondi senza la seed phrase del wallet. Per evitare la rimozione accidentale, si prega di inserire il saldo del wallet {balance} satoshi.",
"details_delete": "Elimina",
"details_delete_wallet": "Rimuovi portafoglio",
"details_derivation_path": "derivation path",

View File

@ -491,10 +491,5 @@
"addresses_title": "アドレス",
"type_change": "チェンジ",
"type_receive": "受取り"
},
"aopp": {
"title": "アドレス選択",
"send_success": "署名は正常に送信されました",
"send_error": "署名送信エラー"
}
}

View File

@ -648,17 +648,10 @@
"sign_placeholder_address": "주소",
"sign_placeholder_message": "메시지",
"sign_placeholder_signature": "서명",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "서명된 메시지를 {hostname}으로 보내겠습니까?",
"addresses_title": "주소",
"type_change": "변경",
"type_receive": "받기",
"type_used": "사용됨",
"transactions": "트랜잭션"
},
"aopp": {
"title": "주소 선택",
"send_success": "서명 전송이 성공적으로 이루어졌습니다. ",
"send_error": "서명 보내기 에러"
}
}

View File

@ -618,17 +618,10 @@
"sign_placeholder_address": "Alamat",
"sign_placeholder_message": "Pesanan",
"sign_placeholder_signature": "Tandatangan",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Adakah anda mahu menghantar pesanan bertanda tangan kepada {hostname}?",
"addresses_title": "Alamat",
"type_change": "Ubah",
"type_receive": "Terima",
"type_used": "Digunakan",
"transactions": "Urus Niaga"
},
"aopp": {
"title": "Pilih Alamat",
"send_success": "Tandatangan berjaya dihantar",
"send_error": "Ralat Penghantaran Tandatangan"
}
}

View File

@ -651,17 +651,10 @@
"sign_placeholder_address": "Adres",
"sign_placeholder_message": "Bericht",
"sign_placeholder_signature": "Ondertekening",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Wil je een ondertekende boodschap sturen naar {hostname}",
"addresses_title": "Adressen",
"type_change": "Wisselgeld",
"type_receive": "Ontvang",
"type_used": "Gebruikt",
"transactions": "Transacties"
},
"aopp": {
"title": "Selecteer adres",
"send_success": "Ondertekening succesvol verstuurd",
"send_error": "Fout bij versturen van Ondertekening"
}
}

View File

@ -28,7 +28,7 @@
"discard_changes_detail": "Masz niezapisane zmiany. Czy jesteś pewien, że chcesz je odrzucić i opuścić ten ekran?"
},
"alert": {
"default": "Uwaga"
"default": "Powiadomienie"
},
"azteco": {
"codeIs": "Twój kod vouchera to",
@ -173,7 +173,7 @@
"ok": "OK, zapisałem",
"ok_lnd": "OK, zapisałem ",
"text": "Poświęć chwilę by zapisać tę frazę mnemoniczną na kartce papieru\nTo Twoja kopia zapasowa, której możesz użyć później by odtworzyć portfel.",
"text_lnd": "Proszę, poświęć chwilę, żeby zapisać to uwierzytelnienie LNDHub. To twoja kopia zapasowa, możesz użyć jej, aby odtworzyć portfel na innym urządzeniu.",
"text_lnd": "Zachowaj tę kopię zapasową portfela. Umożliwi Ci odtworzenie portfela w przypadku utraty.",
"text_lnd2": "Ten portfel jest obsługiwany przez BlueWallet.",
"title": "Twój portfel został utworzony"
},
@ -295,8 +295,8 @@
"currency": "Waluta",
"currency_source": "Kurs jest pozyskiwany z",
"currency_fetch_error": "Wystąpił błąd podczas pobierania kursu dla wybranej waluty.",
"default_desc": "Po uruchomieniu BlueWallet natychmiast otworzy wcześniej wybrany domyślny portfel.",
"default_info": "Informacje domyślne",
"default_desc": "Gdy jest wyłączone, BlueWallet natychmiast otworzy wybrany domyślny portfel.",
"default_info": "Domyślny portfel",
"default_title": "Po uruchomieniu",
"default_wallets": "Wyświetl wszystkie portfele",
"electrum_connected": "Połączony",
@ -340,7 +340,7 @@
"general_adv_mode_e": "Gdy włączone, zobaczysz zaawansowane ustawienia takie jak np. różne typy portfeli, zdolność do określenia instancji LNDHub, z którą chcesz się połączyć oraz niestandardowej entropii w trakcie tworzenia portfela.",
"general_continuity": "Funkcja Continuity",
"general_continuity_e": "Gdy włączone, będziesz miał podgląd do wybranych portfeli i transakcji przy użyciu swoich urządzeń zalogowanych do Apple iCloud. ",
"groundcontrol_explanation": "GroundControl jest darmową opcją serwera powiadamień push dla portfeli bitcoin. Możesz zainstalować swój własny serwer GroundControl i podać jego URL tutaj, tak aby nie polegać na infrastrukturze BlueWallet. Zostaw puste by użyć domyślnej wartości.",
"groundcontrol_explanation": "GroundControl jest darmowym, open source'owym serwerem powiadomień push dla portfeli bitcoin. Możesz zainstalować swój własny serwer GroundControl i podać jego URL tutaj aby nie polegać na infrastrukturze BlueWallet. Zostaw puste by użyć domyślnej wartości.",
"header": "Ustawienia",
"language": "Język",
"last_updated": "Ostatnia aktualizacja",
@ -370,7 +370,7 @@
"privacy_do_not_track": "Wyłącz analitykę",
"privacy_do_not_track_explanation": "Informacje dotyczące wydajności i niezawodności nie będą przesyłane do analizy.",
"push_notifications": "Powiadomienia Push",
"rate": "Stawka",
"rate": "Kurs",
"retype_password": "Wprowadź Ponownie hasło",
"selfTest": "Autotest",
"save": "Zapisz",
@ -525,6 +525,7 @@
"no_ln_wallet_error": "Musisz najpierw dodać portfel Lightning, zanim zapłacisz fakturę.",
"looks_like_bip38": "To wygląda na klucz prywatny chroniony hasłem (BIP38).",
"reorder_title": "Zmień kolejność portfeli",
"reorder_instructions": "Stuknij i przytrzmaj portfel aby go przeciągnąć na liście.",
"please_continue_scanning": "Proszę skanuj dalej.",
"scan_error": "Błąd skanowania",
"select_no_bitcoin": "Nie ma dostępnych portfeli Bitcoin.",
@ -625,6 +626,7 @@
"cc": {
"change": "Reszta",
"coins_selected": "Wybrano monet ({number})",
"selected_summ": "{value} wybrano",
"empty": "Ten portfel nie ma żadnych monet w tej chwili.",
"freeze": "Zamrożona",
"freezeLabel": "Zamroź",
@ -651,17 +653,26 @@
"sign_placeholder_address": "Adres",
"sign_placeholder_message": "Wiadomość",
"sign_placeholder_signature": "Podpis",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Czy chcesz przesłać podpisaną wiadomość do {hostname}?",
"addresses_title": "Adresy",
"type_change": "Reszta",
"type_receive": "Otrzymaj",
"type_used": "Używany",
"transactions": "Transakcje"
},
"aopp": {
"title": "Wybierz adres",
"send_success": "Podpis wysłany z powodzeniem",
"send_error": "Błąd wysyłania podpisu"
"lnurl_auth": {
"register_question_part_1": "Czy chcesz zarejestrować konto w ",
"register_question_part_2": "używając Twojego portfela Lightning Network?",
"register_answer": "Konto w {hostname} zarejestrowane pomyślnie!",
"login_question_part_1": "Czy chcesz się zalogować w ",
"login_question_part_2": "używając Twojego portfela Lightning Network?",
"login_answer": "Zalogowano pomyślnie w {hostname}!",
"link_question_part_1": "Połączyć Twoje konto w ",
"link_question_part_2": "z portfelem Lightning Network?",
"link_answer": "Konto w {hostname} pomyślnie połączone z Twoim portfelem Lightning Network!",
"auth_question_part_1": "Czy chcesz się uwierzytelnić w ",
"auth_question_part_2": "używając Twojego portfela Lightning Network?",
"auth_answer": "Uwierzytelnienie z {hostname} pomyślne!",
"could_not_auth": "Nie można uwierzytelnić z {hostname}.",
"authenticate": "Uwierzytelnianie"
}
}

View File

@ -651,17 +651,10 @@
"sign_placeholder_address": "Endereço",
"sign_placeholder_message": "Mensagem",
"sign_placeholder_signature": "Assinatura",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Deseja enviar uma mensagem assinada para {hostname}?",
"addresses_title": "Endereços",
"type_change": "Troco",
"type_receive": "Receber",
"type_used": "Usado",
"transactions": "Transações"
},
"aopp": {
"title": "Selecionar endereço",
"send_success": "Assinatura enviada com sucesso",
"send_error": "Erro no envio da assinatura"
}
}

View File

@ -651,17 +651,10 @@
"sign_placeholder_address": "Адрес",
"sign_placeholder_message": "Сообщение",
"sign_placeholder_signature": "Подпись",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Отправить подписанное сообщение на {hostname}?",
"addresses_title": "Адреса",
"type_change": "Сдача",
"type_receive": "Получение",
"type_used": "Использован",
"transactions": "Транзакции"
},
"aopp": {
"title": "Выберите адрес",
"send_success": "Подпись успешно отправлена",
"send_error": "Ошибка отправки подписи"
}
}

View File

@ -648,17 +648,10 @@
"sign_placeholder_address": "ලිපිනය",
"sign_placeholder_message": "පණිවිඩය",
"sign_placeholder_signature": "අත්සන",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "ඔබට {hostname} වෙත අත්සන් කළ පණිවිඩයක් යැවීමට අවශ්‍යද?",
"addresses_title": "ලිපිනයන්",
"type_change": "වෙනස් කරන්න",
"type_receive": "පිළිගන්න",
"type_used": "භාවිතා කර ඇත",
"transactions": "ගනුදෙනු"
},
"aopp": {
"title": "ලිපිනය තෝරන්න",
"send_success": "අත්සන සාර්ථකව යවන ලදි",
"send_error": "අත්සන යැවීමේ දෝෂයකි"
}
}

View File

@ -642,17 +642,10 @@
"sign_placeholder_address": "Naslov",
"sign_placeholder_message": "Sporočilo",
"sign_placeholder_signature": "Podpis",
"sign_aopp_title": "AOPP",
"sign_aopp_confirm": "Ali želite podpisano sporočilo poslati na {hostname}?",
"addresses_title": "Naslovi",
"type_change": "Vračilo",
"type_receive": "Prejemni",
"type_used": "Uporabljen",
"transactions": "Transakcije"
},
"aopp": {
"title": "Izberite Naslov",
"send_success": "Podpis uspešno poslan",
"send_error": "Napaka pri pošiljanju podpisa"
}
}

View File

@ -405,16 +405,10 @@
"sign_placeholder_address": "Адреса",
"sign_placeholder_message": "Повідомлення",
"sign_placeholder_signature": "Підпис",
"sign_aopp_confirm": "Ви хочете надіслати підписане повідомлення на адресу {hostname}?",
"addresses_title": "Адреси",
"type_change": "Здача",
"type_receive": "Отримати",
"type_used": "Використаний",
"transactions": "Транзакцій"
},
"aopp": {
"title": "Виберіть Адреси",
"send_success": "Підпис успішно надіслано",
"send_error": "Помилка надсилання підпису"
}
}

View File

@ -554,8 +554,5 @@
"addresses_title": "地址",
"type_change": "改变",
"type_receive": "接收"
},
"aopp": {
"title": "选择地址"
}
}

View File

@ -554,8 +554,5 @@
"addresses_title": "地址",
"type_change": "改變",
"type_receive": "接收"
},
"aopp": {
"title": "選擇地址"
}
}

View File

@ -14,7 +14,7 @@ const RateExtractors = {
try {
const res = await fetch(`https://api.coindesk.com/v1/bpi/currentprice/${ticker}.json`);
json = await res.json();
} catch (e) {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.bpi?.[ticker]?.rate_float; // eslint-disable-line
@ -30,7 +30,7 @@ const RateExtractors = {
try {
const res = await fetch(`https://api.yadio.io/json/${ticker}`);
json = await res.json();
} catch (e) {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.[ticker]?.price;
@ -46,7 +46,7 @@ const RateExtractors = {
try {
const res = await fetch('https://bitcoinduliban.org/api.php?key=lbpusd');
json = await res.json();
} catch (e) {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.[`BTC/${ticker}`];
@ -62,7 +62,7 @@ const RateExtractors = {
try {
const res = await fetch('https://api.exir.io/v1/ticker?symbol=btc-irt');
json = await res.json();
} catch (e) {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.last;
@ -78,7 +78,7 @@ const RateExtractors = {
try {
const res = await fetch(`https://api.wazirx.com/api/v2/tickers/btcinr`);
json = await res.json();
} catch (e) {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.ticker?.buy; // eslint-disable-line

40526
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "bluewallet",
"version": "6.2.17",
"version": "6.2.19",
"license": "MIT",
"repository": {
"type": "git",
@ -15,7 +15,7 @@
"@types/create-hash": "^1.2.2",
"@types/jest": "^26.0.24",
"@types/react": "^17.0.14",
"@types/react-native": "^0.64.12",
"@types/react-native": "^0.66.15",
"@types/react-test-renderer": "^17.0.1",
"@typescript-eslint/eslint-plugin": "^4.28.3",
"@typescript-eslint/parser": "^4.28.3",
@ -37,7 +37,7 @@
"jest": "^26.1.0",
"node-fetch": "^2.6.2",
"prettier": "^2.2.1",
"react-test-renderer": "17.0.1",
"react-test-renderer": "17.0.2",
"typescript": "^4.3.5"
},
"engines": {
@ -96,12 +96,12 @@
]
},
"dependencies": {
"@babel/preset-env": "7.16.8",
"@bugsnag/react-native": "7.15.1",
"@bugsnag/source-maps": "2.3.0",
"@babel/preset-env": "7.16.11",
"@bugsnag/react-native": "7.16.1",
"@bugsnag/source-maps": "2.3.1",
"@keystonehq/bc-ur-registry": "0.4.4",
"@ngraveio/bc-ur": "1.1.6",
"@react-native-async-storage/async-storage": "1.15.15",
"@react-native-async-storage/async-storage": "1.16.1",
"@react-native-clipboard/clipboard": "1.9.0",
"@react-native-community/push-notification-ios": "1.10.1",
"@react-navigation/drawer": "5.12.5",
@ -125,7 +125,7 @@
"coinselect": "3.1.12",
"crypto-js": "4.1.1",
"dayjs": "1.10.7",
"detox": "19.4.2",
"detox": "19.4.4",
"ecpair": "2.0.1",
"ecurve": "1.0.6",
"electrum-client": "https://github.com/BlueWallet/rn-electrum-client#99ebcc649d91a8dc39bea7964b02dd9ead464aa4",
@ -133,36 +133,36 @@
"events": "3.3.0",
"frisbee": "3.1.4",
"junderw-crc32c": "1.2.0",
"lottie-ios": "3.1.9",
"lottie-react-native": "4.0.2",
"metro-react-native-babel-preset": "0.66.2",
"lottie-ios": "3.2.3",
"lottie-react-native": "5.0.1",
"metro-react-native-babel-preset": "0.68.0",
"path-browserify": "1.0.1",
"payjoin-client": "1.0.1",
"process": "0.11.10",
"prop-types": "15.8.1",
"react": "17.0.1",
"react": "17.0.2",
"react-localization": "1.0.17",
"react-native": "0.64.2",
"react-native": "0.67.2",
"react-native-blue-crypto": "https://github.com/BlueWallet/react-native-blue-crypto#fbc2e6beded0b7f61e0986ce98cca1230f84bc1c",
"react-native-camera": "4.2.1",
"react-native-crypto": "2.2.0",
"react-native-default-preference": "1.4.3",
"react-native-device-info": "8.4.8",
"react-native-device-info": "8.4.9",
"react-native-document-picker": "https://github.com/BlueWallet/react-native-document-picker#c52e7a6d2a08f5506c23de86c1401775419f772c",
"react-native-elements": "3.4.2",
"react-native-fingerprint-scanner": "https://github.com/BlueWallet/react-native-fingerprint-scanner#ce644673681716335d786727bab998f7e632ab5e",
"react-native-fs": "2.18.0",
"react-native-gesture-handler": "1.10.3",
"react-native-gesture-handler": "2.2.0",
"react-native-handoff": "https://github.com/BlueWallet/react-native-handoff#31d005f93d31099d0e564590a3bbd052b8a02b39",
"react-native-haptic-feedback": "1.13.0",
"react-native-idle-timer": "https://github.com/BlueWallet/react-native-idle-timer#8587876d68ab5920e79619726aeca9e672beaf2b",
"react-native-image-picker": "4.7.1",
"react-native-image-picker": "4.7.3",
"react-native-ios-context-menu": "https://github.com/BlueWallet/react-native-ios-context-menu.git#v1.3.0",
"react-native-keychain": "8.0.0",
"react-native-level-fs": "3.0.1",
"react-native-linear-gradient": "2.5.6",
"react-native-localize": "2.1.7",
"react-native-modal": "12.1.0",
"react-native-localize": "2.1.9",
"react-native-modal": "13.0.0",
"react-native-navigation-bar-color": "https://github.com/BlueWallet/react-native-navigation-bar-color#3b2894ae62fbce99a3bd24105f0921cebaef5c94",
"react-native-obscure": "https://github.com/BlueWallet/react-native-obscure.git#f4b83b4a261e39b1f5ed4a45ac5bcabc8a59eadb",
"react-native-passcode-auth": "https://github.com/BlueWallet/react-native-passcode-auth#a2ff977ba92b36f8d0a5567f59c05cc608e8bd12",
@ -175,21 +175,20 @@
"react-native-rate": "1.2.9",
"react-native-reanimated": "2.2.4",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "3.10.2",
"react-native-screens": "3.11.0",
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#63ab38c9d382a819844a086a69cc204c46aa93f9",
"react-native-share": "7.3.3",
"react-native-sortable-list": "https://github.com/BlueWallet/react-native-sortable-list.git#e4e44a01a90ee2dcb9c57182262595abf36bfdf7",
"react-native-share": "7.3.5",
"react-native-svg": "12.1.1",
"react-native-tcp-socket": "5.5.0",
"react-native-tor": "0.1.7",
"react-native-vector-icons": "9.0.0",
"react-native-tor": "0.1.8",
"react-native-vector-icons": "9.1.0",
"react-native-watch-connectivity": "1.0.4",
"react-native-webview": "11.16.0",
"react-native-webview": "11.17.2",
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#b1382bbe1ed631b50a8aa03390f64c50775bc9ff",
"react-native-windows": "0.64.14",
"react-native-windows": "0.67.1",
"react-test-render": "1.1.2",
"readable-stream": "3.6.0",
"realm": "10.11.0",
"realm": "10.13.0",
"rn-ldk": "git+https://github.com/BlueWallet/rn-ldk.git#v0.6.4",
"rn-nodeify": "10.3.0",
"scryptsy": "2.1.0",

Some files were not shown because too many files have changed in this diff Show More