mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-23 23:27:26 +01:00
Merge branch 'master' into electrumpref
This commit is contained in:
commit
2dc3efd391
13 changed files with 372 additions and 239 deletions
218
components/CameraScreen.tsx
Normal file
218
components/CameraScreen.tsx
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import { Animated, ImageURISource, SafeAreaView, StatusBar, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { Camera, CameraApi, CameraType, Orientation } from 'react-native-camera-kit';
|
||||||
|
import loc from '../loc';
|
||||||
|
import { Icon } from '@rneui/base';
|
||||||
|
|
||||||
|
interface CameraScreenProps {
|
||||||
|
onCancelButtonPress: () => void;
|
||||||
|
showImagePickerButton?: boolean;
|
||||||
|
showFilePickerButton?: boolean;
|
||||||
|
onImagePickerButtonPress?: () => void;
|
||||||
|
onFilePickerButtonPress?: () => void;
|
||||||
|
torchOnImage?: ImageURISource;
|
||||||
|
torchOffImage?: ImageURISource;
|
||||||
|
onReadCode?: (event: any) => void;
|
||||||
|
cameraFlipImage?: ImageURISource;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CameraScreen: React.FC<CameraScreenProps> = ({
|
||||||
|
onCancelButtonPress,
|
||||||
|
showImagePickerButton,
|
||||||
|
showFilePickerButton,
|
||||||
|
onImagePickerButtonPress,
|
||||||
|
onFilePickerButtonPress,
|
||||||
|
torchOnImage,
|
||||||
|
torchOffImage,
|
||||||
|
onReadCode,
|
||||||
|
cameraFlipImage,
|
||||||
|
}) => {
|
||||||
|
const cameraRef = useRef<CameraApi>(null);
|
||||||
|
const [torchMode, setTorchMode] = useState(false);
|
||||||
|
const [cameraType, setCameraType] = useState(CameraType.Back);
|
||||||
|
const [zoom, setZoom] = useState<number | undefined>();
|
||||||
|
const [orientationAnim] = useState(new Animated.Value(3));
|
||||||
|
|
||||||
|
const onSwitchCameraPressed = () => {
|
||||||
|
const direction = cameraType === CameraType.Back ? CameraType.Front : CameraType.Back;
|
||||||
|
setCameraType(direction);
|
||||||
|
setZoom(1); // When changing camera type, reset to default zoom for that camera
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSetTorch = () => {
|
||||||
|
setTorchMode(!torchMode);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Counter-rotate the icons to indicate the actual orientation of the captured photo.
|
||||||
|
// For this example, it'll behave incorrectly since UI orientation is allowed (and already-counter rotates the entire screen)
|
||||||
|
// For real phone apps, lock your UI orientation using a library like 'react-native-orientation-locker'
|
||||||
|
const rotateUi = true;
|
||||||
|
const uiRotation = orientationAnim.interpolate({
|
||||||
|
inputRange: [1, 4],
|
||||||
|
outputRange: ['180deg', '-90deg'],
|
||||||
|
});
|
||||||
|
const uiRotationStyle = rotateUi ? { transform: [{ rotate: uiRotation }] } : undefined;
|
||||||
|
|
||||||
|
function rotateUiTo(rotationValue: number) {
|
||||||
|
Animated.timing(orientationAnim, {
|
||||||
|
toValue: rotationValue,
|
||||||
|
useNativeDriver: true,
|
||||||
|
duration: 200,
|
||||||
|
isInteraction: false,
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.screen}>
|
||||||
|
<StatusBar hidden />
|
||||||
|
<SafeAreaView style={styles.topButtons}>
|
||||||
|
<TouchableOpacity style={styles.topButton} onPress={onSetTorch}>
|
||||||
|
<Animated.Image
|
||||||
|
source={torchMode ? torchOnImage : torchOffImage}
|
||||||
|
resizeMode="contain"
|
||||||
|
style={[styles.topButtonImg, uiRotationStyle]}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={styles.rightButtonsContainer}>
|
||||||
|
{showImagePickerButton && (
|
||||||
|
<TouchableOpacity
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={loc._.pick_image}
|
||||||
|
style={[styles.topButton, styles.spacing, uiRotationStyle]}
|
||||||
|
onPress={onImagePickerButtonPress}
|
||||||
|
>
|
||||||
|
<Icon name="image" type="font-awesome" color="#ffffff" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
{showFilePickerButton && (
|
||||||
|
<TouchableOpacity
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={loc._.pick_file}
|
||||||
|
style={[styles.topButton, styles.spacing, uiRotationStyle]}
|
||||||
|
onPress={onFilePickerButtonPress}
|
||||||
|
>
|
||||||
|
<Icon name="file-import" type="font-awesome-5" color="#ffffff" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
|
||||||
|
<View style={styles.cameraContainer}>
|
||||||
|
<Camera
|
||||||
|
ref={cameraRef}
|
||||||
|
style={styles.cameraPreview}
|
||||||
|
cameraType={cameraType}
|
||||||
|
resetFocusWhenMotionDetected
|
||||||
|
zoom={zoom}
|
||||||
|
maxZoom={10}
|
||||||
|
onZoom={e => {
|
||||||
|
console.debug('zoom', e.nativeEvent.zoom);
|
||||||
|
setZoom(e.nativeEvent.zoom);
|
||||||
|
}}
|
||||||
|
onReadCode={onReadCode}
|
||||||
|
torchMode={torchMode ? 'on' : 'off'}
|
||||||
|
shutterPhotoSound
|
||||||
|
maxPhotoQualityPrioritization="quality"
|
||||||
|
onOrientationChange={e => {
|
||||||
|
// We recommend locking the camera UI to portrait (using a different library)
|
||||||
|
// and rotating the UI elements counter to the orientation
|
||||||
|
// However, we include onOrientationChange so you can match your UI to what the camera does
|
||||||
|
switch (e.nativeEvent.orientation) {
|
||||||
|
case Orientation.PORTRAIT_UPSIDE_DOWN:
|
||||||
|
console.debug('orientationChange', 'PORTRAIT_UPSIDE_DOWN');
|
||||||
|
rotateUiTo(1);
|
||||||
|
break;
|
||||||
|
case Orientation.LANDSCAPE_LEFT:
|
||||||
|
console.debug('orientationChange', 'LANDSCAPE_LEFT');
|
||||||
|
rotateUiTo(2);
|
||||||
|
break;
|
||||||
|
case Orientation.PORTRAIT:
|
||||||
|
console.debug('orientationChange', 'PORTRAIT');
|
||||||
|
rotateUiTo(3);
|
||||||
|
break;
|
||||||
|
case Orientation.LANDSCAPE_RIGHT:
|
||||||
|
console.debug('orientationChange', 'LANDSCAPE_RIGHT');
|
||||||
|
rotateUiTo(4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.debug('orientationChange', e.nativeEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<SafeAreaView style={styles.bottomButtons}>
|
||||||
|
<TouchableOpacity onPress={onCancelButtonPress}>
|
||||||
|
<Animated.Text style={[styles.backTextStyle, uiRotationStyle]}>{loc._.cancel}</Animated.Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity style={styles.bottomButton} onPress={onSwitchCameraPressed}>
|
||||||
|
<Animated.Image source={cameraFlipImage as ImageURISource} resizeMode="contain" style={[styles.topButtonImg, uiRotationStyle]} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</SafeAreaView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CameraScreen;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
screen: {
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: '#000000',
|
||||||
|
},
|
||||||
|
topButtons: {
|
||||||
|
margin: 10,
|
||||||
|
zIndex: 10,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
topButton: {
|
||||||
|
backgroundColor: '#222',
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
borderRadius: 22,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
topButtonImg: {
|
||||||
|
margin: 10,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
},
|
||||||
|
cameraContainer: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
cameraPreview: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
bottomButtons: {
|
||||||
|
margin: 10,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
backTextStyle: {
|
||||||
|
padding: 10,
|
||||||
|
color: 'white',
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
rightButtonsContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
bottomButton: {
|
||||||
|
backgroundColor: '#222',
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
borderRadius: 22,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginLeft: 10,
|
||||||
|
},
|
||||||
|
spacing: {
|
||||||
|
marginLeft: 20,
|
||||||
|
},
|
||||||
|
});
|
|
@ -6,6 +6,7 @@ import { WalletCarouselItem } from './WalletsCarousel';
|
||||||
import { TransactionListItem } from './TransactionListItem';
|
import { TransactionListItem } from './TransactionListItem';
|
||||||
import { useTheme } from './themes';
|
import { useTheme } from './themes';
|
||||||
import { BitcoinUnit } from '../models/bitcoinUnits';
|
import { BitcoinUnit } from '../models/bitcoinUnits';
|
||||||
|
import { TouchableOpacityWrapper } from './ListItem';
|
||||||
|
|
||||||
enum ItemType {
|
enum ItemType {
|
||||||
WalletSection = 'wallet',
|
WalletSection = 'wallet',
|
||||||
|
@ -29,11 +30,14 @@ interface ManageWalletsListItemProps {
|
||||||
isDraggingDisabled: boolean;
|
isDraggingDisabled: boolean;
|
||||||
drag?: () => void;
|
drag?: () => void;
|
||||||
isPlaceHolder?: boolean;
|
isPlaceHolder?: boolean;
|
||||||
|
onPressIn?: () => void;
|
||||||
|
onPressOut?: () => void;
|
||||||
state: { wallets: TWallet[]; searchQuery: string };
|
state: { wallets: TWallet[]; searchQuery: string };
|
||||||
navigateToWallet: (wallet: TWallet) => void;
|
navigateToWallet: (wallet: TWallet) => void;
|
||||||
renderHighlightedText: (text: string, query: string) => JSX.Element;
|
renderHighlightedText: (text: string, query: string) => JSX.Element;
|
||||||
handleDeleteWallet: (wallet: TWallet) => void;
|
handleDeleteWallet: (wallet: TWallet) => void;
|
||||||
handleToggleHideBalance: (wallet: TWallet) => void;
|
handleToggleHideBalance: (wallet: TWallet) => void;
|
||||||
|
isActive?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SwipeContentProps {
|
interface SwipeContentProps {
|
||||||
|
@ -67,6 +71,9 @@ const ManageWalletsListItem: React.FC<ManageWalletsListItemProps> = ({
|
||||||
renderHighlightedText,
|
renderHighlightedText,
|
||||||
handleDeleteWallet,
|
handleDeleteWallet,
|
||||||
handleToggleHideBalance,
|
handleToggleHideBalance,
|
||||||
|
onPressIn,
|
||||||
|
onPressOut,
|
||||||
|
isActive,
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
|
@ -110,6 +117,10 @@ const ManageWalletsListItem: React.FC<ManageWalletsListItemProps> = ({
|
||||||
containerStyle={{ backgroundColor: colors.background }}
|
containerStyle={{ backgroundColor: colors.background }}
|
||||||
leftContent={leftContent}
|
leftContent={leftContent}
|
||||||
rightContent={rightContent}
|
rightContent={rightContent}
|
||||||
|
Component={TouchableOpacityWrapper}
|
||||||
|
onPressOut={onPressOut}
|
||||||
|
onPressIn={onPressIn}
|
||||||
|
style={isActive ? styles.activeItem : undefined}
|
||||||
>
|
>
|
||||||
<ListItem.Content
|
<ListItem.Content
|
||||||
style={{
|
style={{
|
||||||
|
@ -121,6 +132,8 @@ const ManageWalletsListItem: React.FC<ManageWalletsListItemProps> = ({
|
||||||
item={item.data}
|
item={item.data}
|
||||||
handleLongPress={isDraggingDisabled ? undefined : drag}
|
handleLongPress={isDraggingDisabled ? undefined : drag}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
|
onPressIn={onPressIn}
|
||||||
|
onPressOut={onPressOut}
|
||||||
animationsEnabled={false}
|
animationsEnabled={false}
|
||||||
searchQuery={state.searchQuery}
|
searchQuery={state.searchQuery}
|
||||||
isPlaceHolder={isPlaceHolder}
|
isPlaceHolder={isPlaceHolder}
|
||||||
|
@ -164,6 +177,9 @@ const styles = StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: 'red',
|
backgroundColor: 'red',
|
||||||
},
|
},
|
||||||
|
activeItem: {
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export { ManageWalletsListItem, LeftSwipeContent, RightSwipeContent };
|
export { ManageWalletsListItem, LeftSwipeContent, RightSwipeContent };
|
||||||
|
|
|
@ -172,6 +172,8 @@ interface WalletCarouselItemProps {
|
||||||
searchQuery?: string;
|
searchQuery?: string;
|
||||||
renderHighlightedText?: (text: string, query: string) => JSX.Element;
|
renderHighlightedText?: (text: string, query: string) => JSX.Element;
|
||||||
animationsEnabled?: boolean;
|
animationsEnabled?: boolean;
|
||||||
|
onPressIn?: () => void;
|
||||||
|
onPressOut?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
||||||
|
@ -186,6 +188,8 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
||||||
renderHighlightedText,
|
renderHighlightedText,
|
||||||
animationsEnabled = true,
|
animationsEnabled = true,
|
||||||
isPlaceHolder = false,
|
isPlaceHolder = false,
|
||||||
|
onPressIn,
|
||||||
|
onPressOut,
|
||||||
}) => {
|
}) => {
|
||||||
const scaleValue = useRef(new Animated.Value(1.0)).current;
|
const scaleValue = useRef(new Animated.Value(1.0)).current;
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
@ -203,7 +207,8 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
||||||
tension: 100,
|
tension: 100,
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
}, [scaleValue, animationsEnabled]);
|
if (onPressIn) onPressIn();
|
||||||
|
}, [scaleValue, animationsEnabled, onPressIn]);
|
||||||
|
|
||||||
const onPressedOut = useCallback(() => {
|
const onPressedOut = useCallback(() => {
|
||||||
if (animationsEnabled) {
|
if (animationsEnabled) {
|
||||||
|
@ -214,7 +219,8 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
||||||
tension: 100,
|
tension: 100,
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
}, [scaleValue, animationsEnabled]);
|
if (onPressOut) onPressOut();
|
||||||
|
}, [scaleValue, animationsEnabled, onPressOut]);
|
||||||
|
|
||||||
const handlePress = useCallback(() => {
|
const handlePress = useCallback(() => {
|
||||||
onPressedOut();
|
onPressedOut();
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
B4D0B2682C1DED67006B6B1B /* ReceiveMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4D0B2672C1DED67006B6B1B /* ReceiveMethod.swift */; };
|
B4D0B2682C1DED67006B6B1B /* ReceiveMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4D0B2672C1DED67006B6B1B /* ReceiveMethod.swift */; };
|
||||||
B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; };
|
B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; };
|
||||||
B4EFF73B2C3F6C5E0095D655 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4EFF73A2C3F6C5E0095D655 /* MockData.swift */; };
|
B4EFF73B2C3F6C5E0095D655 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4EFF73A2C3F6C5E0095D655 /* MockData.swift */; };
|
||||||
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
|
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -427,7 +427,7 @@
|
||||||
files = (
|
files = (
|
||||||
782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */,
|
782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */,
|
||||||
764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */,
|
764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */,
|
||||||
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */,
|
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */,
|
||||||
17CDA0718F42DB2CE856C872 /* libPods-BlueWallet.a in Frameworks */,
|
17CDA0718F42DB2CE856C872 /* libPods-BlueWallet.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -56,7 +56,5 @@
|
||||||
<key>apiKey</key>
|
<key>apiKey</key>
|
||||||
<string>17ba9059f676f1cc4f45d98182388b01</string>
|
<string>17ba9059f676f1cc4f45d98182388b01</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>WKCompanionAppBundleIdentifier</key>
|
|
||||||
<string>io.bluewallet.bluewallet</string>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -1588,8 +1588,27 @@ PODS:
|
||||||
- React-logger (= 0.75.4)
|
- React-logger (= 0.75.4)
|
||||||
- React-perflogger (= 0.75.4)
|
- React-perflogger (= 0.75.4)
|
||||||
- React-utils (= 0.75.4)
|
- React-utils (= 0.75.4)
|
||||||
- ReactNativeCameraKit (13.0.0):
|
- ReactNativeCameraKit (14.1.0):
|
||||||
|
- DoubleConversion
|
||||||
|
- glog
|
||||||
|
- hermes-engine
|
||||||
|
- RCT-Folly (= 2024.01.01.00)
|
||||||
|
- RCTRequired
|
||||||
|
- RCTTypeSafety
|
||||||
- React-Core
|
- React-Core
|
||||||
|
- React-debug
|
||||||
|
- React-Fabric
|
||||||
|
- React-featureflags
|
||||||
|
- React-graphics
|
||||||
|
- React-ImageManager
|
||||||
|
- React-NativeModulesApple
|
||||||
|
- React-RCTFabric
|
||||||
|
- React-rendererdebug
|
||||||
|
- React-utils
|
||||||
|
- ReactCodegen
|
||||||
|
- ReactCommon/turbomodule/bridging
|
||||||
|
- ReactCommon/turbomodule/core
|
||||||
|
- Yoga
|
||||||
- RealmJS (20.1.0):
|
- RealmJS (20.1.0):
|
||||||
- React
|
- React
|
||||||
- RNCAsyncStorage (2.1.0):
|
- RNCAsyncStorage (2.1.0):
|
||||||
|
@ -2258,7 +2277,7 @@ SPEC CHECKSUMS:
|
||||||
React-utils: 02526ea15628a768b8db9517b6017a1785c734d2
|
React-utils: 02526ea15628a768b8db9517b6017a1785c734d2
|
||||||
ReactCodegen: 8b5341ecb61898b8bd40a73ebc443c6bf2d14423
|
ReactCodegen: 8b5341ecb61898b8bd40a73ebc443c6bf2d14423
|
||||||
ReactCommon: 36d48f542b4010786d6b2bcee615fe5f906b7105
|
ReactCommon: 36d48f542b4010786d6b2bcee615fe5f906b7105
|
||||||
ReactNativeCameraKit: f058d47e0b1e55fd819bb55ee16505a2e0ca53db
|
ReactNativeCameraKit: e72b838dac4ea2da19b7eb5d00b23125072790fd
|
||||||
RealmJS: 9fd51c849eb552ade9f7b11db42a319b4f6cab4c
|
RealmJS: 9fd51c849eb552ade9f7b11db42a319b4f6cab4c
|
||||||
RNCAsyncStorage: c91d753ede6dc21862c4922cd13f98f7cfde578e
|
RNCAsyncStorage: c91d753ede6dc21862c4922cd13f98f7cfde578e
|
||||||
RNCClipboard: dbcf25b8f666b4685c02eeb65be981d30198e505
|
RNCClipboard: dbcf25b8f666b4685c02eeb65be981d30198e505
|
||||||
|
|
|
@ -9,7 +9,6 @@ export type ScanQRCodeParamList = {
|
||||||
urTotal?: number;
|
urTotal?: number;
|
||||||
urHave?: number;
|
urHave?: number;
|
||||||
backdoorText?: string;
|
backdoorText?: string;
|
||||||
onDismiss?: () => void;
|
|
||||||
onBarScanned?: (data: string) => void;
|
onBarScanned?: (data: string) => void;
|
||||||
showFileImportButton?: boolean;
|
showFileImportButton?: boolean;
|
||||||
backdoorVisible?: boolean;
|
backdoorVisible?: boolean;
|
||||||
|
|
28
package-lock.json
generated
28
package-lock.json
generated
|
@ -63,12 +63,12 @@
|
||||||
"react-native": "0.75.4",
|
"react-native": "0.75.4",
|
||||||
"react-native-biometrics": "3.0.1",
|
"react-native-biometrics": "3.0.1",
|
||||||
"react-native-blue-crypto": "github:BlueWallet/react-native-blue-crypto#3cb5442",
|
"react-native-blue-crypto": "github:BlueWallet/react-native-blue-crypto#3cb5442",
|
||||||
"react-native-camera-kit": "13.0.0",
|
"react-native-camera-kit": "14.1.0",
|
||||||
"react-native-crypto": "2.2.0",
|
"react-native-crypto": "2.2.0",
|
||||||
"react-native-default-preference": "https://github.com/BlueWallet/react-native-default-preference.git#6338a1f1235e4130b8cfc2dd3b53015eeff2870c",
|
"react-native-default-preference": "https://github.com/BlueWallet/react-native-default-preference.git#6338a1f1235e4130b8cfc2dd3b53015eeff2870c",
|
||||||
"react-native-device-info": "13.2.0",
|
"react-native-device-info": "13.2.0",
|
||||||
"react-native-document-picker": "9.3.1",
|
"react-native-document-picker": "9.3.1",
|
||||||
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#3a61627",
|
"react-native-draglist": "github:BlueWallet/react-native-draglist#a4af02f",
|
||||||
"react-native-fs": "2.20.0",
|
"react-native-fs": "2.20.0",
|
||||||
"react-native-gesture-handler": "2.21.2",
|
"react-native-gesture-handler": "2.21.2",
|
||||||
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
|
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
|
||||||
|
@ -20530,12 +20530,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-camera-kit": {
|
"node_modules/react-native-camera-kit": {
|
||||||
"version": "13.0.0",
|
"version": "14.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-camera-kit/-/react-native-camera-kit-13.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-camera-kit/-/react-native-camera-kit-14.1.0.tgz",
|
||||||
"integrity": "sha512-fnkyivCG2xzS+14/doP8pCAYNafYaTyg5J0t+JJltJdgKSHf328OG44Rd+fnbbEOydZxgy/bcuLB24R0kCbynw==",
|
"integrity": "sha512-idkg+Sa2KbGvF6SUqmuAr2U12qBELdiuUJ6fxgB4whUC2AyYHi5jBxiGv6whY/eTB3is7nW1S+TjyM9pEBzNzw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"engines": {
|
||||||
"lodash": "^4.14.2"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "*",
|
"react": "*",
|
||||||
|
@ -20615,17 +20615,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-draggable-flatlist": {
|
"node_modules/react-native-draglist": {
|
||||||
"version": "4.0.1",
|
"version": "3.8.0",
|
||||||
"resolved": "git+ssh://git@github.com/BlueWallet/react-native-draggable-flatlist.git#3a61627474a4e35198ae961310c77fb305507509",
|
"resolved": "git+ssh://git@github.com/BlueWallet/react-native-draglist.git#a4af02fec803b75508a8136e35eca564bbb1d644",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
|
||||||
"@babel/preset-typescript": "^7.17.12"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react-native": ">=0.64.0",
|
"react": ">=17.0.1",
|
||||||
"react-native-gesture-handler": ">=2.0.0",
|
"react-native": ">=0.64.0"
|
||||||
"react-native-reanimated": ">=2.8.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-fs": {
|
"node_modules/react-native-fs": {
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
"android:clean": "cd android; ./gradlew clean ; cd .. ; npm run android",
|
"android:clean": "cd android; ./gradlew clean ; cd .. ; npm run android",
|
||||||
"ios": "react-native run-ios",
|
"ios": "react-native run-ios",
|
||||||
"postinstall": "rn-nodeify --install buffer,events,process,stream,inherits,path,assert,crypto --hack; npm run releasenotes2json; npm run branch2json; npm run patches",
|
"postinstall": "rn-nodeify --install buffer,events,process,stream,inherits,path,assert,crypto --hack; npm run releasenotes2json; npm run branch2json; npm run patches",
|
||||||
"patches": "patch -p1 < scripts/react-native-camera-kit.patch;",
|
"patches": "",
|
||||||
"test": "npm run tslint && npm run lint && npm run unit && npm run jest",
|
"test": "npm run tslint && npm run lint && npm run unit && npm run jest",
|
||||||
"jest": "jest tests/integration/*",
|
"jest": "jest tests/integration/*",
|
||||||
"e2e:debug-build": "detox build -c android.debug",
|
"e2e:debug-build": "detox build -c android.debug",
|
||||||
|
@ -127,12 +127,12 @@
|
||||||
"react-native": "0.75.4",
|
"react-native": "0.75.4",
|
||||||
"react-native-biometrics": "3.0.1",
|
"react-native-biometrics": "3.0.1",
|
||||||
"react-native-blue-crypto": "github:BlueWallet/react-native-blue-crypto#3cb5442",
|
"react-native-blue-crypto": "github:BlueWallet/react-native-blue-crypto#3cb5442",
|
||||||
"react-native-camera-kit": "13.0.0",
|
"react-native-camera-kit": "14.1.0",
|
||||||
"react-native-crypto": "2.2.0",
|
"react-native-crypto": "2.2.0",
|
||||||
"react-native-default-preference": "https://github.com/BlueWallet/react-native-default-preference.git#6338a1f1235e4130b8cfc2dd3b53015eeff2870c",
|
"react-native-default-preference": "https://github.com/BlueWallet/react-native-default-preference.git#6338a1f1235e4130b8cfc2dd3b53015eeff2870c",
|
||||||
"react-native-device-info": "13.2.0",
|
"react-native-device-info": "13.2.0",
|
||||||
"react-native-document-picker": "9.3.1",
|
"react-native-document-picker": "9.3.1",
|
||||||
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#3a61627",
|
"react-native-draglist": "github:BlueWallet/react-native-draglist#a4af02f",
|
||||||
"react-native-fs": "2.20.0",
|
"react-native-fs": "2.20.0",
|
||||||
"react-native-gesture-handler": "2.21.2",
|
"react-native-gesture-handler": "2.21.2",
|
||||||
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
|
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
|
||||||
|
|
|
@ -2,9 +2,7 @@ import { useFocusEffect, useIsFocused, useNavigation, useRoute } from '@react-na
|
||||||
import * as bitcoin from 'bitcoinjs-lib';
|
import * as bitcoin from 'bitcoinjs-lib';
|
||||||
import createHash from 'create-hash';
|
import createHash from 'create-hash';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { Alert, Image, Platform, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
|
import { Alert, Platform, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
|
||||||
import { CameraScreen } from 'react-native-camera-kit';
|
|
||||||
import { Icon } from '@rneui/themed';
|
|
||||||
import Base43 from '../../blue_modules/base43';
|
import Base43 from '../../blue_modules/base43';
|
||||||
import * as fs from '../../blue_modules/fs';
|
import * as fs from '../../blue_modules/fs';
|
||||||
import { BlueURDecoder, decodeUR, extractSingleWorkload } from '../../blue_modules/ur';
|
import { BlueURDecoder, decodeUR, extractSingleWorkload } from '../../blue_modules/ur';
|
||||||
|
@ -15,6 +13,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import { isCameraAuthorizationStatusGranted } from '../../helpers/scan-qr';
|
import { isCameraAuthorizationStatusGranted } from '../../helpers/scan-qr';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { useSettings } from '../../hooks/context/useSettings';
|
import { useSettings } from '../../hooks/context/useSettings';
|
||||||
|
import CameraScreen from '../../components/CameraScreen';
|
||||||
|
|
||||||
let decoder = false;
|
let decoder = false;
|
||||||
|
|
||||||
|
@ -23,39 +22,6 @@ const styles = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#000000',
|
backgroundColor: '#000000',
|
||||||
},
|
},
|
||||||
closeTouch: {
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 20,
|
|
||||||
position: 'absolute',
|
|
||||||
left: 16,
|
|
||||||
top: 55,
|
|
||||||
},
|
|
||||||
closeImage: {
|
|
||||||
alignSelf: 'center',
|
|
||||||
},
|
|
||||||
imagePickerTouch: {
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 20,
|
|
||||||
position: 'absolute',
|
|
||||||
left: 24,
|
|
||||||
bottom: 48,
|
|
||||||
},
|
|
||||||
filePickerTouch: {
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 20,
|
|
||||||
position: 'absolute',
|
|
||||||
left: 96,
|
|
||||||
bottom: 48,
|
|
||||||
},
|
|
||||||
openSettingsContainer: {
|
openSettingsContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
@ -67,6 +33,9 @@ const styles = StyleSheet.create({
|
||||||
height: 60,
|
height: 60,
|
||||||
backgroundColor: 'rgba(0,0,0,0.01)',
|
backgroundColor: 'rgba(0,0,0,0.01)',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
top: 10,
|
||||||
|
left: '50%',
|
||||||
|
transform: [{ translateX: -30 }],
|
||||||
},
|
},
|
||||||
backdoorInputWrapper: { position: 'absolute', left: '5%', top: '0%', width: '90%', height: '70%', backgroundColor: 'white' },
|
backdoorInputWrapper: { position: 'absolute', left: '5%', top: '0%', width: '90%', height: '70%', backgroundColor: 'white' },
|
||||||
progressWrapper: { position: 'absolute', alignSelf: 'center', alignItems: 'center', top: '50%', padding: 8, borderRadius: 8 },
|
progressWrapper: { position: 'absolute', alignSelf: 'center', alignItems: 'center', top: '50%', padding: 8, borderRadius: 8 },
|
||||||
|
@ -89,7 +58,7 @@ const ScanQRCode = () => {
|
||||||
const previousRoute = navigationState.routes[navigationState.routes.length - 2];
|
const previousRoute = navigationState.routes[navigationState.routes.length - 2];
|
||||||
const defaultLaunchedBy = previousRoute ? previousRoute.name : undefined;
|
const defaultLaunchedBy = previousRoute ? previousRoute.name : undefined;
|
||||||
|
|
||||||
const { launchedBy = defaultLaunchedBy, onBarScanned, onDismiss, showFileImportButton } = route.params || {};
|
const { launchedBy = defaultLaunchedBy, onBarScanned, showFileImportButton } = route.params || {};
|
||||||
const scannedCache = {};
|
const scannedCache = {};
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const isFocused = useIsFocused();
|
const isFocused = useIsFocused();
|
||||||
|
@ -288,7 +257,7 @@ const ScanQRCode = () => {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const showImagePicker = () => {
|
const onShowImagePickerButtonPress = () => {
|
||||||
if (!isLoading) {
|
if (!isLoading) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
fs.showImagePickerAndReadImage()
|
fs.showImagePickerAndReadImage()
|
||||||
|
@ -300,16 +269,7 @@ const ScanQRCode = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const dismiss = () => {
|
const dismiss = () => {
|
||||||
if (launchedBy) {
|
navigation.goBack();
|
||||||
let merge = true;
|
|
||||||
if (typeof onBarScanned !== 'function') {
|
|
||||||
merge = false;
|
|
||||||
}
|
|
||||||
navigation.navigate({ name: launchedBy, params: {}, merge });
|
|
||||||
} else {
|
|
||||||
navigation.goBack();
|
|
||||||
}
|
|
||||||
if (onDismiss) onDismiss();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const render = isLoading ? (
|
const render = isLoading ? (
|
||||||
|
@ -330,29 +290,13 @@ const ScanQRCode = () => {
|
||||||
cameraFlipImage={require('../../img/camera-rotate-solid.png')}
|
cameraFlipImage={require('../../img/camera-rotate-solid.png')}
|
||||||
onReadCode={event => onBarCodeRead({ data: event?.nativeEvent?.codeStringValue })}
|
onReadCode={event => onBarCodeRead({ data: event?.nativeEvent?.codeStringValue })}
|
||||||
showFrame={false}
|
showFrame={false}
|
||||||
|
showFilePickerButton={showFileImportButton}
|
||||||
|
showImagePickerButton={true}
|
||||||
|
onFilePickerButtonPress={showFilePicker}
|
||||||
|
onImagePickerButtonPress={onShowImagePickerButtonPress}
|
||||||
|
onCancelButtonPress={dismiss}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<TouchableOpacity accessibilityRole="button" accessibilityLabel={loc._.close} style={styles.closeTouch} onPress={dismiss}>
|
|
||||||
<Image style={styles.closeImage} source={require('../../img/close-white.png')} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={loc._.pick_image}
|
|
||||||
style={styles.imagePickerTouch}
|
|
||||||
onPress={showImagePicker}
|
|
||||||
>
|
|
||||||
<Icon name="image" type="font-awesome" color="#ffffff" />
|
|
||||||
</TouchableOpacity>
|
|
||||||
{showFileImportButton && (
|
|
||||||
<TouchableOpacity
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={loc._.pick_file}
|
|
||||||
style={styles.filePickerTouch}
|
|
||||||
onPress={showFilePicker}
|
|
||||||
>
|
|
||||||
<Icon name="file-import" type="font-awesome-5" color="#ffffff" />
|
|
||||||
</TouchableOpacity>
|
|
||||||
)}
|
|
||||||
{urTotal > 0 && (
|
{urTotal > 0 && (
|
||||||
<View style={[styles.progressWrapper, stylesHook.progressWrapper]} testID="UrProgressBar">
|
<View style={[styles.progressWrapper, stylesHook.progressWrapper]} testID="UrProgressBar">
|
||||||
<BlueText>{loc.wallets.please_continue_scanning}</BlueText>
|
<BlueText>{loc.wallets.please_continue_scanning}</BlueText>
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
import React, { useEffect, useLayoutEffect, useReducer, useCallback, useMemo, useRef } from 'react';
|
import React, { useEffect, useLayoutEffect, useReducer, useCallback, useMemo, useRef, useState } from 'react';
|
||||||
import { StyleSheet, TouchableOpacity, Image, Text, Alert, I18nManager, Animated, LayoutAnimation } from 'react-native';
|
import { StyleSheet, TouchableOpacity, Image, Text, Alert, I18nManager, Animated, LayoutAnimation, FlatList } from 'react-native';
|
||||||
import {
|
|
||||||
NestableScrollContainer,
|
|
||||||
ScaleDecorator,
|
|
||||||
OpacityDecorator,
|
|
||||||
NestableDraggableFlatList,
|
|
||||||
RenderItem,
|
|
||||||
// @ts-expect-error: react-native-draggable-flatlist is not typed
|
|
||||||
} from 'react-native-draggable-flatlist';
|
|
||||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||||
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
|
@ -25,6 +17,7 @@ import prompt from '../../helpers/prompt';
|
||||||
import HeaderRightButton from '../../components/HeaderRightButton';
|
import HeaderRightButton from '../../components/HeaderRightButton';
|
||||||
import { ManageWalletsListItem } from '../../components/ManageWalletsListItem';
|
import { ManageWalletsListItem } from '../../components/ManageWalletsListItem';
|
||||||
import { useSettings } from '../../hooks/context/useSettings';
|
import { useSettings } from '../../hooks/context/useSettings';
|
||||||
|
import DragList, { DragListRenderItemInfo } from 'react-native-draglist';
|
||||||
|
|
||||||
enum ItemType {
|
enum ItemType {
|
||||||
WalletSection = 'wallet',
|
WalletSection = 'wallet',
|
||||||
|
@ -206,21 +199,24 @@ const ManageWallets: React.FC = () => {
|
||||||
color: colors.foregroundColor,
|
color: colors.foregroundColor,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const [data, setData] = useState(state.tempOrder);
|
||||||
|
const listRef = useRef<FlatList<Item> | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({
|
setData(state.tempOrder);
|
||||||
type: SET_INITIAL_ORDER,
|
}, [state.tempOrder]);
|
||||||
payload: { wallets: walletsRef.current, txMetadata },
|
|
||||||
});
|
useEffect(() => {
|
||||||
|
dispatch({ type: SET_INITIAL_ORDER, payload: { wallets: walletsRef.current, txMetadata } });
|
||||||
}, [txMetadata]);
|
}, [txMetadata]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (debouncedSearchQuery) {
|
if (debouncedSearchQuery) {
|
||||||
dispatch({ type: SET_FILTERED_ORDER, payload: debouncedSearchQuery });
|
dispatch({ type: SET_FILTERED_ORDER, payload: debouncedSearchQuery });
|
||||||
} else {
|
} else {
|
||||||
dispatch({ type: SET_INITIAL_ORDER, payload: { wallets: walletsRef.current, txMetadata } });
|
dispatch({ type: SET_TEMP_ORDER, payload: state.order });
|
||||||
}
|
}
|
||||||
}, [debouncedSearchQuery, txMetadata]);
|
}, [debouncedSearchQuery, state.order]);
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
if (state.searchQuery.length === 0 && !state.isSearchFocused) {
|
if (state.searchQuery.length === 0 && !state.isSearchFocused) {
|
||||||
|
@ -244,6 +240,7 @@ const ManageWallets: React.FC = () => {
|
||||||
dispatch({ type: SET_IS_SEARCH_FOCUSED, payload: false });
|
dispatch({ type: SET_IS_SEARCH_FOCUSED, payload: false });
|
||||||
}
|
}
|
||||||
}, [goBack, setWalletsWithNewOrder, state.searchQuery, state.isSearchFocused, state.tempOrder, navigation]);
|
}, [goBack, setWalletsWithNewOrder, state.searchQuery, state.isSearchFocused, state.tempOrder, navigation]);
|
||||||
|
|
||||||
const hasUnsavedChanges = useMemo(() => {
|
const hasUnsavedChanges = useMemo(() => {
|
||||||
return JSON.stringify(walletsRef.current) !== JSON.stringify(state.tempOrder.map(item => item.data));
|
return JSON.stringify(walletsRef.current) !== JSON.stringify(state.tempOrder.map(item => item.data));
|
||||||
}, [state.tempOrder]);
|
}, [state.tempOrder]);
|
||||||
|
@ -319,6 +316,14 @@ const ManageWallets: React.FC = () => {
|
||||||
}, [hasUnsavedChanges, navigation, setIsDrawerShouldHide]),
|
}, [hasUnsavedChanges, navigation, setIsDrawerShouldHide]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ensure the listener is re-added every time there are unsaved changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (beforeRemoveListenerRef.current) {
|
||||||
|
navigation.removeListener('beforeRemove', beforeRemoveListenerRef.current);
|
||||||
|
navigation.addListener('beforeRemove', beforeRemoveListenerRef.current);
|
||||||
|
}
|
||||||
|
}, [hasUnsavedChanges, navigation]);
|
||||||
|
|
||||||
const renderHighlightedText = useCallback(
|
const renderHighlightedText = useCallback(
|
||||||
(text: string, query: string) => {
|
(text: string, query: string) => {
|
||||||
const parts = text.split(new RegExp(`(${query})`, 'gi'));
|
const parts = text.split(new RegExp(`(${query})`, 'gi'));
|
||||||
|
@ -425,60 +430,43 @@ const ManageWallets: React.FC = () => {
|
||||||
},
|
},
|
||||||
[goBack, navigate],
|
[goBack, navigate],
|
||||||
);
|
);
|
||||||
const renderWalletItem = useCallback(
|
const renderItem = useCallback(
|
||||||
({ item, drag, isActive }: RenderItem<Item>) => (
|
(info: DragListRenderItemInfo<Item>) => {
|
||||||
<ScaleDecorator drag={drag} activeScale={1.1}>
|
const { item, onDragStart, onDragEnd, isActive } = info;
|
||||||
<OpacityDecorator activeOpacity={0.5}>
|
return (
|
||||||
<ManageWalletsListItem
|
<ManageWalletsListItem
|
||||||
item={item}
|
item={item}
|
||||||
isDraggingDisabled={state.searchQuery.length > 0 || state.isSearchFocused}
|
onPressIn={state.isSearchFocused || state.searchQuery.length > 0 ? undefined : onDragStart}
|
||||||
drag={drag}
|
onPressOut={state.isSearchFocused || state.searchQuery.length > 0 ? undefined : onDragEnd}
|
||||||
state={state}
|
isDraggingDisabled={state.searchQuery.length > 0 || state.isSearchFocused}
|
||||||
navigateToWallet={navigateToWallet}
|
state={state}
|
||||||
renderHighlightedText={renderHighlightedText}
|
navigateToWallet={navigateToWallet}
|
||||||
handleDeleteWallet={handleDeleteWallet}
|
renderHighlightedText={renderHighlightedText}
|
||||||
handleToggleHideBalance={handleToggleHideBalance}
|
handleDeleteWallet={handleDeleteWallet}
|
||||||
/>
|
handleToggleHideBalance={handleToggleHideBalance}
|
||||||
</OpacityDecorator>
|
isActive={isActive}
|
||||||
</ScaleDecorator>
|
drag={state.isSearchFocused || state.searchQuery.length > 0 ? undefined : onDragStart}
|
||||||
),
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
[state, navigateToWallet, renderHighlightedText, handleDeleteWallet, handleToggleHideBalance],
|
[state, navigateToWallet, renderHighlightedText, handleDeleteWallet, handleToggleHideBalance],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderPlaceholder = useCallback(
|
const onReordered = useCallback(
|
||||||
({ item, drag, isActive }: RenderItem<Item>) => (
|
(fromIndex: number, toIndex: number) => {
|
||||||
<ManageWalletsListItem
|
const copy = [...state.order];
|
||||||
item={item}
|
const removed = copy.splice(fromIndex, 1);
|
||||||
isDraggingDisabled={state.searchQuery.length > 0 || state.isSearchFocused}
|
copy.splice(toIndex, 0, removed[0]);
|
||||||
state={state}
|
dispatch({ type: SET_TEMP_ORDER, payload: copy });
|
||||||
navigateToWallet={navigateToWallet}
|
dispatch({
|
||||||
renderHighlightedText={renderHighlightedText}
|
type: SET_INITIAL_ORDER,
|
||||||
isPlaceHolder
|
payload: {
|
||||||
handleDeleteWallet={handleDeleteWallet}
|
wallets: copy.filter(item => item.type === ItemType.WalletSection).map(item => item.data as TWallet),
|
||||||
handleToggleHideBalance={handleToggleHideBalance}
|
txMetadata: state.txMetadata,
|
||||||
/>
|
},
|
||||||
),
|
});
|
||||||
[handleDeleteWallet, handleToggleHideBalance, navigateToWallet, renderHighlightedText, state],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onChangeOrder = useCallback(() => {
|
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.ImpactMedium);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onDragBegin = useCallback(() => {
|
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.Selection);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onRelease = useCallback(() => {
|
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.ImpactLight);
|
|
||||||
}, []);
|
|
||||||
const onDragEnd = useCallback(
|
|
||||||
({ data }: { data: Item[] }) => {
|
|
||||||
const updatedWallets = data.filter((item): item is WalletItem => item.type === ItemType.WalletSection).map(item => item.data);
|
|
||||||
|
|
||||||
dispatch({ type: SET_INITIAL_ORDER, payload: { wallets: updatedWallets, txMetadata: state.txMetadata } });
|
|
||||||
},
|
},
|
||||||
[state.txMetadata],
|
[state.order, state.txMetadata],
|
||||||
);
|
);
|
||||||
|
|
||||||
const keyExtractor = useCallback((item: Item, index: number) => index.toString(), []);
|
const keyExtractor = useCallback((item: Item, index: number) => index.toString(), []);
|
||||||
|
@ -499,39 +487,21 @@ const ManageWallets: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GestureHandlerRootView style={[{ backgroundColor: colors.background }, styles.root]}>
|
<GestureHandlerRootView style={[{ backgroundColor: colors.background }, styles.root]}>
|
||||||
<NestableScrollContainer contentInsetAdjustmentBehavior="automatic" automaticallyAdjustContentInsets scrollEnabled>
|
<>
|
||||||
{renderHeader}
|
{renderHeader}
|
||||||
<NestableDraggableFlatList
|
<DragList
|
||||||
data={state.tempOrder.filter((item): item is WalletItem => item.type === ItemType.WalletSection)}
|
|
||||||
extraData={state.tempOrder}
|
|
||||||
keyExtractor={keyExtractor}
|
|
||||||
renderItem={renderWalletItem}
|
|
||||||
onChangeOrder={onChangeOrder}
|
|
||||||
onDragBegin={onDragBegin}
|
|
||||||
onPlaceholderIndexChange={onChangeOrder}
|
|
||||||
onRelease={onRelease}
|
|
||||||
delayLongPress={150}
|
|
||||||
useNativeDriver={true}
|
|
||||||
dragItemOverflow
|
|
||||||
autoscrollThreshold={1}
|
|
||||||
renderPlaceholder={renderPlaceholder}
|
|
||||||
autoscrollSpeed={0.5}
|
|
||||||
contentInsetAdjustmentBehavior="automatic"
|
|
||||||
automaticallyAdjustContentInsets
|
automaticallyAdjustContentInsets
|
||||||
onDragEnd={onDragEnd}
|
automaticallyAdjustKeyboardInsets
|
||||||
containerStyle={styles.root}
|
automaticallyAdjustsScrollIndicatorInsets
|
||||||
/>
|
|
||||||
<NestableDraggableFlatList
|
|
||||||
data={state.tempOrder.filter((item): item is TransactionItem => item.type === ItemType.TransactionSection)}
|
|
||||||
keyExtractor={keyExtractor}
|
|
||||||
renderItem={renderWalletItem}
|
|
||||||
dragItemOverflow
|
|
||||||
containerStyle={styles.root}
|
|
||||||
contentInsetAdjustmentBehavior="automatic"
|
contentInsetAdjustmentBehavior="automatic"
|
||||||
automaticallyAdjustContentInsets
|
data={data}
|
||||||
useNativeDriver={true}
|
containerStyle={[{ backgroundColor: colors.background }, styles.root]}
|
||||||
|
keyExtractor={keyExtractor}
|
||||||
|
onReordered={onReordered}
|
||||||
|
renderItem={renderItem}
|
||||||
|
ref={listRef}
|
||||||
/>
|
/>
|
||||||
</NestableScrollContainer>
|
</>
|
||||||
</GestureHandlerRootView>
|
</GestureHandlerRootView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,10 @@ import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
|
||||||
import { useSettings } from '../../hooks/context/useSettings';
|
import { useSettings } from '../../hooks/context/useSettings';
|
||||||
import { isDesktop } from '../../blue_modules/environment';
|
import { isDesktop } from '../../blue_modules/environment';
|
||||||
import { useKeyboard } from '../../hooks/useKeyboard';
|
import { useKeyboard } from '../../hooks/useKeyboard';
|
||||||
|
import {
|
||||||
|
DoneAndDismissKeyboardInputAccessory,
|
||||||
|
DoneAndDismissKeyboardInputAccessoryViewID,
|
||||||
|
} from '../../components/DoneAndDismissKeyboardInputAccessory';
|
||||||
|
|
||||||
const staticCache = {};
|
const staticCache = {};
|
||||||
|
|
||||||
|
@ -684,7 +688,16 @@ const WalletsAddMultisigStep2 = () => {
|
||||||
<BlueTextCentered>{loc.multisig.type_your_mnemonics}</BlueTextCentered>
|
<BlueTextCentered>{loc.multisig.type_your_mnemonics}</BlueTextCentered>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<View style={styles.multiLineTextInput}>
|
<View style={styles.multiLineTextInput}>
|
||||||
<BlueFormMultiInput value={importText} onChangeText={setImportText} />
|
<BlueFormMultiInput
|
||||||
|
value={importText}
|
||||||
|
onChangeText={setImportText}
|
||||||
|
inputAccessoryViewID={DoneAndDismissKeyboardInputAccessoryViewID}
|
||||||
|
/>
|
||||||
|
{Platform.select({
|
||||||
|
ios: <DoneAndDismissKeyboardInputAccessory />,
|
||||||
|
android: isVisible && <DoneAndDismissKeyboardInputAccessory />,
|
||||||
|
})}
|
||||||
|
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
</View>
|
</View>
|
||||||
</BottomModal>
|
</BottomModal>
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
--- ../node_modules/react-native-camera-kit/android/src/main/java/com/rncamerakit/CKCamera.kt 2023-11-10 11:25:36
|
|
||||||
+++ ../node_modules/react-native-camera-kit/android/src/main/java/com/rncamerakit/CKCamera.kt 2023-11-10 11:25:42
|
|
||||||
@@ -180,7 +180,7 @@
|
|
||||||
orientationListener!!.enable()
|
|
||||||
|
|
||||||
val scaleDetector = ScaleGestureDetector(context, object: ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
|
||||||
- override fun onScale(detector: ScaleGestureDetector?): Boolean {
|
|
||||||
+ override fun onScale(detector: ScaleGestureDetector): Boolean {
|
|
||||||
if (zoomMode == "off") return true
|
|
||||||
val cameraControl = camera?.cameraControl ?: return true
|
|
||||||
val zoom = camera?.cameraInfo?.zoomState?.value?.zoomRatio ?: return true
|
|
||||||
|
|
||||||
--- ../node_modules/react-native-camera-kit/dist/CameraScreen.js 2024-09-01 13:00:57
|
|
||||||
+++ ../node_modules/react-native-camera-kit/dist/CameraScreen.js 2024-09-01 13:00:46
|
|
||||||
@@ -61,14 +61,14 @@
|
|
||||||
</TouchableOpacity>));
|
|
||||||
}
|
|
||||||
renderTorchButton() {
|
|
||||||
- return (!this.isCaptureRetakeMode() && (<TouchableOpacity style={{ paddingHorizontal: 15 }} onPress={() => this.onSetTorch()}>
|
|
||||||
- <Image style={[{ flex: 1, justifyContent: 'center' }, this.props.torchImageStyle]} source={this.state.torchMode ? this.props.torchOnImage : this.props.torchOffImage} resizeMode="contain"/>
|
|
||||||
+ return (!this.isCaptureRetakeMode() && (<TouchableOpacity style={{ backgroundColor: '#FFFFFF', borderRadius: 20, height: 40, marginHorizontal: 15 }} onPress={() => this.onSetTorch()}>
|
|
||||||
+ <Image style={[{ width: 40, height: 40, justifyContent: 'center' }, this.props.torchImageStyle]} source={this.state.torchMode ? this.props.torchOnImage : this.props.torchOffImage} resizeMode="contain"/>
|
|
||||||
</TouchableOpacity>));
|
|
||||||
}
|
|
||||||
renderSwitchCameraButton() {
|
|
||||||
return (this.props.cameraFlipImage &&
|
|
||||||
- !this.isCaptureRetakeMode() && (<TouchableOpacity style={{ paddingHorizontal: 15 }} onPress={() => this.onSwitchCameraPressed()}>
|
|
||||||
- <Image style={{ flex: 1, justifyContent: 'center' }} source={this.props.cameraFlipImage} resizeMode="contain"/>
|
|
||||||
+ !this.isCaptureRetakeMode() && (<TouchableOpacity style={{ }} onPress={() => this.onSwitchCameraPressed()}>
|
|
||||||
+ <Image style={{ width: 40, height: 40, justifyContent: 'center' }} source={this.props.cameraFlipImage} resizeMode="contain"/>
|
|
||||||
</TouchableOpacity>));
|
|
||||||
}
|
|
||||||
renderTopButtons() {
|
|
||||||
\ No newline at end of file
|
|
||||||
@@ -228,8 +228,8 @@
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
- paddingTop: 8,
|
|
||||||
- paddingBottom: 0,
|
|
||||||
+ paddingTop:44,
|
|
||||||
+ paddingHorizontal: 16,
|
|
||||||
},
|
|
||||||
cameraContainer: Object.assign({}, Platform.select({
|
|
||||||
android: {
|
|
||||||
\ No newline at end of file
|
|
Loading…
Add table
Reference in a new issue