Merge branch 'master' into privacymanifest

This commit is contained in:
Marcos Rodriguez Velez 2024-03-28 18:52:45 -04:00
commit 3fbf54939c
No known key found for this signature in database
GPG key ID: 6030B2F48CCE86D7
29 changed files with 246 additions and 431 deletions

View file

@ -79,7 +79,7 @@ jobs:
- name: Setup Provisioning Profiles
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_URL: ${{ secrets.GIT_URL }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}

View file

@ -1,14 +1,17 @@
name: Build Release Pull Request (iOS)
name: Build Release and Upload to TestFlight (iOS)
on:
push:
branches:
- master
pull_request:
types: [opened, reopened, synchronize, labeled, unlabeled]
types: [opened, reopened, synchronize, labeled]
branches:
- master
workflow_dispatch:
jobs:
build:
if: contains(github.event.pull_request.labels.*.name, 'testflight')
runs-on: macos-14
timeout-minutes: 180
outputs:
@ -22,171 +25,150 @@ jobs:
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetches all history
- name: Specify node version
uses: actions/setup-node@v2-beta
with:
node-version: 18
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.2
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install dependencies with Bundler
run: bundle install
- name: Install Fastlane 2.217.0
run: gem install fastlane -v 2.217.0
- name: Install CocoaPods
run: sudo gem install cocoapods
- name: Install Fastlane
run: gem install fastlane -v 2.217.0 # If a specific version is needed for PR or not specified, keep only one version
- name: Clear Derived Data
run: bundle exec fastlane ios clear_derived_data_lane
working-directory: ./ios
- name: Install node_modules
run: npm install
- name: Install CocoaPods Dependencies
run: |
sudo gem install cocoapods # Ensure CocoaPods is installed
bundle exec pod install
working-directory: ./ios
- name: Cache CocoaPods Pods
uses: actions/cache@v2
with:
path: ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
- name: Display release-notes.txt
run: cat release-notes.txt
- name: Get Latest Commit Message
id: get_latest_commit_message
run: |
LATEST_COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s")
echo "LATEST_COMMIT_MESSAGE=${LATEST_COMMIT_MESSAGE}" >> $GITHUB_ENV
echo "::set-output name=commit_message::$LATEST_COMMIT_MESSAGE"
- name: Set up Git Authentication
env:
ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
run: |
git config --global credential.helper 'cache --timeout=3600'
git config --global http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n x-access-token:${ACCESS_TOKEN} | base64)"
- name: Create Temporary Keychain
run: bundle exec fastlane ios create_temp_keychain
working-directory: ./ios
env:
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
- name: Setup Provisioning Profiles
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_URL: ${{ secrets.GIT_URL }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: bundle exec fastlane ios setup_provisioning_profiles
working-directory: ./ios
- name: Generate Build Number based on timestamp
id: generate_build_number
run: |
NEW_BUILD_NUMBER=$(date +%s)
echo "NEW_BUILD_NUMBER=$NEW_BUILD_NUMBER" >> $GITHUB_ENV
echo "::set-output name=build_number::$NEW_BUILD_NUMBER"
- name: Set Build Number
run: bundle exec fastlane ios increment_build_number_lane
working-directory: ./ios
- name: Determine Marketing Version
id: determine_marketing_version
run: |
MARKETING_VERSION=$(grep MARKETING_VERSION ios/BlueWallet.xcodeproj/project.pbxproj | awk -F '= ' '{print $2}' | tr -d ' ;' | head -1)
echo "PROJECT_VERSION=$MARKETING_VERSION" >> $GITHUB_ENV
echo "::set-output name=project_version::$MARKETING_VERSION"
- name: Expected IPA file name
run: |
echo "IPA file name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa"
- name: Install CocoaPods Dependencies
run: bundle exec fastlane ios install_pods
working-directory: ./ios
- name: Build App
run: bundle exec fastlane ios build_app_lane
working-directory: ./ios
- name: Upload IPA as Artifact
uses: actions/upload-artifact@v2
with:
name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa
path: ./ios/build/BlueWallet.${{env.PROJECT_VERSION}}(${{ env.NEW_BUILD_NUMBER }}).ipa
testflight-upload:
if: contains(github.event.pull_request.labels.*.name, 'testflight')
needs: build
runs-on: macos-14
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
NEW_BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
PROJECT_VERSION: ${{ needs.build.outputs.project_version }}
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
steps:
- name: Checkout project
uses: actions/checkout@v3
- name: Cache Ruby Gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-
- name: Install dependencies with Bundler
run: |
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
- name: Download IPA from Artifact
uses: actions/download-artifact@v2
with:
name: BlueWallet.${{needs.build.outputs.project_version}}(${{needs.build.outputs.new_build_number}}).ipa
path: ./ios/build
- name: Create App Store Connect API Key JSON
run: echo '${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}' > ./ios/appstore_api_key.json
- name: Upload to TestFlight
env:
APP_STORE_CONNECT_API_KEY_PATH: $(pwd)/ios/appstore_api_key.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_URL: ${{ secrets.GIT_URL }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: bundle exec fastlane ios upload_to_testflight_lane
working-directory: ./ios
- name: Post PR Comment
uses: actions/github-script@v6
if: success() # Ensures the message is only posted if previous steps succeed
env:
BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
with:
script: |
const buildNumber = process.env.BUILD_NUMBER;
const message = `The build ${buildNumber} has been uploaded to TestFlight.`;
const prNumber = context.payload.pull_request.number;
const repo = context.repo;
github.rest.issues.createComment({
...repo,
issue_number: prNumber,
body: message,
});
needs: build
runs-on: macos-14
if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'testflight')
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
NEW_BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
PROJECT_VERSION: ${{ needs.build.outputs.project_version }}
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
steps:
- name: Checkout project
uses: actions/checkout@v3
- name: Cache Ruby Gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-
- name: Install dependencies with Bundler
run: |
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
- name: Download IPA from Artifact
uses: actions/download-artifact@v2
with:
name: BlueWallet.${{needs.build.outputs.project_version}}(${{needs.build.outputs.new_build_number}}).ipa
path: ./ios/build
- name: Create App Store Connect API Key JSON
run: echo '${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}' > ./ios/appstore_api_key.json
- name: Upload to TestFlight
env:
APP_STORE_CONNECT_API_KEY_PATH: $(pwd)/ios/appstore_api_key.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
GIT_ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_URL: ${{ secrets.GIT_URL }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: bundle exec fastlane ios upload_to_testflight_lane
working-directory: ./ios
- name: Post PR Comment
if: success() && github.event_name == 'pull_request'
uses: actions/github-script@v6
env:
BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
with:
script: |
const buildNumber = process.env.BUILD_NUMBER;
const message = `The build ${buildNumber} has been uploaded to TestFlight.`;
const prNumber = context.payload.pull_request.number;
const repo = context.repo;
github.rest.issues.createComment({
...repo,
issue_number: prNumber,
body: message,
});

View file

@ -1,180 +0,0 @@
name: Build Release and Upload to TestFlight (iOS)
on:
push:
branches:
- master
jobs:
build:
runs-on: macos-14
timeout-minutes: 180
outputs:
new_build_number: ${{ steps.generate_build_number.outputs.build_number }}
project_version: ${{ steps.determine_marketing_version.outputs.project_version }}
latest_commit_message: ${{ steps.get_latest_commit_message.outputs.commit_message }}
env:
APPLE_ID: ${{ secrets.APPLE_ID }} # Setting the environment variable
steps:
- name: Checkout project
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetches all history
- name: Specify node version
uses: actions/setup-node@v2-beta
with:
node-version: 18
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 15.2
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install dependencies with Bundler
run: bundle install
- name: Install Fastlane
run: gem install fastlane
- name: Clear Derived Data
run: bundle exec fastlane ios clear_derived_data_lane
working-directory: ./ios
- name: Install node_modules
run: npm install
- name: Install CocoaPods Dependencies
run: bundle exec pod install
working-directory: ./ios
- name: Cache CocoaPods Pods
uses: actions/cache@v2
with:
path: ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
- name: Display release-notes.txt
run: cat release-notes.txt
- name: Get Latest Commit Message
id: get_latest_commit_message
run: |
LATEST_COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s")
echo "LATEST_COMMIT_MESSAGE=${LATEST_COMMIT_MESSAGE}" >> $GITHUB_ENV
echo "::set-output name=commit_message::$LATEST_COMMIT_MESSAGE"
- name: Set up Git Authentication
env:
ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
run: |
git config --global credential.helper 'cache --timeout=3600'
git config --global http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n x-access-token:${ACCESS_TOKEN} | base64)"
- name: Create Temporary Keychain
run: bundle exec fastlane ios create_temp_keychain
working-directory: ./ios
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
- name: Setup Provisioning Profiles
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_URL: ${{ secrets.GIT_URL }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: bundle exec fastlane ios setup_provisioning_profiles
working-directory: ./ios
- name: Generate Build Number based on timestamp
id: generate_build_number
run: |
NEW_BUILD_NUMBER=$(date +%s)
echo "NEW_BUILD_NUMBER=$NEW_BUILD_NUMBER" >> $GITHUB_ENV
echo "::set-output name=build_number::$NEW_BUILD_NUMBER"
- name: Set Build Number
run: bundle exec fastlane ios increment_build_number_lane
working-directory: ./ios
- name: Determine Marketing Version
id: determine_marketing_version
run: |
MARKETING_VERSION=$(grep MARKETING_VERSION ios/BlueWallet.xcodeproj/project.pbxproj | awk -F '= ' '{print $2}' | tr -d ' ;' | head -1)
echo "PROJECT_VERSION=$MARKETING_VERSION" >> $GITHUB_ENV
echo "::set-output name=project_version::$MARKETING_VERSION"
- name: Expected IPA file name
run: |
echo "IPA file name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa"
- name: Build App
run: bundle exec fastlane ios build_app_lane
working-directory: ./ios
- name: Upload IPA as Artifact
uses: actions/upload-artifact@v2
with:
name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa
path: ./ios/build/BlueWallet.${{env.PROJECT_VERSION}}(${{ env.NEW_BUILD_NUMBER }}).ipa
testflight-upload:
needs: build
runs-on: macos-14
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
NEW_BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
PROJECT_VERSION: ${{ needs.build.outputs.project_version }}
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
steps:
- name: Checkout project
uses: actions/checkout@v3
- name: Cache CocoaPods Pods
uses: actions/cache@v2
with:
path: ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
- name: Cache Ruby Gems
uses: actions/cache@v2
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-
- name: Install dependencies with Bundler
run: |
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
- name: Download IPA from Artifact
uses: actions/download-artifact@v2
with:
name: BlueWallet.${{needs.build.outputs.project_version}}(${{needs.build.outputs.new_build_number}}).ipa
path: ./ios/build
- name: Create App Store Connect API Key JSON
run: echo '${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}' > ./ios/appstore_api_key.json
- name: Upload to TestFlight
env:
APP_STORE_CONNECT_API_KEY_PATH: $(pwd)/ios/appstore_api_key.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.GIT_ACCESS_TOKEN }}
GIT_URL: ${{ secrets.GIT_URL }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: bundle exec fastlane ios upload_to_testflight_lane
working-directory: ./ios

View file

@ -863,7 +863,7 @@ export class AppStorage {
if (doNotTrackValue) {
await DefaultPreference.set(AppStorage.DO_NOT_TRACK, '1');
AsyncStorage.removeItem(AppStorage.DO_NOT_TRACK);
}
}
} catch (_) {}
return false;
};

View file

@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import { Icon, Text, Header } from 'react-native-elements';
import {
ActivityIndicator,
Animated,
Dimensions,
Image,
InputAccessoryView,
@ -204,80 +203,6 @@ export const BluePrivateBalance = () => {
);
};
export const BlueCopyToClipboardButton = ({ stringToCopy, displayText = false }) => {
return (
<TouchableOpacity accessibilityRole="button" onPress={() => Clipboard.setString(stringToCopy)}>
<Text style={{ fontSize: 13, fontWeight: '400', color: '#68bbe1' }}>{displayText || loc.transactions.details_copy}</Text>
</TouchableOpacity>
);
};
export class BlueCopyTextToClipboard extends Component {
static propTypes = {
text: PropTypes.string,
truncated: PropTypes.bool,
};
static defaultProps = {
text: '',
truncated: false,
};
constructor(props) {
super(props);
this.state = { hasTappedText: false, address: props.text };
}
static getDerivedStateFromProps(props, state) {
if (state.hasTappedText) {
return { hasTappedText: state.hasTappedText, address: state.address, truncated: props.truncated };
} else {
return { hasTappedText: state.hasTappedText, address: props.text, truncated: props.truncated };
}
}
copyToClipboard = () => {
this.setState({ hasTappedText: true }, () => {
Clipboard.setString(this.props.text);
this.setState({ address: loc.wallets.xpub_copiedToClipboard }, () => {
setTimeout(() => {
this.setState({ hasTappedText: false, address: this.props.text });
}, 1000);
});
});
};
render() {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', paddingHorizontal: 16 }}>
<TouchableOpacity
accessibilityRole="button"
onPress={this.copyToClipboard}
disabled={this.state.hasTappedText}
testID="BlueCopyTextToClipboard"
>
<Animated.Text
style={styleCopyTextToClipboard.address}
{...(this.props.truncated ? { numberOfLines: 1, ellipsizeMode: 'middle' } : { numberOfLines: 0 })}
testID="AddressValue"
>
{this.state.address}
</Animated.Text>
</TouchableOpacity>
</View>
);
}
}
const styleCopyTextToClipboard = StyleSheet.create({
address: {
marginVertical: 32,
fontSize: 15,
color: '#9aa0aa',
textAlign: 'center',
},
});
export const BlueCard = props => {
return <View {...props} style={{ padding: 20 }} />;
};

View file

@ -639,7 +639,7 @@ const Navigation = () => {
/>
<RootStack.Screen name="PaymentCodeRoot" component={PaymentCodeStackRoot} options={NavigationDefaultOptions} />
<InitStack.Screen
<RootStack.Screen
name="ReorderWallets"
component={ReorderWalletsStackRoot}
options={{

View file

@ -1,4 +1,4 @@
import React from 'react';
import React, { forwardRef } from 'react';
import { TouchableOpacity, View, Text, StyleSheet, StyleProp, ViewStyle } from 'react-native';
import { Icon } from 'react-native-elements';
import { useTheme } from './themes';
@ -19,7 +19,7 @@ interface ButtonProps {
onPress?: () => void;
}
export const Button: React.FC<ButtonProps> = props => {
export const Button = forwardRef<TouchableOpacity, ButtonProps>((props, ref) => {
const { colors } = useTheme();
let backgroundColor = props.backgroundColor ?? colors.mainColor;
@ -42,6 +42,7 @@ export const Button: React.FC<ButtonProps> = props => {
return (
<TouchableOpacity
ref={ref}
testID={props.testID}
style={[buttonStyle, props.style]}
accessibilityRole="button"
@ -54,7 +55,7 @@ export const Button: React.FC<ButtonProps> = props => {
</View>
</TouchableOpacity>
);
};
});
const styles = StyleSheet.create({
button: {

View file

@ -0,0 +1,65 @@
import Clipboard from '@react-native-clipboard/clipboard';
import React, { useState, useEffect, forwardRef } from 'react';
import { View, TouchableOpacity, Animated, StyleSheet } from 'react-native';
import loc from '../loc';
type CopyTextToClipboardProps = {
text: string;
truncated?: boolean;
};
const styleCopyTextToClipboard = StyleSheet.create({
address: {
marginVertical: 32,
fontSize: 15,
color: '#9aa0aa',
textAlign: 'center',
},
});
const CopyTextToClipboard = forwardRef<TouchableOpacity, CopyTextToClipboardProps>(({ text, truncated }, ref) => {
const [hasTappedText, setHasTappedText] = useState(false);
const [address, setAddress] = useState(text);
useEffect(() => {
if (!hasTappedText) {
setAddress(text);
}
}, [text, hasTappedText]);
const copyToClipboard = () => {
setHasTappedText(true);
Clipboard.setString(text);
setAddress(loc.wallets.xpub_copiedToClipboard); // Adjust according to your localization logic
setTimeout(() => {
setHasTappedText(false);
setAddress(text);
}, 1000);
};
return (
<View style={styles.container}>
<TouchableOpacity
ref={ref}
accessibilityRole="button"
onPress={copyToClipboard}
disabled={hasTappedText}
testID="CopyTextToClipboard"
>
<Animated.Text
style={styleCopyTextToClipboard.address}
{...(truncated ? { numberOfLines: 1, ellipsizeMode: 'middle' } : { numberOfLines: 0 })}
testID="AddressValue"
>
{address}
</Animated.Text>
</TouchableOpacity>
</View>
);
});
export default CopyTextToClipboard;
const styles = StyleSheet.create({
container: { justifyContent: 'center', alignItems: 'center', paddingHorizontal: 16 },
});

View file

@ -0,0 +1,27 @@
import Clipboard from '@react-native-clipboard/clipboard';
import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
import loc from '../loc';
type CopyToClipboardButtonProps = {
stringToCopy: string;
displayText?: string;
};
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({ stringToCopy, displayText }) => {
const onPress = () => {
Clipboard.setString(stringToCopy);
};
return (
<TouchableOpacity accessibilityRole="button" onPress={onPress}>
<Text style={styles.text}>{displayText && displayText.length > 0 ? displayText : loc.transactions.details_copy}</Text>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
text: { fontSize: 13, fontWeight: '400', color: '#68bbe1' },
});
export default CopyToClipboardButton;

View file

@ -29,5 +29,5 @@
}
}
],
"version" : 3
"version" : 2
}

View file

@ -66,7 +66,7 @@ platform :ios do
platform = options[:platform] || "ios" # Default to iOS if not specified
target_to_app_identifier.each do |target, app_identifier|
match(
git_basic_authorization: ENV["MATCH_GIT_BASIC_AUTHORIZATION"],
git_basic_authorization: ENV["GIT_ACCESS_TOKEN"],
git_url: ENV["GIT_URL"],
type: "appstore",
platform: platform,

View file

@ -402,7 +402,7 @@
"details_delete": "Delete",
"details_delete_wallet": "Delete Wallet",
"details_derivation_path": "derivation path",
"details_display": "Display in Wallets List",
"details_display": "Display in Home Screen",
"details_export_backup": "Export/Backup",
"details_export_history": "Export History to CSV",
"details_master_fingerprint": "Master Fingerprint",

View file

@ -154,7 +154,7 @@
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4",
"react-native-elements": "3.4.3",
"react-native-fs": "2.20.0",
"react-native-gesture-handler": "2.15.0",
"react-native-gesture-handler": "2.16.0",
"react-native-handoff": "https://github.com/BlueWallet/react-native-handoff#31d005f93d31099d0e564590a3bbd052b8a02b39",
"react-native-haptic-feedback": "2.2.0",
"react-native-idle-timer": "https://github.com/BlueWallet/react-native-idle-timer#8587876d68ab5920e79619726aeca9e672beaf2b",
@ -183,7 +183,7 @@
"react-native-tcp-socket": "6.0.6",
"react-native-vector-icons": "10.0.3",
"react-native-watch-connectivity": "1.1.0",
"react-native-webview": "13.8.2",
"react-native-webview": "13.8.4",
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38",
"readable-stream": "3.6.2",
"realm": "12.6.2",

View file

@ -38,6 +38,7 @@ const LNDCreateInvoice = () => {
const { wallets, saveToDisk, setSelectedWalletID } = useContext(BlueStorageContext);
const { walletID, uri } = useRoute().params;
const wallet = useRef(wallets.find(item => item.getID() === walletID) || wallets.find(item => item.chain === Chain.OFFCHAIN));
const createInvoiceRef = useRef();
const { name } = useRoute();
const { colors } = useTheme();
const { navigate, getParent, goBack, pop, setParams } = useNavigation();
@ -194,7 +195,7 @@ const LNDCreateInvoice = () => {
// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
/** @type LightningCustodianWallet */
const decoded = await wallet.current.decodeInvoice(invoiceRequest);
await Notifications.tryToObtainPermissions();
await Notifications.tryToObtainPermissions(createInvoiceRef);
Notifications.majorTomToGroundControl([], [decoded.payment_hash], []);
// send to lnurl-withdraw callback url if that exists
@ -317,7 +318,11 @@ const LNDCreateInvoice = () => {
const renderCreateButton = () => {
return (
<View style={styles.createButton}>
{isLoading ? <ActivityIndicator /> : <Button disabled={!(amount > 0)} onPress={createInvoice} title={loc.send.details_create} />}
{isLoading ? (
<ActivityIndicator />
) : (
<Button disabled={!(amount > 0)} ref={createInvoiceRef} onPress={createInvoice} title={loc.send.details_create} />
)}
</View>
);
};

View file

@ -1,7 +1,7 @@
import React, { useContext, useEffect, useState } from 'react';
import { View, Share, StyleSheet } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import { BlueCopyTextToClipboard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -10,6 +10,7 @@ import presentAlert from '../../components/Alert';
import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import SafeArea from '../../components/SafeArea';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const LNDViewAdditionalInvoiceInformation = () => {
const { walletID } = useRoute().params;
@ -60,7 +61,7 @@ const LNDViewAdditionalInvoiceInformation = () => {
</View>
<BlueSpacing20 />
<BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText>
<BlueCopyTextToClipboard text={walletInfo.uris[0]} />
<CopyTextToClipboard text={walletInfo.uris[0]} />
<View style={styles.share}>
<Button
icon={{

View file

@ -1,12 +1,13 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { useRoute } from '@react-navigation/native';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import QRCodeComponent from '../../components/QRCodeComponent';
import { useTheme } from '../../components/themes';
import SafeArea from '../../components/SafeArea';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const LNDViewAdditionalInvoicePreImage = () => {
// state = { walletInfo: undefined };
@ -27,7 +28,7 @@ const LNDViewAdditionalInvoicePreImage = () => {
<QRCodeComponent value={preImageData} size={300} logoSize={90} />
</View>
<BlueSpacing20 />
<BlueCopyTextToClipboard text={preImageData} />
<CopyTextToClipboard text={preImageData} />
</View>
</SafeArea>
);

View file

@ -4,7 +4,7 @@ import Share from 'react-native-share';
import { Icon } from 'react-native-elements';
import QRCodeComponent from '../../components/QRCodeComponent';
import { useNavigation, useNavigationState, useRoute } from '@react-navigation/native';
import { BlueLoading, BlueText, BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { BlueLoading, BlueText, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -15,6 +15,7 @@ import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import SafeArea from '../../components/SafeArea';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const LNDViewInvoice = () => {
const { invoice, walletID } = useRoute().params;
@ -252,7 +253,7 @@ const LNDViewInvoice = () => {
{loc.lndViewInvoice.for} {invoice.description}
</BlueText>
)}
<BlueCopyTextToClipboard truncated text={invoice.payment_request} />
<CopyTextToClipboard truncated text={invoice.payment_request} />
<Button onPress={handleOnSharePressed} title={loc.receive.details_share} />

View file

@ -13,15 +13,7 @@ import {
import { useRoute, useFocusEffect } from '@react-navigation/native';
import Share from 'react-native-share';
import QRCodeComponent from '../../components/QRCodeComponent';
import {
BlueLoading,
BlueCopyTextToClipboard,
BlueButtonLink,
BlueText,
BlueSpacing20,
BlueCard,
BlueSpacing40,
} from '../../BlueComponents';
import { BlueLoading, BlueButtonLink, BlueText, BlueSpacing20, BlueCard, BlueSpacing40 } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import BottomModal from '../../components/BottomModal';
import { Chain, BitcoinUnit } from '../../models/bitcoinUnits';
@ -39,6 +31,7 @@ import Button from '../../components/Button';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import { fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const ReceiveDetails = () => {
const { walletID, address } = useRoute().params;
@ -101,34 +94,27 @@ const ReceiveDetails = () => {
// re-fetching address balance periodically
useEffect(() => {
console.log('receive/defails - useEffect');
console.log('receive/details - useEffect');
if (fetchAddressInterval.current) {
// interval already exists, lets cleanup it and recreate, so theres no duplicate intervals
clearInterval(fetchAddressInterval.current);
fetchAddressInterval.current = undefined;
}
fetchAddressInterval.current = setInterval(async () => {
const intervalId = setInterval(async () => {
try {
const decoded = DeeplinkSchemaMatch.bip21decode(bip21encoded);
const address2use = address || decoded.address;
if (!address2use) return;
const addressToUse = address || decoded.address;
if (!addressToUse) return;
console.log('checking address', address2use, 'for balance...');
const balance = await BlueElectrum.getBalanceByAddress(address2use);
console.log('checking address', addressToUse, 'for balance...');
const balance = await BlueElectrum.getBalanceByAddress(addressToUse);
console.log('...got', balance);
if (balance.unconfirmed > 0) {
if (initialConfirmed === 0 && initialUnconfirmed === 0) {
// saving initial values for later (when tx gets confirmed)
setInitialConfirmed(balance.confirmed);
setInitialUnconfirmed(balance.unconfirmed);
setIntervalMs(25000);
triggerHapticFeedback(HapticFeedbackTypes.ImpactHeavy);
}
const txs = await BlueElectrum.getMempoolTransactionsByAddress(address2use);
const txs = await BlueElectrum.getMempoolTransactionsByAddress(addressToUse);
const tx = txs.pop();
if (tx) {
const rez = await BlueElectrum.multiGetTransactionByTxid([tx.tx_hash], 10, true);
@ -137,11 +123,9 @@ const ReceiveDetails = () => {
const fees = await BlueElectrum.estimateFees();
if (satPerVbyte >= fees.fast) {
setEta(loc.formatString(loc.transactions.eta_10m));
}
if (satPerVbyte >= fees.medium && satPerVbyte < fees.fast) {
} else if (satPerVbyte >= fees.medium) {
setEta(loc.formatString(loc.transactions.eta_3h));
}
if (satPerVbyte < fees.medium) {
} else {
setEta(loc.formatString(loc.transactions.eta_1d));
}
}
@ -158,7 +142,6 @@ const ReceiveDetails = () => {
} else if (balance.unconfirmed === 0 && initialUnconfirmed !== 0) {
// now, handling a case when unconfirmed == 0, but in past it wasnt (i.e. it changed while user was
// staring at the screen)
const balanceToShow = balance.confirmed - initialConfirmed;
if (balanceToShow > 0) {
@ -166,17 +149,12 @@ const ReceiveDetails = () => {
setShowConfirmedBalance(true);
setShowPendingBalance(false);
setShowAddress(false);
clearInterval(fetchAddressInterval.current);
fetchAddressInterval.current = undefined;
setDisplayBalance(
loc.formatString(loc.transactions.received_with_amount, {
amt1: formatBalance(balanceToShow, BitcoinUnit.LOCAL_CURRENCY, true).toString(),
amt2: formatBalance(balanceToShow, BitcoinUnit.BTC, true).toString(),
}),
);
fetchAndSaveWalletTransactions(walletID);
} else {
// rare case, but probable. transaction evicted from mempool (maybe cancelled by the sender)
@ -189,6 +167,8 @@ const ReceiveDetails = () => {
console.log(error);
}
}, intervalMs);
return () => clearInterval(intervalId);
}, [bip21encoded, address, initialConfirmed, initialUnconfirmed, intervalMs, fetchAndSaveWalletTransactions, walletID]);
const renderConfirmedBalance = () => {
@ -271,7 +251,7 @@ const ReceiveDetails = () => {
)}
<QRCodeComponent value={bip21encoded} />
<BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} ref={receiveAddressButton} />
<CopyTextToClipboard text={isCustom ? bip21encoded : address} ref={receiveAddressButton} />
</View>
<View style={styles.share}>
<BlueCard>
@ -296,7 +276,7 @@ const ReceiveDetails = () => {
let newAddress;
if (address) {
setAddressBIP21Encoded(address);
await Notifications.tryToObtainPermissions(receiveAddressButton.current);
await Notifications.tryToObtainPermissions(receiveAddressButton);
Notifications.majorTomToGroundControl([address], [], []);
} else {
if (wallet.chain === Chain.ONCHAIN) {
@ -324,7 +304,7 @@ const ReceiveDetails = () => {
}
}
setAddressBIP21Encoded(newAddress);
await Notifications.tryToObtainPermissions(receiveAddressButton.current);
await Notifications.tryToObtainPermissions(receiveAddressButton);
Notifications.majorTomToGroundControl([newAddress], [], []);
}
// eslint-disable-next-line react-hooks/exhaustive-deps

View file

@ -6,7 +6,7 @@ import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native'
import RNFS from 'react-native-fs';
import Biometric from '../../class/biometrics';
import { BlueText, BlueCard, BlueSpacing20, BlueCopyToClipboardButton } from '../../BlueComponents';
import { BlueText, BlueCard, BlueSpacing20 } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -18,6 +18,7 @@ import { useTheme } from '../../components/themes';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import SafeArea from '../../components/SafeArea';
import { SecondButton } from '../../components/SecondButton';
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
const BlueElectrum = require('../../blue_modules/BlueElectrum');
const bitcoin = require('bitcoinjs-lib');
const fs = require('../../blue_modules/fs');
@ -275,7 +276,7 @@ const PsbtWithHardwareWallet = () => {
/>
<BlueSpacing20 />
<View style={styles.copyToClipboard}>
<BlueCopyToClipboardButton
<CopyToClipboardButton
stringToCopy={typeof psbt === 'string' ? psbt : psbt.toBase64()}
displayText={loc.send.psbt_clipboard}
/>

View file

@ -4,13 +4,14 @@ import { ScrollView, TouchableWithoutFeedback, I18nManager, StyleSheet, Linking,
import { Button as ButtonRNElements } from 'react-native-elements';
import navigationStyle from '../../components/navigationStyle';
import { BlueCard, BlueCopyToClipboardButton, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import loc from '../../loc';
import { BlueCurrentTheme, useTheme } from '../../components/themes';
import Notifications from '../../blue_modules/notifications';
import presentAlert from '../../components/Alert';
import { Button } from '../../components/Button';
import ListItem from '../../components/ListItem';
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
const NotificationSettings = () => {
const [isLoading, setIsLoading] = useState(true);
@ -147,7 +148,7 @@ const NotificationSettings = () => {
{isShowTokenInfo >= 9 && (
<View>
<BlueCopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
<CopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
</View>
)}

View file

@ -2,7 +2,7 @@ import React, { useContext, useEffect, useLayoutEffect, useState } from 'react';
import { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StyleSheet, Keyboard } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import Clipboard from '@react-native-clipboard/clipboard';
import { BlueCard, BlueCopyToClipboardButton, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import HandoffComponent from '../../components/handoff';
import loc from '../../loc';
@ -11,6 +11,7 @@ import ToolTipMenu from '../../components/TooltipMenu';
import presentAlert from '../../components/Alert';
import { useTheme } from '../../components/themes';
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
const dayjs = require('dayjs');
function onlyUnique(value, index, self) {
@ -240,7 +241,7 @@ const TransactionsDetails = () => {
<>
<View style={styles.rowHeader}>
<BlueText style={styles.rowCaption}>{loc.transactions.details_from}</BlueText>
<BlueCopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
<CopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
</View>
{renderSection(from.filter(onlyUnique))}
<View style={styles.marginBottom18} />
@ -251,7 +252,7 @@ const TransactionsDetails = () => {
<>
<View style={styles.rowHeader}>
<BlueText style={styles.rowCaption}>{loc.transactions.details_to}</BlueText>
<BlueCopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
<CopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
</View>
{renderSection(arrDiff(from, to.filter(onlyUnique)))}
<View style={styles.marginBottom18} />
@ -270,7 +271,7 @@ const TransactionsDetails = () => {
<>
<View style={styles.rowHeader}>
<BlueText style={styles.txid}>{loc.transactions.txid}</BlueText>
<BlueCopyToClipboardButton stringToCopy={tx.hash} />
<CopyToClipboardButton stringToCopy={tx.hash} />
</View>
<BlueText style={styles.rowValue}>{tx.hash}</BlueText>
<View style={styles.marginBottom18} />

View file

@ -1,7 +1,7 @@
import React, { useState, useCallback, useContext, useRef, useEffect } from 'react';
import { InteractionManager, ScrollView, ActivityIndicator, View, StyleSheet, AppState } from 'react-native';
import { useNavigation, useFocusEffect, useRoute } from '@react-navigation/native';
import { BlueSpacing20, BlueText, BlueCopyTextToClipboard, BlueCard } from '../../BlueComponents';
import { BlueSpacing20, BlueText, BlueCard } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import { LegacyWallet, LightningCustodianWallet, SegwitBech32Wallet, SegwitP2SHWallet, WatchOnlyWallet } from '../../class';
import loc from '../../loc';
@ -11,6 +11,7 @@ import HandoffComponent from '../../components/handoff';
import { useTheme } from '../../components/themes';
import SafeArea from '../../components/SafeArea';
import usePrivacy from '../../hooks/usePrivacy';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const WalletExport = () => {
const { wallets, saveToDisk } = useContext(BlueStorageContext);
@ -108,7 +109,7 @@ const WalletExport = () => {
)}
<BlueSpacing20 />
{wallet.type === LightningCustodianWallet.type || wallet.type === WatchOnlyWallet.type ? (
<BlueCopyTextToClipboard text={wallet.getSecret()} />
<CopyTextToClipboard text={wallet.getSecret()} />
) : (
<BlueText style={[styles.secret, styles.secretWritingDirection, stylesHook.secret]} testID="Secret">
{wallet.getSecret()}

View file

@ -1,10 +1,10 @@
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { BlueCopyTextToClipboard } from '../../BlueComponents';
import { PaymentCodeStackParamList } from '../../Navigation';
import QRCodeComponent from '../../components/QRCodeComponent';
import loc from '../../loc';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
type Props = NativeStackScreenProps<PaymentCodeStackParamList, 'PaymentCode'>;
@ -17,7 +17,7 @@ export default function PaymentCode({ route }: Props) {
{paymentCode && (
<>
<QRCodeComponent value={paymentCode} />
<BlueCopyTextToClipboard text={paymentCode} />
<CopyTextToClipboard text={paymentCode} truncated={false} />
</>
)}
</View>

View file

@ -1,10 +1,10 @@
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import React, { useContext, useEffect, useState } from 'react';
import { SectionList, StyleSheet, Text, View } from 'react-native';
import { BlueCopyTextToClipboard } from '../../BlueComponents';
import { PaymentCodeStackParamList } from '../../Navigation';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import loc from '../../loc';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
interface DataSection {
title: string;
@ -45,7 +45,7 @@ export default function PaymentCodesList({ route }: Props) {
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View>
<BlueCopyTextToClipboard truncated text={item} />
<CopyTextToClipboard truncated text={item} />
</View>
)}
renderSectionHeader={({ section: { title } }) => <Text style={styles.titleText}>{title}</Text>}

View file

@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native';
import { View, StyleSheet, ScrollView, BackHandler } from 'react-native';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -11,6 +11,7 @@ import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import SafeArea from '../../components/SafeArea';
import usePrivacy from '../../hooks/usePrivacy';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const PleaseBackupLNDHub = () => {
const { wallets } = useContext(BlueStorageContext);
@ -63,7 +64,7 @@ const PleaseBackupLNDHub = () => {
</View>
<BlueSpacing20 />
<QRCodeComponent value={wallet.getSecret()} size={qrCodeSize} />
<BlueCopyTextToClipboard text={wallet.getSecret()} />
<CopyTextToClipboard text={wallet.getSecret()} />
<BlueSpacing20 />
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
</ScrollView>

View file

@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect } from 'react';
import { useNavigation, useRoute } from '@react-navigation/native';
import { View, useWindowDimensions, StyleSheet, BackHandler, ScrollView } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import { BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
@ -10,6 +10,7 @@ import { useTheme } from '../../components/themes';
import Button from '../../components/Button';
import SafeArea from '../../components/SafeArea';
import usePrivacy from '../../hooks/usePrivacy';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
const PleaseBackupLdk = () => {
const { wallets } = useContext(BlueStorageContext);
@ -71,7 +72,7 @@ const PleaseBackupLdk = () => {
ecl="H"
/>
</View>
<BlueCopyTextToClipboard text={wallet.getSecret()} />
<CopyTextToClipboard text={wallet.getSecret()} />
<BlueSpacing20 />
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
</ScrollView>

View file

@ -2,7 +2,7 @@ import { NavigationProp, RouteProp, useFocusEffect, useNavigation, useRoute } fr
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { ActivityIndicator, InteractionManager, View } from 'react-native';
import Share from 'react-native-share';
import { BlueCopyTextToClipboard, BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueSpacing20, BlueText } from '../../BlueComponents';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import Button from '../../components/Button';
import QRCodeComponent from '../../components/QRCodeComponent';
@ -11,6 +11,7 @@ import HandoffComponent from '../../components/handoff';
import usePrivacy from '../../hooks/usePrivacy';
import loc from '../../loc';
import { styles, useDynamicStyles } from './xpub.styles';
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
export type RootStackParamList = {
@ -91,7 +92,7 @@ const WalletXpub: React.FC = () => {
<QRCodeComponent value={xpub} size={qrCodeSize} />
<BlueSpacing20 />
<BlueCopyTextToClipboard text={xPubText} />
{xPubText && <CopyTextToClipboard text={xPubText} />}
</View>
<HandoffComponent title={loc.wallets.xpub_title} type={HandoffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
<View style={styles.share}>

View file

@ -206,7 +206,7 @@ describe('BlueWallet UI Tests - no wallets', () => {
await element(by.text(`No, and do not ask me again.`)).tap();
} catch (_) {}
await yo('BitcoinAddressQRCodeContainer');
await yo('BlueCopyTextToClipboard');
await yo('CopyTextToClipboard');
await element(by.id('SetCustomAmountButton')).tap();
await element(by.id('BitcoinAmountInput')).replaceText('1');
await element(by.id('CustomAmountDescription')).typeText('test');
@ -214,7 +214,7 @@ describe('BlueWallet UI Tests - no wallets', () => {
await sup('1 BTC');
await sup('test');
await yo('BitcoinAddressQRCodeContainer');
await yo('BlueCopyTextToClipboard');
await yo('CopyTextToClipboard');
await device.pressBack();
await device.pressBack();
await helperDeleteWallet('cr34t3d');

View file

@ -402,7 +402,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
// XPUB
await element(by.id('WalletDetailsScroll')).swipe('up', 'fast', 1);
await element(by.id('XPub')).tap();
await expect(element(by.id('BlueCopyTextToClipboard'))).toBeVisible();
await expect(element(by.id('CopyTextToClipboard'))).toBeVisible();
await device.pressBack();
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');