Skip to content

Commit

Permalink
Merge branch 'master' into p
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosrdz committed Oct 26, 2024
2 parents 8efb60d + 2e22804 commit e7ac556
Show file tree
Hide file tree
Showing 50 changed files with 333 additions and 136 deletions.
11 changes: 11 additions & 0 deletions android/.project
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1729710829465</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
11 changes: 11 additions & 0 deletions android/app/.project
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,15 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1729710829486</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
11 changes: 10 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,16 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" android:mimeType="application/octet-stream" android:pathPattern=".*\\.psbt" />
</intent-filter>


<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" android:mimeType="image/jpeg" />
<data android:scheme="file" android:mimeType="image/png" />
<data android:scheme="file" android:mimeType="image/jpg" />
</intent-filter>

<!-- Intent filter for other custom schemes (bitcoin, bluewallet, etc.) -->
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
Expand Down
38 changes: 24 additions & 14 deletions blue_modules/fs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import LocalQRCode from '@remobile/react-native-qrcode-local-image';
import { Alert, Linking, Platform } from 'react-native';
import DocumentPicker from 'react-native-document-picker';
import RNFS from 'react-native-fs';
Expand All @@ -9,6 +8,7 @@ import presentAlert from '../components/Alert';
import loc from '../loc';
import { isDesktop } from './environment';
import { readFile } from './react-native-bw-file-access';
import RNQRGenerator from 'rn-qr-generator';

const _sanitizeFileName = (fileName: string) => {
// Remove any path delimiters and non-alphanumeric characters except for -, _, and .
Expand Down Expand Up @@ -128,14 +128,18 @@ export const showImagePickerAndReadImage = (): Promise<string | undefined> => {
if (!response.didCancel) {
const asset = response.assets?.[0] ?? {};
if (asset.uri) {
const uri = asset.uri.toString().replace('file://', '');
LocalQRCode.decode(uri, (error: any, result: string) => {
if (!error) {
resolve(result);
} else {
RNQRGenerator.detect({
uri: decodeURI(asset.uri.toString()),
})
.then(result => {
if (result) {
resolve(result.values[0]);
}
})
.catch(error => {
console.error(error);
reject(new Error(loc.send.qr_error_no_qrcode));
}
});
});
}
}
},
Expand Down Expand Up @@ -183,13 +187,19 @@ export const showFilePickerAndReadFile = async function (): Promise<{ data: stri
return;
}
const uri2 = res.fileCopyUri.replace('file://', '');
LocalQRCode.decode(decodeURI(uri2), (error: any, result: string) => {
if (!error) {
resolve({ data: result, uri: fileCopyUri });
} else {

RNQRGenerator.detect({
uri: decodeURI(uri2),
})
.then(result => {
if (result) {
resolve({ data: result.values[0], uri: fileCopyUri });
}
})
.catch(error => {
console.error(error);
resolve({ data: false, uri: false });
}
});
});
});
}

Expand Down
52 changes: 41 additions & 11 deletions blue_modules/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,24 +190,54 @@ function Notifications(props) {
* @returns {Promise<object>} Response object from API rest call
*/
Notifications.majorTomToGroundControl = async function (addresses, hashes, txids) {
if (!Array.isArray(addresses) || !Array.isArray(hashes) || !Array.isArray(txids))
throw new Error('no addresses or hashes or txids provided');
const pushToken = await Notifications.getPushToken();
if (!pushToken || !pushToken.token || !pushToken.os) return;
try {
if (!Array.isArray(addresses) || !Array.isArray(hashes) || !Array.isArray(txids)) {
throw new Error('No addresses, hashes, or txids provided');
}

const response = await fetch(`${baseURI}/majorTomToGroundControl`, {
method: 'POST',
headers: _getHeaders(),
body: JSON.stringify({
const pushToken = await Notifications.getPushToken();
if (!pushToken || !pushToken.token || !pushToken.os) {
return;
}

const requestBody = JSON.stringify({
addresses,
hashes,
txids,
token: pushToken.token,
os: pushToken.os,
}),
});
});

return response.json();
let response;
try {
response = await fetch(`${baseURI}/majorTomToGroundControl`, {
method: 'POST',
headers: _getHeaders(),
body: requestBody,
});
} catch (networkError) {
console.error('Network request failed:', networkError);
throw networkError;
}

if (!response.ok) {
return;
}

const responseText = await response.text();
if (responseText) {
try {
return JSON.parse(responseText);
} catch (jsonError) {
console.error('Error parsing response JSON:', jsonError);
throw jsonError;
}
} else {
return {}; // Return an empty object if there is no response body
}
} catch (error) {
console.error('Error in majorTomToGroundControl:', error);
}
};

/**
Expand Down
54 changes: 43 additions & 11 deletions components/AddressInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { scanQrHelper } from '../helpers/scan-qr';
import loc from '../loc';
import presentAlert from './Alert';
import ToolTipMenu from './TooltipMenu';
import { showFilePickerAndReadFile, showImagePickerAndReadImage } from '../blue_modules/fs';
import { CommonToolTipActions } from '../typings/CommonToolTipActions';
import Clipboard from '@react-native-clipboard/clipboard';
import RNQRGenerator from 'rn-qr-generator';
import { showFilePickerAndReadFile, showImagePickerAndReadImage } from '../blue_modules/fs';
import { useTheme } from './themes';

interface AddressInputProps {
Expand Down Expand Up @@ -76,7 +78,7 @@ const AddressInput = ({
}, [launchedBy, onBarScanned, scanButtonTapped]);

const onMenuItemPressed = useCallback(
(action: string) => {
async (action: string) => {
if (onBarScanned === undefined) throw new Error('onBarScanned is required');
switch (action) {
case actionKeys.ScanQR:
Expand All @@ -90,12 +92,42 @@ const AddressInput = ({
}

break;
case actionKeys.CopyFromClipboard:
Clipboard.getString()
.then(onChangeText)
.catch(error => {
presentAlert({ message: error.message });
});
case CommonToolTipActions.PasteFromClipboard.id:
try {
let getImage: string | null = null;

if (Platform.OS === 'android') {
getImage = await Clipboard.getImage();
} else {
const hasImage = await Clipboard.hasImage();
if (hasImage) {
getImage = await Clipboard.getImageJPG();
}
}

if (getImage) {
try {
const base64Data = getImage.replace(/^data:image\/jpeg;base64,/, '');

const values = await RNQRGenerator.detect({
base64: base64Data,
});

if (values && values.values.length > 0) {
onChangeText(values.values[0]);
} else {
presentAlert({ message: loc.send.qr_error_no_qrcode });
}
} catch (error) {
presentAlert({ message: (error as Error).message });
}
} else {
const clipboardText = await Clipboard.getString();
onChangeText(clipboardText);
}
} catch (error) {
presentAlert({ message: (error as Error).message });
}
break;
case actionKeys.ChoosePhoto:
showImagePickerAndReadImage()
Expand Down Expand Up @@ -202,7 +234,7 @@ const styles = StyleSheet.create({

const actionKeys = {
ScanQR: 'scan_qr',
CopyFromClipboard: 'copy_from_clipboard',
PasteFromClipboard: 'copy_from_clipboard',
ChoosePhoto: 'choose_photo',
ImportFile: 'import_file',
};
Expand All @@ -229,8 +261,8 @@ const actions = [
icon: actionIcons.ScanQR,
},
{
id: actionKeys.CopyFromClipboard,
text: loc.wallets.list_long_clipboard,
id: actionKeys.PasteFromClipboard,
text: loc.wallets.paste_from_clipboard,
icon: actionIcons.Clipboard,
},
{
Expand Down
54 changes: 45 additions & 9 deletions components/CompanionDelegates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { Chain } from '../models/bitcoinUnits';
import { navigationRef } from '../NavigationService';
import ActionSheet from '../screen/ActionSheet';
import { useStorage } from '../hooks/context/useStorage';
import RNQRGenerator from 'rn-qr-generator';
import presentAlert from './Alert';

const MenuElements = lazy(() => import('../components/MenuElements'));
const DeviceQuickActions = lazy(() => import('../components/DeviceQuickActions'));
Expand Down Expand Up @@ -104,17 +106,51 @@ const CompanionDelegates = () => {
}, [fetchAndSaveWalletTransactions, refreshAllWalletTransactions, wallets]);

const handleOpenURL = useCallback(
(event: { url: string }) => {
DeeplinkSchemaMatch.navigationRouteFor(event, value => navigationRef.navigate(...value), {
wallets,
addWallet,
saveToDisk,
setSharedCosigner,
});
async (event: { url: string }): Promise<void> => {
const { url } = event;

if (url) {
const decodedUrl = decodeURIComponent(url);
const fileName = decodedUrl.split('/').pop()?.toLowerCase();

if (fileName && /\.(jpe?g|png)$/i.test(fileName)) {
try {
const values = await RNQRGenerator.detect({
uri: decodedUrl,
});

if (values && values.values.length > 0) {
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
DeeplinkSchemaMatch.navigationRouteFor(
{ url: values.values[0] },
(value: [string, any]) => navigationRef.navigate(...value),
{
wallets,
addWallet,
saveToDisk,
setSharedCosigner,
},
);
} else {
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
presentAlert({ message: loc.send.qr_error_no_qrcode });
}
} catch (error) {
console.error('Error detecting QR code:', error);
}
}
} else {
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
DeeplinkSchemaMatch.navigationRouteFor(event, (value: [string, any]) => navigationRef.navigate(...value), {
wallets,
addWallet,
saveToDisk,
setSharedCosigner,
});
}
},
[addWallet, saveToDisk, setSharedCosigner, wallets],
[wallets, addWallet, saveToDisk, setSharedCosigner],
);

const showClipboardAlert = useCallback(
({ contentType }: { contentType: undefined | string }) => {
triggerHapticFeedback(HapticFeedbackTypes.ImpactLight);
Expand Down
24 changes: 21 additions & 3 deletions ios/BlueWallet/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@
<string>io.bluewallet.psbt</string>
</array>
</dict>
<!-- Image file types -->
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>Image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.jpeg</string>
<string>public.image</string>
</array>
</dict>
<!-- TXN file type -->
<dict>
<key>CFBundleTypeIconFiles</key>
Expand Down Expand Up @@ -158,7 +174,7 @@
</dict>
</dict>
<key>NSCameraUsageDescription</key>
<string>In order to quickly scan the recipient&apos;s address, we need your permission to use the camera to scan their QR Code.</string>
<string>In order to quickly scan the recipient's address, we need your permission to use the camera to scan their QR Code.</string>
<key>NSFaceIDUsageDescription</key>
<string>In order to use FaceID please confirm your permission.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
Expand Down Expand Up @@ -209,7 +225,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

<!-- Define exported types (UTIs) for file types -->
<key>UTExportedTypeDeclarations</key>
<array>
Expand Down Expand Up @@ -306,6 +322,8 @@
<string>application/json</string>
</array>
</dict>
<key>LSHandlerRank</key>
<string>Alternate</string>
</dict>
</array>

Expand All @@ -320,4 +338,4 @@
<key>FIREBASE_MESSAGING_AUTO_INIT_ENABLED</key>
<false/>
</dict>
</plist>
</plist>
Loading

0 comments on commit e7ac556

Please sign in to comment.