Skip to content

Commit

Permalink
REF: Haptic feedback into a class with power state verification (#5954)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosrdz committed Dec 29, 2023
1 parent 89ce917 commit a08117a
Show file tree
Hide file tree
Showing 29 changed files with 129 additions and 110 deletions.
4 changes: 2 additions & 2 deletions App.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
} from 'react-native';
import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { navigationRef } from './NavigationService';
import * as NavigationService from './NavigationService';
import { Chain } from './models/bitcoinUnits';
Expand All @@ -32,6 +31,7 @@ import WidgetCommunication from './blue_modules/WidgetCommunication';
import ActionSheet from './screen/ActionSheet';
import HandoffComponent from './components/handoff';
import Privacy from './blue_modules/Privacy';
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
const A = require('./blue_modules/analytics');
const currency = require('./blue_modules/currency');

Expand Down Expand Up @@ -260,7 +260,7 @@ const App = () => {
};

const showClipboardAlert = ({ contentType }) => {
ReactNativeHapticFeedback.trigger('impactLight', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.ImpactLight);
BlueClipboard()
.getClipboardContent()
.then(clipboard => {
Expand Down
5 changes: 3 additions & 2 deletions UnlockWith.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import LottieView from 'lottie-react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StackActions, useNavigation, useRoute } from '@react-navigation/native';
import { BlueStorageContext } from './blue_modules/storage-context';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { isHandset } from './blue_modules/environment';
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
const lottieJson = require('./img/bluewalletsplash.json');

const styles = StyleSheet.create({
Expand Down Expand Up @@ -86,7 +86,8 @@ const UnlockWith = () => {
const unlockWithKey = async () => {
setIsAuthenticating(true);
if (await startAndDecrypt()) {
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);

successfullyAuthenticated();
} else {
setIsAuthenticating(false);
Expand Down
25 changes: 25 additions & 0 deletions blue_modules/hapticFeedback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import DeviceInfo, { PowerState } from 'react-native-device-info';

// Define a const enum for HapticFeedbackTypes
export const enum HapticFeedbackTypes {
ImpactLight = 'impactLight',
ImpactMedium = 'impactMedium',
ImpactHeavy = 'impactHeavy',
Selection = 'selection',
NotificationSuccess = 'notificationSuccess',
NotificationWarning = 'notificationWarning',
NotificationError = 'notificationError',
}

const triggerHapticFeedback = (type: HapticFeedbackTypes) => {
DeviceInfo.getPowerState().then((state: Partial<PowerState>) => {
if (!state.lowPowerMode) {
ReactNativeHapticFeedback.trigger(type, { ignoreAndroidSystemSettings: false, enableVibrateFallback: true });
} else {
console.log('Haptic feedback not triggered due to low power mode.');
}
});
};

export default triggerHapticFeedback;
6 changes: 3 additions & 3 deletions blue_modules/storage-context.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { createContext, useEffect, useState } from 'react';
import { Alert } from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
import { FiatUnit } from '../models/fiatUnit';
import Notifications from '../blue_modules/notifications';
import loc, { STORAGE_KEY as LOC_STORAGE_KEY } from '../loc';
import { LegacyWallet, WatchOnlyWallet } from '../class';
import alert from '../components/Alert';
import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback';
const BlueApp = require('../BlueApp');
const BlueElectrum = require('./BlueElectrum');
const currency = require('../blue_modules/currency');
Expand Down Expand Up @@ -177,12 +177,12 @@ export const BlueStorageProvider = ({ children }) => {

const addAndSaveWallet = async w => {
if (wallets.some(i => i.getID() === w.getID())) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
Alert.alert('', 'This wallet has been previously imported.');
return;
}
const emptyWalletLabel = new LegacyWallet().getLabel();
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
if (w.getLabel() === emptyWalletLabel) w.setLabel(loc.wallets.import_imported + ' ' + w.typeReadable);
w.setUserHasSavedExport(true);
addWallet(w);
Expand Down
4 changes: 2 additions & 2 deletions class/payjoin-transaction.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as bitcoin from 'bitcoinjs-lib';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import alert from '../components/Alert';
import { ECPairFactory } from 'ecpair';
import ecc from '../blue_modules/noble_ecc';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../blue_modules/hapticFeedback';
const ECPair = ECPairFactory(ecc);

const delay = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
Expand Down Expand Up @@ -74,7 +74,7 @@ export default class PayjoinTransaction {
const result = await this.broadcastTx(txHex);
if (result === '') {
// TODO: Improve the wording of this error message
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
alert('Something was wrong with the payjoin transaction, the original transaction sucessfully broadcast.');
}
});
Expand Down
18 changes: 9 additions & 9 deletions screen/lnd/ldkOpenChannel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import AddressInput from '../../components/AddressInput';
import AmountInput from '../../components/AmountInput';
import { BitcoinUnit } from '../../models/bitcoinUnits';
import loc from '../../loc';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { AbstractWallet, HDSegwitBech32Wallet, LightningLdkWallet } from '../../class';
import { ArrowPicker } from '../../components/ArrowPicker';
import { Psbt } from 'bitcoinjs-lib';
import Biometric from '../../class/biometrics';
import alert from '../../components/Alert';
import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
const currency = require('../../blue_modules/currency');

type LdkOpenChannelProps = RouteProp<
Expand Down Expand Up @@ -67,7 +67,7 @@ const LdkOpenChannel = (props: any) => {
(async () => {
if (psbtOpenChannelStartedTs.current ? +new Date() - psbtOpenChannelStartedTs.current >= 5 * 60 * 1000 : false) {
// its 10 min actually, but lets check 5 min just for any case
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
return alert('Channel opening expired. Please try again');
}

Expand All @@ -93,7 +93,7 @@ const LdkOpenChannel = (props: any) => {
}
if (psbtOpenChannelStartedTs.current ? +new Date() - psbtOpenChannelStartedTs.current >= 5 * 60 * 1000 : false) {
// its 10 min actually, but lets check 5 min just for any case
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
setIsLoading(false);
return alert('Channel opening expired. Please try again');
}
Expand All @@ -102,14 +102,14 @@ const LdkOpenChannel = (props: any) => {
const res = await ldkWallet.fundingStateStepFinalize(tx.toHex()); // comment this out to debug
// const res = true; // debug
if (!res) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
setIsLoading(false);
return alert('Something wend wrong during opening channel tx broadcast');
}
fetchAndSaveWalletTransactions(ldkWallet.getID());
await new Promise(resolve => setTimeout(resolve, 3000)); // sleep to make sure network propagates
fetchAndSaveWalletTransactions(fundingWalletID);
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
// @ts-ignore: Address types later
navigate('Success', { amount: undefined });
setIsLoading(false);
Expand All @@ -120,14 +120,14 @@ const LdkOpenChannel = (props: any) => {
try {
const amountSatsNumber = new BigNumber(fundingAmount.amountSats).toNumber();
if (!amountSatsNumber) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
return alert('Amount is not valid');
}

const pubkey = remoteHostWithPubkey.split('@')[0];
const host = remoteHostWithPubkey.split('@')[1];
if (!pubkey || !host) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
return alert('Remote node address is not valid');
}

Expand All @@ -141,7 +141,7 @@ const LdkOpenChannel = (props: any) => {
if (event) {
reason += event.reason + ' ' + event.text;
}
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
return alert('Initiating channel open failed: ' + reason);
}

Expand All @@ -162,7 +162,7 @@ const LdkOpenChannel = (props: any) => {
},
});
} catch (error: any) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
alert(error.message);
} finally {
setIsLoading(false);
Expand Down
14 changes: 7 additions & 7 deletions screen/lnd/lndCreateInvoice.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
View,
I18nManager,
} from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Icon } from 'react-native-elements';
import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';

Expand All @@ -31,6 +30,7 @@ import { parse } from 'url'; // eslint-disable-line n/no-deprecated-api
import { requestCameraAuthorization } from '../../helpers/scan-qr';
import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
const currency = require('../../blue_modules/currency');

const LNDCreateInvoice = () => {
Expand Down Expand Up @@ -131,7 +131,7 @@ const LNDCreateInvoice = () => {
});
}
} else {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
alert(loc.wallets.add_ln_wallet_first);
goBack();
}
Expand Down Expand Up @@ -179,15 +179,15 @@ const LNDCreateInvoice = () => {
? loc.formatString(loc.receive.maxSats, { max })
: loc.formatString(loc.receive.maxSatsFull, { max, currency: formatBalance(max, unit) });
}
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
alert(text);
setIsLoading(false);
return;
}
}

const invoiceRequest = await wallet.current.addInvoice(invoiceAmount, description);
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);

// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
/** @type LightningCustodianWallet */
Expand Down Expand Up @@ -223,7 +223,7 @@ const LNDCreateInvoice = () => {
walletID: wallet.current.getID(),
});
} catch (Err) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
setIsLoading(false);
alert(Err.message);
}
Expand All @@ -232,7 +232,7 @@ const LNDCreateInvoice = () => {
const processLnurl = async data => {
setIsLoading(true);
if (!wallet.current) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
alert(loc.wallets.no_ln_wallet_error);
return goBack();
}
Expand Down Expand Up @@ -307,7 +307,7 @@ const LNDCreateInvoice = () => {
} catch (Err) {
Keyboard.dismiss();
setIsLoading(false);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
alert(Err.message);
}
};
Expand Down
6 changes: 3 additions & 3 deletions screen/lnd/lndViewInvoice.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useContext, useEffect, useRef, useState } from 'react';
import { View, Text, ScrollView, BackHandler, TouchableOpacity, StyleSheet, I18nManager, Image } from 'react-native';
import Share from 'react-native-share';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Icon } from 'react-native-elements';
import QRCodeComponent from '../../components/QRCodeComponent';
import { useNavigation, useNavigationState, useRoute } from '@react-navigation/native';
Expand All @@ -14,6 +13,7 @@ import { SuccessView } from '../send/success';
import LNDCreateInvoice from './lndCreateInvoice';
import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';

const LNDViewInvoice = () => {
const { invoice, walletID } = useRoute().params;
Expand Down Expand Up @@ -129,7 +129,7 @@ const LNDViewInvoice = () => {
// invoice expired :-(
fetchAndSaveWalletTransactions(walletID);
setIsFetchingInvoices(false);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
clearInterval(fetchInvoiceInterval.current);
fetchInvoiceInterval.current = undefined;
}
Expand Down Expand Up @@ -177,7 +177,7 @@ const LNDViewInvoice = () => {

useEffect(() => {
if (invoiceStatusChanged) {
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
}
}, [invoiceStatusChanged]);

Expand Down
6 changes: 3 additions & 3 deletions screen/lnd/lnurlPay.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState, useEffect, useContext } from 'react';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { I18nManager, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
Expand All @@ -16,6 +15,7 @@ import { BlueStorageContext } from '../../blue_modules/storage-context';
import alert from '../../components/Alert';
import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
const prompt = require('../../helpers/prompt');
const currency = require('../../blue_modules/currency');

Expand Down Expand Up @@ -143,7 +143,7 @@ const LnurlPay = () => {
setPayButtonDisabled(false);

// success, probably
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
if (wallet.last_paid_invoice_result && wallet.last_paid_invoice_result.payment_preimage) {
await LN.storeSuccess(decoded.payment_hash, wallet.last_paid_invoice_result.payment_preimage);
}
Expand All @@ -161,7 +161,7 @@ const LnurlPay = () => {
console.log(Err.message);
setIsLoading(false);
setPayButtonDisabled(false);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
return alert(Err.message);
}
};
Expand Down

0 comments on commit a08117a

Please sign in to comment.