mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 18:00:17 +01:00
Merge branch 'master' into keysedit
This commit is contained in:
commit
a537917b0d
@ -33,7 +33,7 @@ import * as NavigationService from './NavigationService';
|
||||
import WalletGradient from './class/wallet-gradient';
|
||||
import ToolTip from 'react-native-tooltip';
|
||||
import { BlurView } from '@react-native-community/blur';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
|
||||
import showPopupMenu from 'react-native-popup-menu-android';
|
||||
import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeType } from './models/networkTransactionFees';
|
||||
import Biometric from './class/biometrics';
|
||||
@ -1641,7 +1641,7 @@ export class BlueAddressInput extends Component {
|
||||
};
|
||||
|
||||
choosePhoto = () => {
|
||||
ImagePicker.launchImageLibrary(
|
||||
launchImageLibrary(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -1649,7 +1649,7 @@ export class BlueAddressInput extends Component {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
this.props.onBarScanned(result);
|
||||
@ -1663,7 +1663,7 @@ export class BlueAddressInput extends Component {
|
||||
};
|
||||
|
||||
takePhoto = () => {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -1671,7 +1671,7 @@ export class BlueAddressInput extends Component {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
this.props.onBarScanned(result);
|
||||
|
13
__mocks__/react-native-image-picker.js
vendored
Normal file
13
__mocks__/react-native-image-picker.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
import {NativeModules} from 'react-native';
|
||||
|
||||
// Mock the ImagePickerManager native module to allow us to unit test the JavaScript code
|
||||
NativeModules.ImagePickerManager = {
|
||||
showImagePicker: jest.fn(),
|
||||
launchCamera: jest.fn(),
|
||||
launchImageLibrary: jest.fn(),
|
||||
};
|
||||
|
||||
// Reset the mocks before each test
|
||||
global.beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
minSdkVersion = 18
|
||||
minSdkVersion = 21
|
||||
supportLibVersion = "28.0.0"
|
||||
buildToolsVersion = "29.0.2"
|
||||
compileSdkVersion = 29
|
||||
|
@ -119,7 +119,7 @@ const showFilePickerAndReadFile = async function () {
|
||||
} else {
|
||||
if (res.type === DocumentPicker.types.images || res.type.startsWith('image/')) {
|
||||
return new Promise(resolve => {
|
||||
const uri = Platform.OS === 'ios' ? res.uri.toString().replace('file://', '') : res.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? res.uri.toString().replace('file://', '') : res.uri;
|
||||
LocalQRCode.decode(decodeURI(uri), (error, result) => {
|
||||
if (!error) {
|
||||
resolve({ data: result, uri: decodeURI(res.uri) });
|
||||
|
@ -265,8 +265,8 @@ PODS:
|
||||
- React
|
||||
- react-native-geolocation (2.0.2):
|
||||
- React
|
||||
- react-native-image-picker (2.3.4):
|
||||
- React-Core
|
||||
- react-native-image-picker (3.0.1):
|
||||
- React
|
||||
- react-native-is-catalyst (1.0.0):
|
||||
- React
|
||||
- react-native-randombytes (3.5.3):
|
||||
@ -703,7 +703,7 @@ SPEC CHECKSUMS:
|
||||
react-native-document-picker: c5752781fbc0c126c627c1549b037c139444a4cf
|
||||
react-native-fingerprint-scanner: c68136ca57e3704d7bdf5faa554ea535ce15b1d0
|
||||
react-native-geolocation: cbd9d6bd06bac411eed2671810f454d4908484a8
|
||||
react-native-image-picker: 32d1ad2c0024ca36161ae0d5c2117e2d6c441f11
|
||||
react-native-image-picker: 4efc5b7f3a780975bcc677335eb670e52d203424
|
||||
react-native-is-catalyst: 52ee70e0123c82419dd4ce47dc4cc94b22467512
|
||||
react-native-randombytes: 991545e6eaaf700b4ee384c291ef3d572e0b2ca8
|
||||
react-native-safe-area-context: 01158a92c300895d79dee447e980672dc3fb85a6
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -18996,9 +18996,9 @@
|
||||
"integrity": "sha512-KTIy7lExwMtB6pOpCARyUzFj5EzYTh+A1GN/FB5Eb0LrW5C6hbb1kdj9K2/RHyZC+wyAJD1M823ZaDCU6n6cLA=="
|
||||
},
|
||||
"react-native-image-picker": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-2.3.4.tgz",
|
||||
"integrity": "sha512-4UHu+zOyDT570r5mIbjH6h1iMrKIq/qfsKiAVUEZwncVegh0usJiEYNyJw4CEVwNeehmye/ia5sLDsa+kzIE4g=="
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-3.0.1.tgz",
|
||||
"integrity": "sha512-jVWiKT24jxr7K8dAixlsfHURZd+eDA4WWYeZhhKeJDGITCtFPphcTuFomTMtaWYE/gJgNTEL8TiLedcfeqJ9qw=="
|
||||
},
|
||||
"react-native-inappbrowser-reborn": {
|
||||
"version": "git+https://github.com/BlueWallet/react-native-inappbrowser.git#fa2d8e1763e46dd12a7e53081e97a0f908049103",
|
||||
|
@ -129,7 +129,7 @@
|
||||
"react-native-gesture-handler": "1.8.0",
|
||||
"react-native-handoff": "git+https://github.com/marcosrdz/react-native-handoff.git",
|
||||
"react-native-haptic-feedback": "1.11.0",
|
||||
"react-native-image-picker": "2.3.4",
|
||||
"react-native-image-picker": "3.0.1",
|
||||
"react-native-inappbrowser-reborn": "git+https://github.com/BlueWallet/react-native-inappbrowser.git#fa2d8e1763e46dd12a7e53081e97a0f908049103",
|
||||
"react-native-is-catalyst": "git+https://github.com/BlueWallet/react-native-is-catalyst.git#v1.0.0",
|
||||
"react-native-level-fs": "3.0.1",
|
||||
|
@ -3,7 +3,7 @@ import React, { useState } from 'react';
|
||||
import { Image, View, TouchableOpacity, StatusBar, Platform, StyleSheet, TextInput } from 'react-native';
|
||||
import { RNCamera } from 'react-native-camera';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchImageLibrary } from 'react-native-image-picker';
|
||||
import { decodeUR, extractSingleWorkload } from 'bc-ur';
|
||||
import { useNavigation, useRoute, useIsFocused, useTheme } from '@react-navigation/native';
|
||||
import loc from '../../loc';
|
||||
@ -192,7 +192,7 @@ const ScanQRCode = () => {
|
||||
const showImagePicker = () => {
|
||||
if (!isLoading) {
|
||||
setIsLoading(true);
|
||||
ImagePicker.launchImageLibrary(
|
||||
launchImageLibrary(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -200,7 +200,7 @@ const ScanQRCode = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarCodeRead({ data: result });
|
||||
|
@ -6,7 +6,7 @@ import { DynamicQRCode } from '../../components/DynamicQRCode';
|
||||
import { SquareButton } from '../../components/SquareButton';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import loc from '../../loc';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchCamera } from 'react-native-image-picker';
|
||||
import ScanQRCode from './ScanQRCode';
|
||||
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
@ -49,7 +49,7 @@ const PsbtMultisigQRCode = () => {
|
||||
|
||||
const openScanner = () => {
|
||||
if (isDesktop) {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -57,7 +57,7 @@ const PsbtMultisigQRCode = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
StyleSheet,
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchCamera } from 'react-native-image-picker';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import {
|
||||
SecondButton,
|
||||
@ -244,7 +244,7 @@ const PsbtWithHardwareWallet = () => {
|
||||
|
||||
const openScanner = () => {
|
||||
if (isDesktop) {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -252,7 +252,7 @@ const PsbtWithHardwareWallet = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
|
@ -29,7 +29,7 @@ import { HDSegwitBech32Wallet, MultisigCosigner, MultisigHDWallet } from '../../
|
||||
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
import loc from '../../loc';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchCamera } from 'react-native-image-picker';
|
||||
import ScanQRCode from '../send/ScanQRCode';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import { SquareButton } from '../../components/SquareButton';
|
||||
@ -59,7 +59,6 @@ const WalletsAddMultisigStep2 = () => {
|
||||
const { m, n, format } = useRoute().params;
|
||||
|
||||
const [cosigners, setCosigners] = useState([]); // array of cosigners user provided. if format [cosigner, fp, path]
|
||||
const [isOnCreateButtonEnabled, setIsOnCreateButtonEnabled] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isMnemonicsModalVisible, setIsMnemonicsModalVisible] = useState(false);
|
||||
const [isProvideMnemonicsModalVisible, setIsProvideMnemonicsModalVisible] = useState(false);
|
||||
@ -186,12 +185,12 @@ const WalletsAddMultisigStep2 = () => {
|
||||
w.generate().then(() => {
|
||||
const cosignersCopy = [...cosigners];
|
||||
cosignersCopy.push([w.getSecret(), false, false]);
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
if (Platform.OS !== 'android') LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setCosigners(cosignersCopy);
|
||||
setVaultKeyData({ keyIndex: cosignersCopy.length, seed: w.getSecret(), xpub: w.getXpub(), isLoading: false });
|
||||
setIsLoading(true);
|
||||
setIsMnemonicsModalVisible(true);
|
||||
if (cosignersCopy.length === n) setIsOnCreateButtonEnabled(true);
|
||||
|
||||
// filling cache
|
||||
setTimeout(() => {
|
||||
// filling cache
|
||||
@ -281,9 +280,8 @@ const WalletsAddMultisigStep2 = () => {
|
||||
|
||||
const cosignersCopy = [...cosigners];
|
||||
cosignersCopy.push([xpub, fp, path]);
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
if (Platform.OS !== 'android') LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setCosigners(cosignersCopy);
|
||||
if (cosignersCopy.length === n) setIsOnCreateButtonEnabled(true);
|
||||
};
|
||||
|
||||
const useMnemonicPhrase = () => {
|
||||
@ -301,9 +299,9 @@ const WalletsAddMultisigStep2 = () => {
|
||||
|
||||
const cosignersCopy = [...cosigners];
|
||||
cosignersCopy.push([hd.getSecret(), false, false]);
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
if (Platform.OS !== 'android') LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setCosigners(cosignersCopy);
|
||||
if (cosignersCopy.length === n) setIsOnCreateButtonEnabled(true);
|
||||
|
||||
setIsProvideMnemonicsModalVisible(false);
|
||||
setIsLoading(false);
|
||||
setImportText('');
|
||||
@ -388,16 +386,15 @@ const WalletsAddMultisigStep2 = () => {
|
||||
|
||||
const cosignersCopy = [...cosigners];
|
||||
cosignersCopy.push([cosigner.getXpub(), cosigner.getFp(), cosigner.getPath()]);
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
if (Platform.OS !== 'android') LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
setCosigners(cosignersCopy);
|
||||
if (cosignersCopy.length === n) setIsOnCreateButtonEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
const scanOrOpenFile = () => {
|
||||
setIsProvideMnemonicsModalVisible(false);
|
||||
if (isDesktop) {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -405,7 +402,7 @@ const WalletsAddMultisigStep2 = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
@ -665,7 +662,7 @@ const WalletsAddMultisigStep2 = () => {
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<View style={styles.buttonBottom}>
|
||||
<BlueButton title={loc.multisig.create} onPress={onCreate} disabled={!isOnCreateButtonEnabled} />
|
||||
<BlueButton title={loc.multisig.create} onPress={onCreate} disabled={cosigners.length !== n} />
|
||||
</View>
|
||||
);
|
||||
|
||||
|
@ -17,7 +17,7 @@ import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
import WalletImport from '../../class/wallet-import';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import ActionSheet from '../ActionSheet';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
|
||||
import loc from '../../loc';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import RNFS from 'react-native-fs';
|
||||
@ -115,7 +115,7 @@ const WalletsImport = () => {
|
||||
};
|
||||
|
||||
const choosePhoto = () => {
|
||||
ImagePicker.launchImageLibrary(
|
||||
launchImageLibrary(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -123,7 +123,7 @@ const WalletsImport = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
@ -137,7 +137,7 @@ const WalletsImport = () => {
|
||||
};
|
||||
|
||||
const takePhoto = () => {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -145,7 +145,7 @@ const WalletsImport = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
|
@ -21,7 +21,7 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
import { PlaceholderWallet } from '../../class';
|
||||
import WalletImport from '../../class/wallet-import';
|
||||
import ActionSheet from '../ActionSheet';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchImageLibrary, launchCamera } from 'react-native-image-picker';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import loc from '../../loc';
|
||||
import { FContainer, FButton } from '../../components/FloatButtons';
|
||||
@ -363,7 +363,7 @@ const WalletsList = () => {
|
||||
};
|
||||
|
||||
const choosePhoto = () => {
|
||||
ImagePicker.launchImageLibrary(
|
||||
launchImageLibrary(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -371,7 +371,7 @@ const WalletsList = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
@ -385,7 +385,7 @@ const WalletsList = () => {
|
||||
};
|
||||
|
||||
const takePhoto = () => {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -393,7 +393,7 @@ const WalletsList = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarScanned(result);
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchImageLibrary } from 'react-native-image-picker';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import Handoff from 'react-native-handoff';
|
||||
@ -451,7 +451,7 @@ const WalletTransactions = () => {
|
||||
};
|
||||
|
||||
const choosePhoto = () => {
|
||||
ImagePicker.launchImageLibrary(
|
||||
launchImageLibrary(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -459,7 +459,7 @@ const WalletTransactions = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
onBarCodeRead({ data: result });
|
||||
|
@ -18,7 +18,7 @@ import { Icon } from 'react-native-elements';
|
||||
import { useFocusEffect, useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { launchCamera } from 'react-native-image-picker';
|
||||
|
||||
import {
|
||||
BlueButton,
|
||||
@ -404,7 +404,7 @@ const ViewEditMultisigCosigners = () => {
|
||||
const scanOrOpenFile = () => {
|
||||
setIsProvideMnemonicsModalVisible(false);
|
||||
if (isDesktop) {
|
||||
ImagePicker.launchCamera(
|
||||
launchCamera(
|
||||
{
|
||||
title: null,
|
||||
mediaType: 'photo',
|
||||
@ -412,7 +412,7 @@ const ViewEditMultisigCosigners = () => {
|
||||
},
|
||||
response => {
|
||||
if (response.uri) {
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
||||
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
|
||||
LocalQRCode.decode(uri, (error, result) => {
|
||||
if (!error) {
|
||||
_handleUseMnemonicPhrase(result);
|
||||
|
@ -1,619 +0,0 @@
|
||||
--- ImagePickerManager.m 1985-10-26 04:15:00.000000000 -0400
|
||||
+++ ImagePickerManager.m 2020-11-15 21:01:40.000000000 -0500
|
||||
@@ -1,9 +1,11 @@
|
||||
#import "ImagePickerManager.h"
|
||||
#import <React/RCTConvert.h>
|
||||
-#import <AssetsLibrary/AssetsLibrary.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <Photos/Photos.h>
|
||||
#import <React/RCTUtils.h>
|
||||
+#if !TARGET_OS_MACCATALYST
|
||||
+#import <AssetsLibrary/AssetsLibrary.h>
|
||||
+#endif
|
||||
|
||||
@import MobileCoreServices;
|
||||
|
||||
@@ -42,25 +44,25 @@
|
||||
{
|
||||
self.callback = callback; // Save the callback so we can use it from the delegate methods
|
||||
self.options = options;
|
||||
-
|
||||
+
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
-
|
||||
+
|
||||
NSString *title = [self.options valueForKey:@"title"];
|
||||
if ([title isEqual:[NSNull null]] || title.length == 0) {
|
||||
title = nil; // A more visually appealing UIAlertControl is displayed with a nil title rather than title = @""
|
||||
}
|
||||
NSString *cancelTitle = [self.options valueForKey:@"cancelButtonTitle"];
|
||||
NSString *takePhotoButtonTitle = [self.options valueForKey:@"takePhotoButtonTitle"];
|
||||
- NSString *chooseFromLibraryButtonTitle = [self.options valueForKey:@"chooseFromLibraryButtonTitle"];
|
||||
-
|
||||
+ NSString *chooseFromLibraryButtonTitle = [self.options valueForKey:@"chooseFromLibraryButtonTitle"];
|
||||
+
|
||||
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
alertController.view.tintColor = [RCTConvert UIColor:options[@"tintColor"]];
|
||||
-
|
||||
+
|
||||
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
|
||||
self.callback(@[@{@"didCancel": @YES}]); // Return callback for 'cancel' action (if is required)
|
||||
}];
|
||||
[alertController addAction:cancelAction];
|
||||
-
|
||||
+
|
||||
if (![takePhotoButtonTitle isEqual:[NSNull null]] && takePhotoButtonTitle.length > 0) {
|
||||
UIAlertAction *takePhotoAction = [UIAlertAction actionWithTitle:takePhotoButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
|
||||
[self actionHandler:action];
|
||||
@@ -73,7 +75,7 @@
|
||||
}];
|
||||
[alertController addAction:chooseFromLibraryAction];
|
||||
}
|
||||
-
|
||||
+
|
||||
// Add custom buttons to action sheet
|
||||
if ([self.options objectForKey:@"customButtons"] && [[self.options objectForKey:@"customButtons"] isKindOfClass:[NSArray class]]) {
|
||||
self.customButtons = [self.options objectForKey:@"customButtons"];
|
||||
@@ -85,16 +87,16 @@
|
||||
[alertController addAction:customAction];
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
UIViewController *root = RCTPresentedViewController();
|
||||
-
|
||||
+
|
||||
/* On iPad, UIAlertController presents a popover view rather than an action sheet like on iPhone. We must provide the location
|
||||
- of the location to show the popover in this case. For simplicity, we'll just display it on the bottom center of the screen
|
||||
- to mimic an action sheet */
|
||||
+ of the location to show the popover in this case. For simplicity, we'll just display it on the bottom center of the screen
|
||||
+ to mimic an action sheet */
|
||||
alertController.popoverPresentationController.sourceView = root.view;
|
||||
alertController.popoverPresentationController.sourceRect = CGRectMake(root.view.bounds.size.width / 2.0, root.view.bounds.size.height, 1.0, 1.0);
|
||||
-
|
||||
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
+
|
||||
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
|
||||
alertController.popoverPresentationController.permittedArrowDirections = 0;
|
||||
for (id subview in alertController.view.subviews) {
|
||||
if ([subview isMemberOfClass:[UIView class]]) {
|
||||
@@ -102,7 +104,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
[root presentViewController:alertController animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
@@ -119,7 +121,7 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
if ([action.title isEqualToString:[self.options valueForKey:@"takePhotoButtonTitle"]]) { // Take photo
|
||||
[self launchImagePicker:RNImagePickerTargetCamera];
|
||||
}
|
||||
@@ -137,7 +139,7 @@
|
||||
- (void)launchImagePicker:(RNImagePickerTarget)target
|
||||
{
|
||||
self.picker = [[UIImagePickerController alloc] init];
|
||||
-
|
||||
+
|
||||
if (target == RNImagePickerTargetCamera) {
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
self.callback(@[@{@"error": @"Camera not available on simulator"}]);
|
||||
@@ -155,10 +157,10 @@
|
||||
else { // RNImagePickerTargetLibrarySingleImage
|
||||
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
||||
}
|
||||
-
|
||||
+
|
||||
if ([[self.options objectForKey:@"mediaType"] isEqualToString:@"video"]
|
||||
|| [[self.options objectForKey:@"mediaType"] isEqualToString:@"mixed"]) {
|
||||
-
|
||||
+
|
||||
if ([[self.options objectForKey:@"videoQuality"] isEqualToString:@"high"]) {
|
||||
self.picker.videoQuality = UIImagePickerControllerQualityTypeHigh;
|
||||
}
|
||||
@@ -168,7 +170,7 @@
|
||||
else {
|
||||
self.picker.videoQuality = UIImagePickerControllerQualityTypeMedium;
|
||||
}
|
||||
-
|
||||
+
|
||||
id durationLimit = [self.options objectForKey:@"durationLimit"];
|
||||
if (durationLimit) {
|
||||
self.picker.videoMaximumDuration = [durationLimit doubleValue];
|
||||
@@ -182,13 +184,13 @@
|
||||
} else {
|
||||
self.picker.mediaTypes = @[(NSString *)kUTTypeImage];
|
||||
}
|
||||
-
|
||||
+
|
||||
if ([[self.options objectForKey:@"allowsEditing"] boolValue]) {
|
||||
self.picker.allowsEditing = true;
|
||||
}
|
||||
self.picker.modalPresentationStyle = UIModalPresentationCurrentContext;
|
||||
self.picker.delegate = self;
|
||||
-
|
||||
+
|
||||
// Check permissions
|
||||
void (^showPickerViewController)() = ^void() {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
@@ -196,57 +198,57 @@
|
||||
[root presentViewController:self.picker animated:YES completion:nil];
|
||||
});
|
||||
};
|
||||
-
|
||||
+
|
||||
if (target == RNImagePickerTargetCamera) {
|
||||
[self checkCameraPermissions:^(BOOL granted) {
|
||||
if (!granted) {
|
||||
self.callback(@[@{@"error": @"Camera permissions not granted"}]);
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
showPickerViewController();
|
||||
}];
|
||||
}
|
||||
else { // RNImagePickerTargetLibrarySingleImage
|
||||
- if (@available(iOS 11.0, *)) {
|
||||
- showPickerViewController();
|
||||
- } else {
|
||||
- [self checkPhotosPermissions:^(BOOL granted) {
|
||||
- if (!granted) {
|
||||
- self.callback(@[@{@"error": @"Photo library permissions not granted"}]);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- showPickerViewController();
|
||||
- }];
|
||||
- }
|
||||
+ if (@available(iOS 11.0, *)) {
|
||||
+ showPickerViewController();
|
||||
+ } else {
|
||||
+ [self checkPhotosPermissions:^(BOOL granted) {
|
||||
+ if (!granted) {
|
||||
+ self.callback(@[@{@"error": @"Photo library permissions not granted"}]);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ showPickerViewController();
|
||||
+ }];
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString * _Nullable)originalFilenameForAsset:(PHAsset * _Nullable)asset assetType:(PHAssetResourceType)type {
|
||||
if (!asset) { return nil; }
|
||||
-
|
||||
+
|
||||
PHAssetResource *originalResource;
|
||||
// Get the underlying resources for the PHAsset (PhotoKit)
|
||||
NSArray<PHAssetResource *> *pickedAssetResources = [PHAssetResource assetResourcesForAsset:asset];
|
||||
-
|
||||
+
|
||||
// Find the original resource (underlying image) for the asset, which has the desired filename
|
||||
for (PHAssetResource *resource in pickedAssetResources) {
|
||||
if (resource.type == type) {
|
||||
originalResource = resource;
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
return originalResource.originalFilename;
|
||||
}
|
||||
|
||||
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
|
||||
{
|
||||
dispatch_block_t dismissCompletionBlock = ^{
|
||||
-
|
||||
- NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
|
||||
+
|
||||
+ NSURL *imageURL = [info valueForKey:UIImagePickerControllerPHAsset];
|
||||
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
|
||||
-
|
||||
+
|
||||
NSString *fileName;
|
||||
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
|
||||
NSString *tempFileName = [[NSUUID UUID] UUIDString];
|
||||
@@ -264,18 +266,18 @@
|
||||
NSURL *videoURL = info[UIImagePickerControllerMediaURL];
|
||||
fileName = videoURL.lastPathComponent;
|
||||
}
|
||||
-
|
||||
+
|
||||
// We default to path to the temporary directory
|
||||
NSString *path = [[NSTemporaryDirectory()stringByStandardizingPath] stringByAppendingPathComponent:fileName];
|
||||
-
|
||||
+
|
||||
// If storage options are provided, we use the documents directory which is persisted
|
||||
if ([self.options objectForKey:@"storageOptions"] && [[self.options objectForKey:@"storageOptions"] isKindOfClass:[NSDictionary class]]) {
|
||||
NSDictionary *storageOptions = [self.options objectForKey:@"storageOptions"];
|
||||
-
|
||||
+
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
path = [documentsDirectory stringByAppendingPathComponent:fileName];
|
||||
-
|
||||
+
|
||||
// Creates documents subdirectory, if provided
|
||||
if ([storageOptions objectForKey:@"path"]) {
|
||||
NSString *newPath = [documentsDirectory stringByAppendingPathComponent:[storageOptions objectForKey:@"path"]];
|
||||
@@ -291,10 +293,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
// Create the response object
|
||||
self.response = [[NSMutableDictionary alloc] init];
|
||||
-
|
||||
+
|
||||
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { // PHOTOS
|
||||
UIImage *originalImage;
|
||||
if ([[self.options objectForKey:@"allowsEditing"] boolValue]) {
|
||||
@@ -303,13 +305,15 @@
|
||||
else {
|
||||
originalImage = [info objectForKey:UIImagePickerControllerOriginalImage];
|
||||
}
|
||||
-
|
||||
+
|
||||
if (imageURL) {
|
||||
PHAsset *pickedAsset;
|
||||
if (@available(iOS 11.0, *)) {
|
||||
- pickedAsset = [info objectForKey: UIImagePickerControllerPHAsset];
|
||||
+ pickedAsset = [info objectForKey: UIImagePickerControllerPHAsset];
|
||||
} else {
|
||||
- pickedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil].lastObject;
|
||||
+#if !TARGET_OS_MACCATALYST
|
||||
+ pickedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil].lastObject;
|
||||
+#endif
|
||||
}
|
||||
|
||||
NSString *originalFilename = [self originalFilenameForAsset:pickedAsset assetType:PHAssetResourceTypePhoto];
|
||||
@@ -322,9 +326,10 @@
|
||||
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:pickedAsset.creationDate];
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
// GIFs break when resized, so we handle them differently
|
||||
if (imageURL && [[imageURL absoluteString] rangeOfString:@"ext=GIF"].location != NSNotFound) {
|
||||
+#if !TARGET_OS_MACCATALYST
|
||||
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
|
||||
[assetsLibrary assetForURL:imageURL resultBlock:^(ALAsset *asset) {
|
||||
ALAssetRepresentation *rep = [asset defaultRepresentation];
|
||||
@@ -333,38 +338,39 @@
|
||||
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:repSize error:nil];
|
||||
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
|
||||
[data writeToFile:path atomically:YES];
|
||||
-
|
||||
+
|
||||
NSMutableDictionary *gifResponse = [[NSMutableDictionary alloc] init];
|
||||
[gifResponse setObject:@(originalImage.size.width) forKey:@"width"];
|
||||
[gifResponse setObject:@(originalImage.size.height) forKey:@"height"];
|
||||
-
|
||||
+
|
||||
BOOL vertical = (originalImage.size.width < originalImage.size.height) ? YES : NO;
|
||||
[gifResponse setObject:@(vertical) forKey:@"isVertical"];
|
||||
-
|
||||
+
|
||||
if (![[self.options objectForKey:@"noData"] boolValue]) {
|
||||
NSString *dataString = [data base64EncodedStringWithOptions:0];
|
||||
[gifResponse setObject:dataString forKey:@"data"];
|
||||
}
|
||||
-
|
||||
+
|
||||
NSURL *fileURL = [NSURL fileURLWithPath:path];
|
||||
[gifResponse setObject:[fileURL absoluteString] forKey:@"uri"];
|
||||
-
|
||||
+
|
||||
NSNumber *fileSizeValue = nil;
|
||||
NSError *fileSizeError = nil;
|
||||
[fileURL getResourceValue:&fileSizeValue forKey:NSURLFileSizeKey error:&fileSizeError];
|
||||
if (fileSizeValue){
|
||||
[gifResponse setObject:fileSizeValue forKey:@"fileSize"];
|
||||
}
|
||||
-
|
||||
+
|
||||
self.callback(@[gifResponse]);
|
||||
} failureBlock:^(NSError *error) {
|
||||
self.callback(@[@{@"error": error.localizedFailureReason}]);
|
||||
}];
|
||||
+#endif
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
UIImage *editedImage = [self fixOrientation:originalImage]; // Rotate the image for upload to web
|
||||
-
|
||||
+
|
||||
// If needed, downscale image
|
||||
float maxWidth = editedImage.size.width;
|
||||
float maxHeight = editedImage.size.height;
|
||||
@@ -375,7 +381,7 @@
|
||||
maxHeight = [[self.options valueForKey:@"maxHeight"] floatValue];
|
||||
}
|
||||
editedImage = [self downscaleImageIfNecessary:editedImage maxWidth:maxWidth maxHeight:maxHeight];
|
||||
-
|
||||
+
|
||||
NSData *data;
|
||||
NSString *mimeType;
|
||||
if ([[self.options objectForKey:@"imageFileType"] isEqualToString:@"png"]) {
|
||||
@@ -388,36 +394,37 @@
|
||||
}
|
||||
[self.response setObject:mimeType forKey:@"type"];
|
||||
[data writeToFile:path atomically:YES];
|
||||
-
|
||||
+
|
||||
if (![[self.options objectForKey:@"noData"] boolValue]) {
|
||||
NSString *dataString = [data base64EncodedStringWithOptions:0]; // base64 encoded image string
|
||||
[self.response setObject:dataString forKey:@"data"];
|
||||
}
|
||||
-
|
||||
+
|
||||
BOOL vertical = (editedImage.size.width < editedImage.size.height) ? YES : NO;
|
||||
[self.response setObject:@(vertical) forKey:@"isVertical"];
|
||||
NSURL *fileURL = [NSURL fileURLWithPath:path];
|
||||
NSString *filePath = [fileURL absoluteString];
|
||||
[self.response setObject:filePath forKey:@"uri"];
|
||||
-
|
||||
+
|
||||
// add ref to the original image
|
||||
NSString *origURL = [imageURL absoluteString];
|
||||
if (origURL) {
|
||||
- [self.response setObject:origURL forKey:@"origURL"];
|
||||
+ [self.response setObject:origURL forKey:@"origURL"];
|
||||
}
|
||||
-
|
||||
+
|
||||
NSNumber *fileSizeValue = nil;
|
||||
NSError *fileSizeError = nil;
|
||||
[fileURL getResourceValue:&fileSizeValue forKey:NSURLFileSizeKey error:&fileSizeError];
|
||||
if (fileSizeValue){
|
||||
[self.response setObject:fileSizeValue forKey:@"fileSize"];
|
||||
}
|
||||
-
|
||||
+
|
||||
[self.response setObject:@(editedImage.size.width) forKey:@"width"];
|
||||
[self.response setObject:@(editedImage.size.height) forKey:@"height"];
|
||||
-
|
||||
+
|
||||
NSDictionary *storageOptions = [self.options objectForKey:@"storageOptions"];
|
||||
if (storageOptions && [[storageOptions objectForKey:@"cameraRoll"] boolValue] == YES && self.picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
|
||||
+#if !TARGET_OS_MACCATALYST
|
||||
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
|
||||
if ([[storageOptions objectForKey:@"waitUntilSaved"] boolValue]) {
|
||||
[library writeImageToSavedPhotosAlbum:originalImage.CGImage metadata:[info valueForKey:UIImagePickerControllerMediaMetadata] completionBlock:^(NSURL *assetURL, NSError *error) {
|
||||
@@ -440,13 +447,15 @@
|
||||
} else {
|
||||
[library writeImageToSavedPhotosAlbum:originalImage.CGImage metadata:[info valueForKey:UIImagePickerControllerMediaMetadata] completionBlock:nil];
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
else { // VIDEO
|
||||
- NSURL *videoRefURL = info[UIImagePickerControllerReferenceURL];
|
||||
+ NSURL *videoRefURL = info[UIImagePickerControllerPHAsset];
|
||||
NSURL *videoURL = info[UIImagePickerControllerMediaURL];
|
||||
NSURL *videoDestinationURL = [NSURL fileURLWithPath:path];
|
||||
-
|
||||
+
|
||||
+#if !TARGET_OS_MACCATALYST
|
||||
if (videoRefURL) {
|
||||
PHAsset *pickedAsset = [PHAsset fetchAssetsWithALAssetURLs:@[videoRefURL] options:nil].lastObject;
|
||||
NSString *originalFilename = [self originalFilenameForAsset:pickedAsset assetType:PHAssetResourceTypeVideo];
|
||||
@@ -459,39 +468,41 @@
|
||||
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:pickedAsset.creationDate];
|
||||
}
|
||||
}
|
||||
-
|
||||
+#endif
|
||||
+
|
||||
if ([videoURL.URLByResolvingSymlinksInPath.path isEqualToString:videoDestinationURL.URLByResolvingSymlinksInPath.path] == NO) {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
-
|
||||
+
|
||||
// Delete file if it already exists
|
||||
if ([fileManager fileExistsAtPath:videoDestinationURL.path]) {
|
||||
[fileManager removeItemAtURL:videoDestinationURL error:nil];
|
||||
}
|
||||
-
|
||||
+
|
||||
if (videoURL) { // Protect against reported crash
|
||||
- NSError *error = nil;
|
||||
-
|
||||
- // If we have write access to the source file, move it. Otherwise use copy.
|
||||
- if ([fileManager isWritableFileAtPath:[videoURL path]]) {
|
||||
- [fileManager moveItemAtURL:videoURL toURL:videoDestinationURL error:&error];
|
||||
- } else {
|
||||
- [fileManager copyItemAtURL:videoURL toURL:videoDestinationURL error:&error];
|
||||
- }
|
||||
-
|
||||
- if (error) {
|
||||
- self.callback(@[@{@"error": error.localizedFailureReason}]);
|
||||
- return;
|
||||
- }
|
||||
+ NSError *error = nil;
|
||||
+
|
||||
+ // If we have write access to the source file, move it. Otherwise use copy.
|
||||
+ if ([fileManager isWritableFileAtPath:[videoURL path]]) {
|
||||
+ [fileManager moveItemAtURL:videoURL toURL:videoDestinationURL error:&error];
|
||||
+ } else {
|
||||
+ [fileManager copyItemAtURL:videoURL toURL:videoDestinationURL error:&error];
|
||||
+ }
|
||||
+
|
||||
+ if (error) {
|
||||
+ self.callback(@[@{@"error": error.localizedFailureReason}]);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
[self.response setObject:videoDestinationURL.absoluteString forKey:@"uri"];
|
||||
if (videoRefURL.absoluteString) {
|
||||
[self.response setObject:videoRefURL.absoluteString forKey:@"origURL"];
|
||||
}
|
||||
-
|
||||
+
|
||||
NSDictionary *storageOptions = [self.options objectForKey:@"storageOptions"];
|
||||
if (storageOptions && [[storageOptions objectForKey:@"cameraRoll"] boolValue] == YES && self.picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
|
||||
+#if !TARGET_OS_MACCATALYST
|
||||
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
|
||||
[library writeVideoAtPathToSavedPhotosAlbum:videoDestinationURL completionBlock:^(NSURL *assetURL, NSError *error) {
|
||||
if (error) {
|
||||
@@ -509,22 +520,23 @@
|
||||
self.response[@"timestamp"] = [[ImagePickerManager ISO8601DateFormatter] stringFromDate:capturedAsset.creationDate];
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
self.callback(@[self.response]);
|
||||
}
|
||||
}
|
||||
}];
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
// If storage options are provided, check the skipBackup flag
|
||||
if ([self.options objectForKey:@"storageOptions"] && [[self.options objectForKey:@"storageOptions"] isKindOfClass:[NSDictionary class]]) {
|
||||
NSDictionary *storageOptions = [self.options objectForKey:@"storageOptions"];
|
||||
-
|
||||
+
|
||||
if ([[storageOptions objectForKey:@"skipBackup"] boolValue]) {
|
||||
[self addSkipBackupAttributeToItemAtPath:path]; // Don't back up the file to iCloud
|
||||
}
|
||||
-
|
||||
+
|
||||
if ([[storageOptions objectForKey:@"waitUntilSaved"] boolValue] == NO ||
|
||||
[[storageOptions objectForKey:@"cameraRoll"] boolValue] == NO ||
|
||||
self.picker.sourceType != UIImagePickerControllerSourceTypeCamera)
|
||||
@@ -536,7 +548,7 @@
|
||||
self.callback(@[self.response]);
|
||||
}
|
||||
};
|
||||
-
|
||||
+
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[picker dismissViewControllerAnimated:YES completion:dismissCompletionBlock];
|
||||
});
|
||||
@@ -595,12 +607,12 @@
|
||||
- (UIImage*)downscaleImageIfNecessary:(UIImage*)image maxWidth:(float)maxWidth maxHeight:(float)maxHeight
|
||||
{
|
||||
UIImage* newImage = image;
|
||||
-
|
||||
+
|
||||
// Nothing to do here
|
||||
if (image.size.width <= maxWidth && image.size.height <= maxHeight) {
|
||||
return newImage;
|
||||
}
|
||||
-
|
||||
+
|
||||
CGSize scaledSize = CGSizeMake(image.size.width, image.size.height);
|
||||
if (maxWidth < scaledSize.width) {
|
||||
scaledSize = CGSizeMake(maxWidth, (maxWidth / scaledSize.width) * scaledSize.height);
|
||||
@@ -608,11 +620,11 @@
|
||||
if (maxHeight < scaledSize.height) {
|
||||
scaledSize = CGSizeMake((maxHeight / scaledSize.height) * scaledSize.width, maxHeight);
|
||||
}
|
||||
-
|
||||
+
|
||||
// If the pixels are floats, it causes a white line in iOS8 and probably other versions too
|
||||
scaledSize.width = (int)scaledSize.width;
|
||||
scaledSize.height = (int)scaledSize.height;
|
||||
-
|
||||
+
|
||||
UIGraphicsBeginImageContext(scaledSize); // this will resize
|
||||
[image drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
|
||||
newImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
@@ -620,7 +632,7 @@
|
||||
NSLog(@"could not scale image");
|
||||
}
|
||||
UIGraphicsEndImageContext();
|
||||
-
|
||||
+
|
||||
return newImage;
|
||||
}
|
||||
|
||||
@@ -628,7 +640,7 @@
|
||||
if (srcImg.imageOrientation == UIImageOrientationUp) {
|
||||
return srcImg;
|
||||
}
|
||||
-
|
||||
+
|
||||
CGAffineTransform transform = CGAffineTransformIdentity;
|
||||
switch (srcImg.imageOrientation) {
|
||||
case UIImageOrientationDown:
|
||||
@@ -636,13 +648,13 @@
|
||||
transform = CGAffineTransformTranslate(transform, srcImg.size.width, srcImg.size.height);
|
||||
transform = CGAffineTransformRotate(transform, M_PI);
|
||||
break;
|
||||
-
|
||||
+
|
||||
case UIImageOrientationLeft:
|
||||
case UIImageOrientationLeftMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, srcImg.size.width, 0);
|
||||
transform = CGAffineTransformRotate(transform, M_PI_2);
|
||||
break;
|
||||
-
|
||||
+
|
||||
case UIImageOrientationRight:
|
||||
case UIImageOrientationRightMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, 0, srcImg.size.height);
|
||||
@@ -652,14 +664,14 @@
|
||||
case UIImageOrientationUpMirrored:
|
||||
break;
|
||||
}
|
||||
-
|
||||
+
|
||||
switch (srcImg.imageOrientation) {
|
||||
case UIImageOrientationUpMirrored:
|
||||
case UIImageOrientationDownMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, srcImg.size.width, 0);
|
||||
transform = CGAffineTransformScale(transform, -1, 1);
|
||||
break;
|
||||
-
|
||||
+
|
||||
case UIImageOrientationLeftMirrored:
|
||||
case UIImageOrientationRightMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, srcImg.size.height, 0);
|
||||
@@ -671,7 +683,7 @@
|
||||
case UIImageOrientationRight:
|
||||
break;
|
||||
}
|
||||
-
|
||||
+
|
||||
CGContextRef ctx = CGBitmapContextCreate(NULL, srcImg.size.width, srcImg.size.height, CGImageGetBitsPerComponent(srcImg.CGImage), 0, CGImageGetColorSpace(srcImg.CGImage), CGImageGetBitmapInfo(srcImg.CGImage));
|
||||
CGContextConcatCTM(ctx, transform);
|
||||
switch (srcImg.imageOrientation) {
|
||||
@@ -681,12 +693,12 @@
|
||||
case UIImageOrientationRightMirrored:
|
||||
CGContextDrawImage(ctx, CGRectMake(0,0,srcImg.size.height,srcImg.size.width), srcImg.CGImage);
|
||||
break;
|
||||
-
|
||||
+
|
||||
default:
|
||||
CGContextDrawImage(ctx, CGRectMake(0,0,srcImg.size.width,srcImg.size.height), srcImg.CGImage);
|
||||
break;
|
||||
}
|
||||
-
|
||||
+
|
||||
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
|
||||
UIImage *img = [UIImage imageWithCGImage:cgimg];
|
||||
CGContextRelease(ctx);
|
||||
@@ -701,7 +713,7 @@
|
||||
NSError *error = nil;
|
||||
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
|
||||
forKey: NSURLIsExcludedFromBackupKey error: &error];
|
||||
-
|
||||
+
|
||||
if(!success){
|
||||
NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
|
||||
}
|
@ -15,16 +15,12 @@ cd node_modules/react-native-camera/ios/RCT
|
||||
patch RCTCameraManager.m ../../../../scripts/maccatalystpatches/RCTCameraManager.patch --no-backup-if-mismatch
|
||||
cd ../RN/
|
||||
patch RNCamera.m ../../../../scripts/maccatalystpatches/RNCamera.patch
|
||||
echo "Applying patch for react-native-image-picker"
|
||||
cd ../../../../
|
||||
cd node_modules/react-native-image-picker/ios
|
||||
patch ImagePickerManager.m ../../../scripts/maccatalystpatches/ImagePickerManager.patch --no-backup-if-mismatch
|
||||
echo "Applying patch for Podfile"
|
||||
cd ../../../
|
||||
cd ../../../../
|
||||
patch ios/Podfile ./scripts/maccatalystpatches/podfile.patch --no-backup-if-mismatch
|
||||
echo "Applying patch for Realm podspec"
|
||||
patch node_modules/realm/RealmJS.podspec ./scripts/maccatalystpatches/realm.patch --no-backup-if-mismatch
|
||||
cd ios
|
||||
pod update
|
||||
echo ""
|
||||
echo "You should now be able to compile BlueWallet using Mac Catalyst on XCode. Enable Mac under Deployment Info by using XCode. If you are running macOS Catalina, you will need to remove the iOS 14 Widgets from the project targets."
|
||||
echo "You should now be able to compile BlueWallet using Mac Catalyst on XCode. Enable Mac under Deployment Info by using XCode. If you are running macOS Catalina, you will need to remove the iOS 14 Widgets from the project targets."
|
||||
|
@ -32,13 +32,6 @@ jest.mock('react-native-quick-actions', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('react-native-image-picker', () => {
|
||||
return {
|
||||
launchCamera: jest.fn(),
|
||||
launchImageLibrary: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('react-native-default-preference', () => {
|
||||
return {
|
||||
setName: jest.fn(),
|
||||
|
Loading…
Reference in New Issue
Block a user