mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-19 05:45:15 +01:00
Merge branch 'master' into PSBT---File-can-only-be-saved-on-APP,-not-on-Internal/External-Storage-#6220
This commit is contained in:
commit
7c93fa124e
@ -79,7 +79,7 @@ jobs:
|
|||||||
- name: Setup Provisioning Profiles
|
- name: Setup Provisioning Profiles
|
||||||
env:
|
env:
|
||||||
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
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 }}
|
GIT_URL: ${{ secrets.GIT_URL }}
|
||||||
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
|
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
|
||||||
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
|
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
|
||||||
|
178
.github/workflows/build-ios-release-pullrequest.yml
vendored
178
.github/workflows/build-ios-release-pullrequest.yml
vendored
@ -1,14 +1,17 @@
|
|||||||
name: Build Release Pull Request (iOS)
|
name: Build Release and Upload to TestFlight (iOS)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, reopened, synchronize, labeled, unlabeled]
|
types: [opened, reopened, synchronize, labeled]
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'testflight')
|
|
||||||
runs-on: macos-14
|
runs-on: macos-14
|
||||||
timeout-minutes: 180
|
timeout-minutes: 180
|
||||||
outputs:
|
outputs:
|
||||||
@ -22,171 +25,150 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Fetches all history
|
fetch-depth: 0 # Fetches all history
|
||||||
|
|
||||||
- name: Specify node version
|
- name: Specify node version
|
||||||
uses: actions/setup-node@v2-beta
|
uses: actions/setup-node@v2-beta
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|
||||||
- uses: maxim-lobanov/setup-xcode@v1
|
- uses: maxim-lobanov/setup-xcode@v1
|
||||||
with:
|
with:
|
||||||
xcode-version: 15.2
|
xcode-version: 15.2
|
||||||
|
|
||||||
- name: Set up Ruby
|
- name: Set up Ruby
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
|
|
||||||
- name: Install dependencies with Bundler
|
- name: Install dependencies with Bundler
|
||||||
run: bundle install
|
run: bundle install
|
||||||
|
- name: Install Fastlane
|
||||||
- name: Install Fastlane 2.217.0
|
run: gem install fastlane -v 2.217.0 # If a specific version is needed for PR or not specified, keep only one version
|
||||||
run: gem install fastlane -v 2.217.0
|
|
||||||
|
|
||||||
- name: Install CocoaPods
|
|
||||||
run: sudo gem install cocoapods
|
|
||||||
|
|
||||||
- name: Clear Derived Data
|
- name: Clear Derived Data
|
||||||
run: bundle exec fastlane ios clear_derived_data_lane
|
run: bundle exec fastlane ios clear_derived_data_lane
|
||||||
working-directory: ./ios
|
working-directory: ./ios
|
||||||
|
|
||||||
- name: Install node_modules
|
- name: Install node_modules
|
||||||
run: npm install
|
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
|
- name: Display release-notes.txt
|
||||||
run: cat release-notes.txt
|
run: cat release-notes.txt
|
||||||
|
|
||||||
- name: Get Latest Commit Message
|
- name: Get Latest Commit Message
|
||||||
id: get_latest_commit_message
|
id: get_latest_commit_message
|
||||||
run: |
|
run: |
|
||||||
LATEST_COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s")
|
LATEST_COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s")
|
||||||
echo "LATEST_COMMIT_MESSAGE=${LATEST_COMMIT_MESSAGE}" >> $GITHUB_ENV
|
echo "LATEST_COMMIT_MESSAGE=${LATEST_COMMIT_MESSAGE}" >> $GITHUB_ENV
|
||||||
echo "::set-output name=commit_message::$LATEST_COMMIT_MESSAGE"
|
echo "::set-output name=commit_message::$LATEST_COMMIT_MESSAGE"
|
||||||
|
|
||||||
- name: Set up Git Authentication
|
- name: Set up Git Authentication
|
||||||
env:
|
env:
|
||||||
ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
|
ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
git config --global credential.helper 'cache --timeout=3600'
|
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)"
|
git config --global http.https://github.com/.extraheader "AUTHORIZATION: basic $(echo -n x-access-token:${ACCESS_TOKEN} | base64)"
|
||||||
|
|
||||||
- name: Create Temporary Keychain
|
- name: Create Temporary Keychain
|
||||||
run: bundle exec fastlane ios create_temp_keychain
|
run: bundle exec fastlane ios create_temp_keychain
|
||||||
working-directory: ./ios
|
working-directory: ./ios
|
||||||
env:
|
env:
|
||||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
|
|
||||||
- name: Setup Provisioning Profiles
|
- name: Setup Provisioning Profiles
|
||||||
env:
|
env:
|
||||||
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
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 }}
|
GIT_URL: ${{ secrets.GIT_URL }}
|
||||||
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
|
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
|
||||||
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
|
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
|
||||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
run: bundle exec fastlane ios setup_provisioning_profiles
|
run: bundle exec fastlane ios setup_provisioning_profiles
|
||||||
working-directory: ./ios
|
working-directory: ./ios
|
||||||
|
|
||||||
- name: Generate Build Number based on timestamp
|
- name: Generate Build Number based on timestamp
|
||||||
id: generate_build_number
|
id: generate_build_number
|
||||||
run: |
|
run: |
|
||||||
NEW_BUILD_NUMBER=$(date +%s)
|
NEW_BUILD_NUMBER=$(date +%s)
|
||||||
echo "NEW_BUILD_NUMBER=$NEW_BUILD_NUMBER" >> $GITHUB_ENV
|
echo "NEW_BUILD_NUMBER=$NEW_BUILD_NUMBER" >> $GITHUB_ENV
|
||||||
echo "::set-output name=build_number::$NEW_BUILD_NUMBER"
|
echo "::set-output name=build_number::$NEW_BUILD_NUMBER"
|
||||||
|
|
||||||
- name: Set Build Number
|
- name: Set Build Number
|
||||||
run: bundle exec fastlane ios increment_build_number_lane
|
run: bundle exec fastlane ios increment_build_number_lane
|
||||||
working-directory: ./ios
|
working-directory: ./ios
|
||||||
|
|
||||||
- name: Determine Marketing Version
|
- name: Determine Marketing Version
|
||||||
id: determine_marketing_version
|
id: determine_marketing_version
|
||||||
run: |
|
run: |
|
||||||
MARKETING_VERSION=$(grep MARKETING_VERSION ios/BlueWallet.xcodeproj/project.pbxproj | awk -F '= ' '{print $2}' | tr -d ' ;' | head -1)
|
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 "PROJECT_VERSION=$MARKETING_VERSION" >> $GITHUB_ENV
|
||||||
echo "::set-output name=project_version::$MARKETING_VERSION"
|
echo "::set-output name=project_version::$MARKETING_VERSION"
|
||||||
|
|
||||||
|
|
||||||
- name: Expected IPA file name
|
- name: Expected IPA file name
|
||||||
run: |
|
run: |
|
||||||
echo "IPA file name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa"
|
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
|
- name: Build App
|
||||||
run: bundle exec fastlane ios build_app_lane
|
run: bundle exec fastlane ios build_app_lane
|
||||||
working-directory: ./ios
|
working-directory: ./ios
|
||||||
|
|
||||||
- name: Upload IPA as Artifact
|
- name: Upload IPA as Artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa
|
name: BlueWallet.${{env.PROJECT_VERSION}}(${{env.NEW_BUILD_NUMBER}}).ipa
|
||||||
path: ./ios/build/BlueWallet.${{env.PROJECT_VERSION}}(${{ env.NEW_BUILD_NUMBER }}).ipa
|
path: ./ios/build/BlueWallet.${{env.PROJECT_VERSION}}(${{ env.NEW_BUILD_NUMBER }}).ipa
|
||||||
|
|
||||||
|
|
||||||
testflight-upload:
|
testflight-upload:
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'testflight')
|
needs: build
|
||||||
needs: build
|
runs-on: macos-14
|
||||||
runs-on: macos-14
|
if: github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'testflight')
|
||||||
env:
|
env:
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
NEW_BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
|
NEW_BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
|
||||||
PROJECT_VERSION: ${{ needs.build.outputs.project_version }}
|
PROJECT_VERSION: ${{ needs.build.outputs.project_version }}
|
||||||
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
|
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout project
|
- name: Checkout project
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
- name: Cache Ruby Gems
|
||||||
- name: Cache Ruby Gems
|
uses: actions/cache@v2
|
||||||
uses: actions/cache@v2
|
with:
|
||||||
with:
|
path: vendor/bundle
|
||||||
path: vendor/bundle
|
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
||||||
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
restore-keys: |
|
||||||
restore-keys: |
|
${{ runner.os }}-gems-
|
||||||
${{ runner.os }}-gems-
|
- name: Install dependencies with Bundler
|
||||||
|
run: |
|
||||||
- name: Install dependencies with Bundler
|
bundle config path vendor/bundle
|
||||||
run: |
|
bundle install --jobs 4 --retry 3
|
||||||
bundle config path vendor/bundle
|
- name: Download IPA from Artifact
|
||||||
bundle install --jobs 4 --retry 3
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
- name: Download IPA from Artifact
|
name: BlueWallet.${{needs.build.outputs.project_version}}(${{needs.build.outputs.new_build_number}}).ipa
|
||||||
uses: actions/download-artifact@v2
|
path: ./ios/build
|
||||||
with:
|
- name: Create App Store Connect API Key JSON
|
||||||
name: BlueWallet.${{needs.build.outputs.project_version}}(${{needs.build.outputs.new_build_number}}).ipa
|
run: echo '${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}' > ./ios/appstore_api_key.json
|
||||||
path: ./ios/build
|
- name: Upload to TestFlight
|
||||||
|
env:
|
||||||
- name: Create App Store Connect API Key JSON
|
APP_STORE_CONNECT_API_KEY_PATH: $(pwd)/ios/appstore_api_key.p8
|
||||||
run: echo '${{ secrets.APP_STORE_CONNECT_API_KEY_CONTENT }}' > ./ios/appstore_api_key.json
|
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
||||||
|
GIT_ACCESS_TOKEN: ${{ secrets.GIT_ACCESS_TOKEN }}
|
||||||
- name: Upload to TestFlight
|
GIT_URL: ${{ secrets.GIT_URL }}
|
||||||
env:
|
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
|
||||||
APP_STORE_CONNECT_API_KEY_PATH: $(pwd)/ios/appstore_api_key.p8
|
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
|
||||||
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
|
||||||
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.GIT_ACCESS_TOKEN }}
|
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
|
||||||
GIT_URL: ${{ secrets.GIT_URL }}
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
|
run: bundle exec fastlane ios upload_to_testflight_lane
|
||||||
ITC_TEAM_NAME: ${{ secrets.ITC_TEAM_NAME }}
|
working-directory: ./ios
|
||||||
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
|
- name: Post PR Comment
|
||||||
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
|
if: success() && github.event_name == 'pull_request'
|
||||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
uses: actions/github-script@v6
|
||||||
run: bundle exec fastlane ios upload_to_testflight_lane
|
env:
|
||||||
working-directory: ./ios
|
BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
|
||||||
- name: Post PR Comment
|
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
|
||||||
uses: actions/github-script@v6
|
with:
|
||||||
if: success() # Ensures the message is only posted if previous steps succeed
|
script: |
|
||||||
env:
|
const buildNumber = process.env.BUILD_NUMBER;
|
||||||
BUILD_NUMBER: ${{ needs.build.outputs.new_build_number }}
|
const message = `The build ${buildNumber} has been uploaded to TestFlight.`;
|
||||||
LATEST_COMMIT_MESSAGE: ${{ needs.build.outputs.latest_commit_message }}
|
const prNumber = context.payload.pull_request.number;
|
||||||
with:
|
const repo = context.repo;
|
||||||
script: |
|
github.rest.issues.createComment({
|
||||||
const buildNumber = process.env.BUILD_NUMBER;
|
...repo,
|
||||||
const message = `The build ${buildNumber} has been uploaded to TestFlight.`;
|
issue_number: prNumber,
|
||||||
const prNumber = context.payload.pull_request.number;
|
body: message,
|
||||||
const repo = context.repo;
|
});
|
||||||
github.rest.issues.createComment({
|
|
||||||
...repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
body: message,
|
|
||||||
});
|
|
180
.github/workflows/build-ios-release-testflight.yml
vendored
180
.github/workflows/build-ios-release-testflight.yml
vendored
@ -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
|
|
59
App.js
59
App.js
@ -33,6 +33,7 @@ import HandoffComponent from './components/handoff';
|
|||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
||||||
import MenuElements from './components/MenuElements';
|
import MenuElements from './components/MenuElements';
|
||||||
import { updateExchangeRate } from './blue_modules/currency';
|
import { updateExchangeRate } from './blue_modules/currency';
|
||||||
|
import { NavigationProvider } from './components/NavigationProvider';
|
||||||
const A = require('./blue_modules/analytics');
|
const A = require('./blue_modules/analytics');
|
||||||
|
|
||||||
const eventEmitter = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
|
const eventEmitter = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
|
||||||
@ -99,28 +100,42 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (walletsInitialized) {
|
|
||||||
addListeners();
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [walletsInitialized]);
|
|
||||||
|
|
||||||
const addListeners = () => {
|
const addListeners = () => {
|
||||||
Linking.addEventListener('url', handleOpenURL);
|
const urlSubscription = Linking.addEventListener('url', handleOpenURL);
|
||||||
AppState.addEventListener('change', handleAppStateChange);
|
const appStateSubscription = AppState.addEventListener('change', handleAppStateChange);
|
||||||
|
|
||||||
|
// Note: `getMostRecentUserActivity` doesn't create a persistent listener, so no need to unsubscribe
|
||||||
EventEmitter?.getMostRecentUserActivity()
|
EventEmitter?.getMostRecentUserActivity()
|
||||||
.then(onUserActivityOpen)
|
.then(onUserActivityOpen)
|
||||||
.catch(() => console.log('No userActivity object sent'));
|
.catch(() => console.log('No userActivity object sent'));
|
||||||
handleAppStateChange(undefined);
|
|
||||||
/*
|
const notificationSubscription = eventEmitter?.addListener('onNotificationReceived', onNotificationReceived);
|
||||||
When a notification on iOS is shown while the app is on foreground;
|
const activitySubscription = eventEmitter?.addListener('onUserActivityOpen', onUserActivityOpen);
|
||||||
On willPresent on AppDelegate.m
|
|
||||||
*/
|
// Store subscriptions in a ref or state to remove them later
|
||||||
eventEmitter?.addListener('onNotificationReceived', onNotificationReceived);
|
return {
|
||||||
eventEmitter?.addListener('onUserActivityOpen', onUserActivityOpen);
|
urlSubscription,
|
||||||
|
appStateSubscription,
|
||||||
|
notificationSubscription,
|
||||||
|
activitySubscription,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (walletsInitialized) {
|
||||||
|
const subscriptions = addListeners();
|
||||||
|
|
||||||
|
// Cleanup function
|
||||||
|
return () => {
|
||||||
|
subscriptions.urlSubscription?.remove();
|
||||||
|
subscriptions.appStateSubscription?.remove();
|
||||||
|
subscriptions.notificationSubscription?.remove();
|
||||||
|
subscriptions.activitySubscription?.remove();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [walletsInitialized]); // Re-run when walletsInitialized changes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes push notifications stored in AsyncStorage. Might navigate to some screen.
|
* Processes push notifications stored in AsyncStorage. Might navigate to some screen.
|
||||||
*
|
*
|
||||||
@ -285,14 +300,16 @@ const App = () => {
|
|||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<View style={styles.root}>
|
<View style={styles.root}>
|
||||||
<NavigationContainer ref={navigationRef} theme={colorScheme === 'dark' ? BlueDarkTheme : BlueDefaultTheme}>
|
<NavigationContainer ref={navigationRef} theme={colorScheme === 'dark' ? BlueDarkTheme : BlueDefaultTheme}>
|
||||||
<InitRoot />
|
<NavigationProvider>
|
||||||
<Notifications onProcessNotifications={processPushNotifications} />
|
<InitRoot />
|
||||||
<MenuElements />
|
<Notifications onProcessNotifications={processPushNotifications} />
|
||||||
<DeviceQuickActions />
|
<MenuElements />
|
||||||
|
<DeviceQuickActions />
|
||||||
|
<Biometric />
|
||||||
|
</NavigationProvider>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
</View>
|
</View>
|
||||||
<WatchConnectivity />
|
<WatchConnectivity />
|
||||||
<Biometric />
|
|
||||||
<WidgetCommunication />
|
<WidgetCommunication />
|
||||||
</SafeAreaProvider>
|
</SafeAreaProvider>
|
||||||
);
|
);
|
||||||
|
@ -859,7 +859,11 @@ export class AppStorage {
|
|||||||
|
|
||||||
isDoNotTrackEnabled = async (): Promise<boolean> => {
|
isDoNotTrackEnabled = async (): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
return !!(await AsyncStorage.getItem(AppStorage.DO_NOT_TRACK));
|
const doNotTrackValue = !!(await AsyncStorage.getItem(AppStorage.DO_NOT_TRACK));
|
||||||
|
if (doNotTrackValue) {
|
||||||
|
await DefaultPreference.set(AppStorage.DO_NOT_TRACK, '1');
|
||||||
|
AsyncStorage.removeItem(AppStorage.DO_NOT_TRACK);
|
||||||
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,6 @@ import PropTypes from 'prop-types';
|
|||||||
import { Icon, Text, Header } from 'react-native-elements';
|
import { Icon, Text, Header } from 'react-native-elements';
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Alert,
|
|
||||||
Animated,
|
|
||||||
Dimensions,
|
Dimensions,
|
||||||
Image,
|
Image,
|
||||||
InputAccessoryView,
|
InputAccessoryView,
|
||||||
@ -18,7 +16,6 @@ import {
|
|||||||
View,
|
View,
|
||||||
I18nManager,
|
I18nManager,
|
||||||
ImageBackground,
|
ImageBackground,
|
||||||
findNodeHandle,
|
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import Clipboard from '@react-native-clipboard/clipboard';
|
import Clipboard from '@react-native-clipboard/clipboard';
|
||||||
import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeType } from './models/networkTransactionFees';
|
import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeType } from './models/networkTransactionFees';
|
||||||
@ -27,8 +24,6 @@ import { BlueCurrentTheme, useTheme } from './components/themes';
|
|||||||
import PlusIcon from './components/icons/PlusIcon';
|
import PlusIcon from './components/icons/PlusIcon';
|
||||||
import loc, { formatStringAddTwoWhiteSpaces } from './loc';
|
import loc, { formatStringAddTwoWhiteSpaces } from './loc';
|
||||||
import SafeArea from './components/SafeArea';
|
import SafeArea from './components/SafeArea';
|
||||||
import { isDesktop } from './blue_modules/environment';
|
|
||||||
import ActionSheet from './screen/ActionSheet';
|
|
||||||
|
|
||||||
const { height, width } = Dimensions.get('window');
|
const { height, width } = Dimensions.get('window');
|
||||||
const aspectRatio = height / width;
|
const aspectRatio = height / width;
|
||||||
@ -196,39 +191,6 @@ export const BlueButtonLink = forwardRef((props, ref) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const BlueAlertWalletExportReminder = ({ onSuccess = () => {}, onFailure, anchor }) => {
|
|
||||||
if (isDesktop) {
|
|
||||||
ActionSheet.showActionSheetWithOptions(
|
|
||||||
{
|
|
||||||
title: loc.wallets.details_title, // Changed from loc.send.header to loc.wallets.details_title
|
|
||||||
message: loc.pleasebackup.ask,
|
|
||||||
options: [loc.pleasebackup.ask_yes, loc.pleasebackup.ask_no],
|
|
||||||
anchor: findNodeHandle(anchor), // Kept the same for context
|
|
||||||
},
|
|
||||||
buttonIndex => {
|
|
||||||
switch (buttonIndex) {
|
|
||||||
case 0:
|
|
||||||
onSuccess(); // Assuming the first button (yes) triggers onSuccess
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
onFailure(); // Assuming the second button (no) triggers onFailure
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Alert.alert(
|
|
||||||
loc.wallets.details_title,
|
|
||||||
loc.pleasebackup.ask,
|
|
||||||
[
|
|
||||||
{ text: loc.pleasebackup.ask_yes, onPress: onSuccess, style: 'cancel' },
|
|
||||||
{ text: loc.pleasebackup.ask_no, onPress: onFailure },
|
|
||||||
],
|
|
||||||
{ cancelable: false },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const BluePrivateBalance = () => {
|
export const BluePrivateBalance = () => {
|
||||||
return (
|
return (
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 13, borderRadius: 9 }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 13, borderRadius: 9 }}>
|
||||||
@ -241,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 => {
|
export const BlueCard = props => {
|
||||||
return <View {...props} style={{ padding: 20 }} />;
|
return <View {...props} style={{ padding: 20 }} />;
|
||||||
};
|
};
|
||||||
|
@ -639,7 +639,7 @@ const Navigation = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<RootStack.Screen name="PaymentCodeRoot" component={PaymentCodeStackRoot} options={NavigationDefaultOptions} />
|
<RootStack.Screen name="PaymentCodeRoot" component={PaymentCodeStackRoot} options={NavigationDefaultOptions} />
|
||||||
<InitStack.Screen
|
<RootStack.Screen
|
||||||
name="ReorderWallets"
|
name="ReorderWallets"
|
||||||
component={ReorderWalletsStackRoot}
|
component={ReorderWalletsStackRoot}
|
||||||
options={{
|
options={{
|
||||||
|
@ -13,7 +13,6 @@ import com.facebook.soloader.SoLoader;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.bugsnag.android.Bugsnag;
|
|
||||||
|
|
||||||
public class MainApplication extends Application implements ReactApplication {
|
public class MainApplication extends Application implements ReactApplication {
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ public class MainApplication extends Application implements ReactApplication {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
Bugsnag.start(this);
|
|
||||||
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
|
I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance();
|
||||||
sharedI18nUtilInstance.allowRTL(getApplicationContext(), true);
|
sharedI18nUtilInstance.allowRTL(getApplicationContext(), true);
|
||||||
SoLoader.init(this, /* native exopackage */ false);
|
SoLoader.init(this, /* native exopackage */ false);
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import PushNotificationIOS from '@react-native-community/push-notification-ios';
|
import PushNotificationIOS from '@react-native-community/push-notification-ios';
|
||||||
import { Alert, Platform, findNodeHandle } from 'react-native';
|
import { Platform, findNodeHandle } from 'react-native';
|
||||||
import Frisbee from 'frisbee';
|
import Frisbee from 'frisbee';
|
||||||
import { getApplicationName, getVersion, getSystemName, getSystemVersion, hasGmsSync, hasHmsSync } from 'react-native-device-info';
|
import { getApplicationName, getVersion, getSystemName, getSystemVersion, hasGmsSync, hasHmsSync } from 'react-native-device-info';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import loc from '../loc';
|
import loc from '../loc';
|
||||||
import { requestNotifications } from 'react-native-permissions';
|
import { requestNotifications } from 'react-native-permissions';
|
||||||
import PushNotification from 'react-native-push-notification';
|
import PushNotification from 'react-native-push-notification';
|
||||||
import { isDesktop } from './environment';
|
|
||||||
import ActionSheet from '../screen/ActionSheet';
|
import ActionSheet from '../screen/ActionSheet';
|
||||||
|
|
||||||
const constants = require('./constants');
|
const constants = require('./constants');
|
||||||
@ -144,63 +143,30 @@ function Notifications(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
if (isDesktop) {
|
const options = [loc.notifications.no_and_dont_ask, loc.notifications.ask_me_later, loc._.ok];
|
||||||
ActionSheet.showActionSheetWithOptions(
|
|
||||||
{
|
ActionSheet.showActionSheetWithOptions(
|
||||||
title: loc.settings.notifications,
|
{
|
||||||
message: loc.notifications.would_you_like_to_receive_notifications,
|
title: loc.settings.notifications,
|
||||||
options: [loc.notifications.no_and_dont_ask, loc.notifications.ask_me_later, loc._.ok],
|
message: loc.notifications.would_you_like_to_receive_notifications,
|
||||||
cancelButtonIndex: 0, // Assuming 'no and don't ask' is treated as the cancel action
|
options,
|
||||||
anchor: findNodeHandle(anchor.current), // Assuming you have a relevant anchor as before
|
cancelButtonIndex: 0, // Assuming 'no and don't ask' is still treated as the cancel action
|
||||||
},
|
anchor: findNodeHandle(anchor.current),
|
||||||
buttonIndex => {
|
},
|
||||||
switch (buttonIndex) {
|
buttonIndex => {
|
||||||
case 0:
|
switch (buttonIndex) {
|
||||||
AsyncStorage.setItem(NOTIFICATIONS_NO_AND_DONT_ASK_FLAG, '1');
|
case 0:
|
||||||
resolve(false);
|
AsyncStorage.setItem(NOTIFICATIONS_NO_AND_DONT_ASK_FLAG, '1').then(() => resolve(false));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
resolve(false);
|
resolve(false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
(async () => {
|
configureNotifications().then(resolve);
|
||||||
resolve(await configureNotifications());
|
break;
|
||||||
})();
|
}
|
||||||
break;
|
},
|
||||||
}
|
);
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Alert.alert(
|
|
||||||
loc.settings.notifications,
|
|
||||||
loc.notifications.would_you_like_to_receive_notifications,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
text: loc.notifications.no_and_dont_ask,
|
|
||||||
onPress: () => {
|
|
||||||
AsyncStorage.setItem(NOTIFICATIONS_NO_AND_DONT_ASK_FLAG, '1');
|
|
||||||
resolve(false);
|
|
||||||
},
|
|
||||||
style: 'cancel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: loc.notifications.ask_me_later,
|
|
||||||
onPress: () => {
|
|
||||||
resolve(false);
|
|
||||||
},
|
|
||||||
style: 'cancel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: loc._.ok,
|
|
||||||
onPress: async () => {
|
|
||||||
resolve(await configureNotifications());
|
|
||||||
},
|
|
||||||
style: 'default',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ cancelable: false },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { forwardRef } from 'react';
|
||||||
import { TouchableOpacity, View, Text, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
import { TouchableOpacity, View, Text, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import { useTheme } from './themes';
|
import { useTheme } from './themes';
|
||||||
@ -19,7 +19,7 @@ interface ButtonProps {
|
|||||||
onPress?: () => void;
|
onPress?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Button: React.FC<ButtonProps> = props => {
|
export const Button = forwardRef<TouchableOpacity, ButtonProps>((props, ref) => {
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
let backgroundColor = props.backgroundColor ?? colors.mainColor;
|
let backgroundColor = props.backgroundColor ?? colors.mainColor;
|
||||||
@ -48,13 +48,23 @@ export const Button: React.FC<ButtonProps> = props => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return props.onPress ? (
|
return props.onPress ? (
|
||||||
<TouchableOpacity testID={props.testID} accessibilityRole="button" onPress={props.onPress} disabled={props.disabled}>
|
<TouchableOpacity
|
||||||
{buttonView}
|
ref={ref}
|
||||||
|
testID={props.testID}
|
||||||
|
style={[buttonStyle, props.style]}
|
||||||
|
accessibilityRole="button"
|
||||||
|
onPress={props.onPress}
|
||||||
|
disabled={props.disabled}
|
||||||
|
>
|
||||||
|
<View style={styles.content}>
|
||||||
|
{props.icon && <Icon name={props.icon.name} type={props.icon.type} color={props.icon.color} />}
|
||||||
|
{props.title && <Text style={textStyle}>{props.title}</Text>}
|
||||||
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
) : (
|
) : (
|
||||||
buttonView
|
buttonView
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
button: {
|
button: {
|
||||||
|
65
components/CopyTextToClipboard.tsx
Normal file
65
components/CopyTextToClipboard.tsx
Normal 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 },
|
||||||
|
});
|
27
components/CopyToClipboardButton.tsx
Normal file
27
components/CopyToClipboardButton.tsx
Normal 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;
|
9
components/NavigationProvider.tsx
Normal file
9
components/NavigationProvider.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React, { ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface NavigationProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NavigationProvider: React.FC<NavigationProviderProps> = ({ children }) => {
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
16
helpers/presentWalletExportReminder.ts
Normal file
16
helpers/presentWalletExportReminder.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Alert } from 'react-native';
|
||||||
|
import loc from '../loc';
|
||||||
|
|
||||||
|
export const presentWalletExportReminder = (): Promise<void> => {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
Alert.alert(
|
||||||
|
loc.wallets.details_title,
|
||||||
|
loc.pleasebackup.ask,
|
||||||
|
[
|
||||||
|
{ text: loc.pleasebackup.ask_yes, onPress: () => resolve(), style: 'default' },
|
||||||
|
{ text: loc.pleasebackup.ask_no, onPress: () => reject(new Error('User has denied saving the wallet backup.')), style: 'cancel' },
|
||||||
|
],
|
||||||
|
{ cancelable: false },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
94
hooks/useExtendedNavigation.ts
Normal file
94
hooks/useExtendedNavigation.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { useNavigation, NavigationProp, ParamListBase } from '@react-navigation/native';
|
||||||
|
import Biometric from '../class/biometrics';
|
||||||
|
import { navigationRef } from '../NavigationService';
|
||||||
|
import { BlueStorageContext } from '../blue_modules/storage-context';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import { presentWalletExportReminder } from '../helpers/presentWalletExportReminder';
|
||||||
|
|
||||||
|
// List of screens that require biometrics
|
||||||
|
|
||||||
|
const requiresBiometrics = ['WalletExportRoot', 'WalletXpubRoot', 'ViewEditMultisigCosignersRoot', 'ExportMultisigCoordinationSetupRoot'];
|
||||||
|
|
||||||
|
// List of screens that require wallet export to be saved
|
||||||
|
|
||||||
|
const requiresWalletExportIsSaved = ['ReceiveDetailsRoot', 'WalletAddresses'];
|
||||||
|
|
||||||
|
export const useExtendedNavigation = (): NavigationProp<ParamListBase> => {
|
||||||
|
const originalNavigation = useNavigation<NavigationProp<ParamListBase>>();
|
||||||
|
const { wallets, saveToDisk } = useContext(BlueStorageContext);
|
||||||
|
|
||||||
|
const enhancedNavigate: NavigationProp<ParamListBase>['navigate'] = (screenOrOptions: any, params?: any) => {
|
||||||
|
let screenName: string;
|
||||||
|
if (typeof screenOrOptions === 'string') {
|
||||||
|
screenName = screenOrOptions;
|
||||||
|
} else if (typeof screenOrOptions === 'object' && 'name' in screenOrOptions) {
|
||||||
|
screenName = screenOrOptions.name;
|
||||||
|
params = screenOrOptions.params; // Assign params from object if present
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid navigation options');
|
||||||
|
}
|
||||||
|
|
||||||
|
const isRequiresBiometrics = requiresBiometrics.includes(screenName);
|
||||||
|
const isRequiresWalletExportIsSaved = requiresWalletExportIsSaved.includes(screenName);
|
||||||
|
|
||||||
|
const proceedWithNavigation = () => {
|
||||||
|
console.log('Proceeding with navigation to', screenName);
|
||||||
|
if (navigationRef.current?.isReady()) {
|
||||||
|
typeof screenOrOptions === 'string'
|
||||||
|
? originalNavigation.navigate(screenOrOptions, params)
|
||||||
|
: originalNavigation.navigate(screenName, params); // Fixed to use screenName and params
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
if (isRequiresBiometrics) {
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseEnabled();
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
const isAuthenticated = await Biometric.unlockWithBiometrics();
|
||||||
|
if (isAuthenticated) {
|
||||||
|
proceedWithNavigation();
|
||||||
|
return; // Ensure the function exits if this path is taken
|
||||||
|
} else {
|
||||||
|
console.error('Biometric authentication failed');
|
||||||
|
// Decide if navigation should proceed or not after failed authentication
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isRequiresWalletExportIsSaved) {
|
||||||
|
console.log('Checking if wallet export is saved');
|
||||||
|
let walletID: string | undefined;
|
||||||
|
if (params && params.walletID) {
|
||||||
|
walletID = params.walletID;
|
||||||
|
} else if (params && params.params && params.params.walletID) {
|
||||||
|
walletID = params.params.walletID;
|
||||||
|
}
|
||||||
|
if (!walletID) {
|
||||||
|
proceedWithNavigation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const wallet = wallets.find(w => w.getID() === walletID);
|
||||||
|
if (wallet && !wallet.getUserHasSavedExport()) {
|
||||||
|
try {
|
||||||
|
await presentWalletExportReminder();
|
||||||
|
wallet.setUserHasSavedExport(true);
|
||||||
|
await saveToDisk(); // Assuming saveToDisk() returns a Promise.
|
||||||
|
proceedWithNavigation();
|
||||||
|
} catch {
|
||||||
|
originalNavigation.navigate('WalletExportRoot', {
|
||||||
|
screen: 'WalletExport',
|
||||||
|
params: { walletID },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return; // Prevent proceeding with the original navigation if the reminder is shown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proceedWithNavigation();
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...originalNavigation,
|
||||||
|
navigate: enhancedNavigate,
|
||||||
|
};
|
||||||
|
};
|
@ -65,6 +65,10 @@
|
|||||||
B40FC3FA29CCD1D00007EBAC /* SwiftTCPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */; };
|
B40FC3FA29CCD1D00007EBAC /* SwiftTCPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */; };
|
||||||
B41B76852B66B2FF002C48D5 /* Bugsnag in Frameworks */ = {isa = PBXBuildFile; productRef = B41B76842B66B2FF002C48D5 /* Bugsnag */; };
|
B41B76852B66B2FF002C48D5 /* Bugsnag in Frameworks */ = {isa = PBXBuildFile; productRef = B41B76842B66B2FF002C48D5 /* Bugsnag */; };
|
||||||
B41B76872B66B2FF002C48D5 /* BugsnagNetworkRequestPlugin in Frameworks */ = {isa = PBXBuildFile; productRef = B41B76862B66B2FF002C48D5 /* BugsnagNetworkRequestPlugin */; };
|
B41B76872B66B2FF002C48D5 /* BugsnagNetworkRequestPlugin in Frameworks */ = {isa = PBXBuildFile; productRef = B41B76862B66B2FF002C48D5 /* BugsnagNetworkRequestPlugin */; };
|
||||||
|
B41C2E562BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */; };
|
||||||
|
B41C2E572BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */; };
|
||||||
|
B41C2E582BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */; };
|
||||||
|
B41C2E592BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */; };
|
||||||
B43D0378225847C500FBAA95 /* WalletGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0372225847C500FBAA95 /* WalletGradient.swift */; };
|
B43D0378225847C500FBAA95 /* WalletGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0372225847C500FBAA95 /* WalletGradient.swift */; };
|
||||||
B43D0379225847C500FBAA95 /* WatchDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0373225847C500FBAA95 /* WatchDataSource.swift */; };
|
B43D0379225847C500FBAA95 /* WatchDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0373225847C500FBAA95 /* WatchDataSource.swift */; };
|
||||||
B43D037A225847C500FBAA95 /* Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0374225847C500FBAA95 /* Transaction.swift */; };
|
B43D037A225847C500FBAA95 /* Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0374225847C500FBAA95 /* Transaction.swift */; };
|
||||||
@ -92,7 +96,7 @@
|
|||||||
B4AB225E2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; };
|
B4AB225E2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; };
|
||||||
B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; };
|
B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; };
|
||||||
C59F90CE0D04D3E4BB39BC5D /* libPods-BlueWalletUITests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F02C2F7CA3591E4E0B06EBA /* libPods-BlueWalletUITests.a */; };
|
C59F90CE0D04D3E4BB39BC5D /* libPods-BlueWalletUITests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F02C2F7CA3591E4E0B06EBA /* libPods-BlueWalletUITests.a */; };
|
||||||
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
|
||||||
E5D4794B26781FC0007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
|
E5D4794B26781FC0007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
|
||||||
E5D4794C26781FC1007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
|
E5D4794C26781FC1007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
@ -362,6 +366,7 @@
|
|||||||
B40D4E5C2258425500428FCC /* WalletDetailsInterfaceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletDetailsInterfaceController.swift; sourceTree = "<group>"; };
|
B40D4E5C2258425500428FCC /* WalletDetailsInterfaceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletDetailsInterfaceController.swift; sourceTree = "<group>"; };
|
||||||
B40D4E672258426B00428FCC /* KeychainSwiftDistrib.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftDistrib.swift; sourceTree = SOURCE_ROOT; };
|
B40D4E672258426B00428FCC /* KeychainSwiftDistrib.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftDistrib.swift; sourceTree = SOURCE_ROOT; };
|
||||||
B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTCPClient.swift; sourceTree = "<group>"; };
|
B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTCPClient.swift; sourceTree = "<group>"; };
|
||||||
|
B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
B43B69BA225C46D800925B1E /* libRCTLinking.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRCTLinking.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
B43B69BA225C46D800925B1E /* libRCTLinking.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRCTLinking.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
B43D0372225847C500FBAA95 /* WalletGradient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletGradient.swift; sourceTree = "<group>"; };
|
B43D0372225847C500FBAA95 /* WalletGradient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletGradient.swift; sourceTree = "<group>"; };
|
||||||
B43D0373225847C500FBAA95 /* WatchDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchDataSource.swift; sourceTree = "<group>"; };
|
B43D0373225847C500FBAA95 /* WatchDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchDataSource.swift; sourceTree = "<group>"; };
|
||||||
@ -407,7 +412,7 @@
|
|||||||
files = (
|
files = (
|
||||||
782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */,
|
782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */,
|
||||||
764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */,
|
764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */,
|
||||||
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */,
|
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */,
|
||||||
773E382FE62E836172AAB98B /* libPods-BlueWallet.a in Frameworks */,
|
773E382FE62E836172AAB98B /* libPods-BlueWallet.a in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -650,6 +655,7 @@
|
|||||||
83CBB9F61A601CBA00E9B192 = {
|
83CBB9F61A601CBA00E9B192 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */,
|
||||||
B4549F2E2B80FEA1002E3153 /* ci_scripts */,
|
B4549F2E2B80FEA1002E3153 /* ci_scripts */,
|
||||||
13B07FAE1A68108700A75B9A /* BlueWallet */,
|
13B07FAE1A68108700A75B9A /* BlueWallet */,
|
||||||
00E356EF1AD99517003FC87E /* BlueWalletTests */,
|
00E356EF1AD99517003FC87E /* BlueWalletTests */,
|
||||||
@ -1031,7 +1037,7 @@
|
|||||||
);
|
);
|
||||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */,
|
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */,
|
||||||
B41B76832B66B2FF002C48D5 /* XCRemoteSwiftPackageReference "bugsnag-cocoa" */,
|
B41B76832B66B2FF002C48D5 /* XCRemoteSwiftPackageReference "bugsnag-cocoa" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||||
@ -1057,6 +1063,7 @@
|
|||||||
6DF25A9F249DB97E001D06F5 /* LaunchScreen.storyboard in Resources */,
|
6DF25A9F249DB97E001D06F5 /* LaunchScreen.storyboard in Resources */,
|
||||||
84E05A842721191B001A0D3A /* Settings.bundle in Resources */,
|
84E05A842721191B001A0D3A /* Settings.bundle in Resources */,
|
||||||
B4549F362B82B10D002E3153 /* ci_post_clone.sh in Resources */,
|
B4549F362B82B10D002E3153 /* ci_post_clone.sh in Resources */,
|
||||||
|
B41C2E562BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -1073,6 +1080,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
B41C2E582BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
6DD410B7266CAF5C0087DE03 /* Assets.xcassets in Resources */,
|
6DD410B7266CAF5C0087DE03 /* Assets.xcassets in Resources */,
|
||||||
6DD410AE266CAF1F0087DE03 /* fiatUnits.json in Resources */,
|
6DD410AE266CAF1F0087DE03 /* fiatUnits.json in Resources */,
|
||||||
);
|
);
|
||||||
@ -1092,6 +1100,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
B41C2E572BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
B4EE583C226703320003363C /* Assets.xcassets in Resources */,
|
B4EE583C226703320003363C /* Assets.xcassets in Resources */,
|
||||||
E5D4794B26781FC0007838C1 /* fiatUnits.json in Resources */,
|
E5D4794B26781FC0007838C1 /* fiatUnits.json in Resources */,
|
||||||
);
|
);
|
||||||
@ -1108,6 +1117,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
B41C2E592BB3DCB8000FE097 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
B4A29A352B55C990002A67DF /* LaunchScreen.storyboard in Resources */,
|
B4A29A352B55C990002A67DF /* LaunchScreen.storyboard in Resources */,
|
||||||
B4A29A372B55C990002A67DF /* Images.xcassets in Resources */,
|
B4A29A372B55C990002A67DF /* Images.xcassets in Resources */,
|
||||||
);
|
);
|
||||||
@ -2485,7 +2495,7 @@
|
|||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */ = {
|
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/EFPrefix/EFQRCode.git";
|
repositoryURL = "https://github.com/EFPrefix/EFQRCode.git";
|
||||||
requirement = {
|
requirement = {
|
||||||
@ -2498,7 +2508,7 @@
|
|||||||
repositoryURL = "https://github.com/bugsnag/bugsnag-cocoa";
|
repositoryURL = "https://github.com/bugsnag/bugsnag-cocoa";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = 6.28.0;
|
version = 6.28.1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
@ -2506,7 +2516,7 @@
|
|||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
6DFC806F24EA0B6C007B8700 /* EFQRCode */ = {
|
6DFC806F24EA0B6C007B8700 /* EFQRCode */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */;
|
package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */;
|
||||||
productName = EFQRCode;
|
productName = EFQRCode;
|
||||||
};
|
};
|
||||||
B41B76842B66B2FF002C48D5 /* Bugsnag */ = {
|
B41B76842B66B2FF002C48D5 /* Bugsnag */ = {
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"pins" : [
|
|
||||||
{
|
|
||||||
"identity" : "efqrcode",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/EFPrefix/EFQRCode.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "2991c2f318ad9529d93b2a73a382a3f9c72c64ce",
|
|
||||||
"version" : "6.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift_qrcodejs",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/ApolloZhu/swift_qrcodejs.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "374dc7f7b9e76c6aeb393f6a84590c6d387e1ecb",
|
|
||||||
"version" : "2.2.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version" : 2
|
|
||||||
}
|
|
@ -7,7 +7,7 @@
|
|||||||
"location" : "https://github.com/bugsnag/bugsnag-cocoa",
|
"location" : "https://github.com/bugsnag/bugsnag-cocoa",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "49f60b8dc2e94e7ede1114e2c39ba6ac0b576f42",
|
"revision" : "49f60b8dc2e94e7ede1114e2c39ba6ac0b576f42",
|
||||||
"version" : "6.28.0"
|
"version" : "6.28.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -29,5 +29,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version" : 3
|
"version" : 2
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#import <Bugsnag/Bugsnag.h>
|
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
#import <React/RCTLinkingManager.h>
|
#import <React/RCTLinkingManager.h>
|
||||||
#import <React/RCTBundleURLProvider.h>
|
#import <React/RCTBundleURLProvider.h>
|
||||||
@ -9,6 +8,7 @@
|
|||||||
#import <RNCPushNotificationIOS.h>
|
#import <RNCPushNotificationIOS.h>
|
||||||
#import "EventEmitter.h"
|
#import "EventEmitter.h"
|
||||||
#import <React/RCTRootView.h>
|
#import <React/RCTRootView.h>
|
||||||
|
#import <Bugsnag/Bugsnag.h>
|
||||||
|
|
||||||
@interface AppDelegate() <UNUserNotificationCenterDelegate>
|
@interface AppDelegate() <UNUserNotificationCenterDelegate>
|
||||||
|
|
||||||
@ -21,7 +21,10 @@
|
|||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
{
|
{
|
||||||
|
|
||||||
// Set the appType based on the current platform
|
NSUserDefaults *group = [[NSUserDefaults alloc] initWithSuiteName:@"group.io.bluewallet.bluewallet"];
|
||||||
|
NSString *isDoNotTrackEnabled = [group stringForKey:@"donottrack"];
|
||||||
|
if (![isDoNotTrackEnabled isEqualToString:@"1"]) {
|
||||||
|
// Set the appType based on the current platform
|
||||||
#if TARGET_OS_MACCATALYST
|
#if TARGET_OS_MACCATALYST
|
||||||
BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
|
BugsnagConfiguration *config = [BugsnagConfiguration loadConfig];
|
||||||
config.appType = @"macOS";
|
config.appType = @"macOS";
|
||||||
@ -30,6 +33,8 @@
|
|||||||
#else
|
#else
|
||||||
[Bugsnag start];
|
[Bugsnag start];
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[self copyDeviceUID];
|
[self copyDeviceUID];
|
||||||
|
|
||||||
|
@ -1,92 +1,134 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"size" : "24x24",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "Icon-48.png",
|
"filename" : "Icon-48.png",
|
||||||
"scale" : "2x",
|
"idiom" : "watch",
|
||||||
"role" : "notificationCenter",
|
"role" : "notificationCenter",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "24x24",
|
||||||
"subtype" : "38mm"
|
"subtype" : "38mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "27.5x27.5",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "Icon-55.png",
|
"filename" : "Icon-55.png",
|
||||||
"scale" : "2x",
|
"idiom" : "watch",
|
||||||
"role" : "notificationCenter",
|
"role" : "notificationCenter",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "27.5x27.5",
|
||||||
"subtype" : "42mm"
|
"subtype" : "42mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "58.png",
|
"filename" : "58.png",
|
||||||
"role" : "companionSettings",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "watch",
|
"idiom" : "watch",
|
||||||
"filename" : "87.png",
|
|
||||||
"role" : "companionSettings",
|
"role" : "companionSettings",
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "watch.png",
|
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "87.png",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"role" : "companionSettings",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "watch",
|
||||||
|
"role" : "notificationCenter",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "33x33",
|
||||||
|
"subtype" : "45mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "watch.png",
|
||||||
|
"idiom" : "watch",
|
||||||
"role" : "appLauncher",
|
"role" : "appLauncher",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40",
|
||||||
"subtype" : "38mm"
|
"subtype" : "38mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "44x44",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "Icon-88.png",
|
"filename" : "Icon-88.png",
|
||||||
"scale" : "2x",
|
"idiom" : "watch",
|
||||||
"role" : "appLauncher",
|
"role" : "appLauncher",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "44x44",
|
||||||
"subtype" : "40mm"
|
"subtype" : "40mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "50x50",
|
|
||||||
"idiom" : "watch",
|
"idiom" : "watch",
|
||||||
"filename" : "Icon-173.png",
|
|
||||||
"scale" : "2x",
|
|
||||||
"role" : "appLauncher",
|
"role" : "appLauncher",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "46x46",
|
||||||
|
"subtype" : "41mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-173.png",
|
||||||
|
"idiom" : "watch",
|
||||||
|
"role" : "appLauncher",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "50x50",
|
||||||
"subtype" : "44mm"
|
"subtype" : "44mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "86x86",
|
|
||||||
"idiom" : "watch",
|
"idiom" : "watch",
|
||||||
"filename" : "Icon-172.png",
|
"role" : "appLauncher",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
|
"size" : "51x51",
|
||||||
|
"subtype" : "45mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "watch",
|
||||||
|
"role" : "appLauncher",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "54x54",
|
||||||
|
"subtype" : "49mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-172.png",
|
||||||
|
"idiom" : "watch",
|
||||||
"role" : "quickLook",
|
"role" : "quickLook",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "86x86",
|
||||||
"subtype" : "38mm"
|
"subtype" : "38mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "98x98",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "Icon-196.png",
|
"filename" : "Icon-196.png",
|
||||||
"scale" : "2x",
|
"idiom" : "watch",
|
||||||
"role" : "quickLook",
|
"role" : "quickLook",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "98x98",
|
||||||
"subtype" : "42mm"
|
"subtype" : "42mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "108x108",
|
|
||||||
"idiom" : "watch",
|
|
||||||
"filename" : "group-copy-2@3x.png",
|
"filename" : "group-copy-2@3x.png",
|
||||||
"scale" : "2x",
|
"idiom" : "watch",
|
||||||
"role" : "quickLook",
|
"role" : "quickLook",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "108x108",
|
||||||
"subtype" : "44mm"
|
"subtype" : "44mm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "1024x1024",
|
"idiom" : "watch",
|
||||||
"idiom" : "watch-marketing",
|
"role" : "quickLook",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "117x117",
|
||||||
|
"subtype" : "45mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "watch",
|
||||||
|
"role" : "quickLook",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "129x129",
|
||||||
|
"subtype" : "49mm"
|
||||||
|
},
|
||||||
|
{
|
||||||
"filename" : "1024.png",
|
"filename" : "1024.png",
|
||||||
"scale" : "1x"
|
"idiom" : "watch-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +352,7 @@ PODS:
|
|||||||
- react-native-tcp-socket (6.0.6):
|
- react-native-tcp-socket (6.0.6):
|
||||||
- CocoaAsyncSocket
|
- CocoaAsyncSocket
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-webview (13.8.2):
|
- react-native-webview (13.8.4):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core
|
- React-Core
|
||||||
- react-native-widget-center (0.0.9):
|
- react-native-widget-center (0.0.9):
|
||||||
@ -485,7 +485,7 @@ PODS:
|
|||||||
- React-Core
|
- React-Core
|
||||||
- RNFS (2.20.0):
|
- RNFS (2.20.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNGestureHandler (2.15.0):
|
- RNGestureHandler (2.16.0):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNHandoff (0.0.3):
|
- RNHandoff (0.0.3):
|
||||||
@ -494,7 +494,7 @@ PODS:
|
|||||||
- React-Core
|
- React-Core
|
||||||
- RNLocalize (3.0.6):
|
- RNLocalize (3.0.6):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNPermissions (4.1.4):
|
- RNPermissions (4.1.5):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNPrivacySnapshot (1.0.0):
|
- RNPrivacySnapshot (1.0.0):
|
||||||
- React
|
- React
|
||||||
@ -508,10 +508,10 @@ PODS:
|
|||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core
|
- React-Core
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- RNScreens (3.29.0):
|
- RNScreens (3.30.1):
|
||||||
- RCT-Folly (= 2021.07.22.00)
|
- RCT-Folly (= 2021.07.22.00)
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNShare (10.0.2):
|
- RNShare (10.1.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- RNSVG (13.14.0):
|
- RNSVG (13.14.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
@ -822,7 +822,7 @@ SPEC CHECKSUMS:
|
|||||||
react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b
|
react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b
|
||||||
react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898
|
react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898
|
||||||
react-native-tcp-socket: e724380c910c2e704816ec817ed28f1342246ff7
|
react-native-tcp-socket: e724380c910c2e704816ec817ed28f1342246ff7
|
||||||
react-native-webview: 2adf6af211b3485284dc87a644d64e95243aa6e6
|
react-native-webview: 007d5c5a74de7243be6331221727639ed01ef760
|
||||||
react-native-widget-center: 12dfba20a4fa995850b52cf0afecf734397f4b9c
|
react-native-widget-center: 12dfba20a4fa995850b52cf0afecf734397f4b9c
|
||||||
React-NativeModulesApple: 694679e4193a49c09f0a76ee27ec09b2c466d59c
|
React-NativeModulesApple: 694679e4193a49c09f0a76ee27ec09b2c466d59c
|
||||||
React-perflogger: 63606aeab27683112e1bd4ef25bd099ec1cb03f8
|
React-perflogger: 63606aeab27683112e1bd4ef25bd099ec1cb03f8
|
||||||
@ -850,18 +850,18 @@ SPEC CHECKSUMS:
|
|||||||
RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31
|
RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31
|
||||||
RNDeviceInfo: 4f9c7cfd6b9db1b05eb919620a001cf35b536423
|
RNDeviceInfo: 4f9c7cfd6b9db1b05eb919620a001cf35b536423
|
||||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||||
RNGestureHandler: fc754e30bb46d093b46b47824e1a04e722fd8a3d
|
RNGestureHandler: b83cf821f60b7ec59827f0ed9e5b8c46b1de2c99
|
||||||
RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa
|
RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa
|
||||||
RNKeychain: bfe3d12bf4620fe488771c414530bf16e88f3678
|
RNKeychain: bfe3d12bf4620fe488771c414530bf16e88f3678
|
||||||
RNLocalize: 4222a3756cdbe2dc9a5bdf445765a4d2572107cb
|
RNLocalize: 4222a3756cdbe2dc9a5bdf445765a4d2572107cb
|
||||||
RNPermissions: 31223c0cf32b7623e6ec4cd13a7e4552fd43c71c
|
RNPermissions: 9fa74223844f437bc309e112994859dc47194829
|
||||||
RNPrivacySnapshot: 71919dde3c6a29dd332115409c2aec564afee8f4
|
RNPrivacySnapshot: 71919dde3c6a29dd332115409c2aec564afee8f4
|
||||||
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
|
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
|
||||||
RNRate: ef3bcff84f39bb1d1e41c5593d3eea4aab2bd73a
|
RNRate: ef3bcff84f39bb1d1e41c5593d3eea4aab2bd73a
|
||||||
RNReactNativeHapticFeedback: ec56a5f81c3941206fd85625fa669ffc7b4545f9
|
RNReactNativeHapticFeedback: ec56a5f81c3941206fd85625fa669ffc7b4545f9
|
||||||
RNReanimated: fc36806836aca984b797f01432abe31689663421
|
RNReanimated: fc36806836aca984b797f01432abe31689663421
|
||||||
RNScreens: 8ba3eeb8f5cb9f13662df564e785d64ef7214bf2
|
RNScreens: e5ee7223f7c8fa261f0c4594a0541c56ea99bbfc
|
||||||
RNShare: 859ff710211285676b0bcedd156c12437ea1d564
|
RNShare: b674d9f1cb0dc11116983bebd8712908a226a3ee
|
||||||
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
|
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
|
||||||
RNVectorIcons: 2b974a961e7ad079fafdd8af68b12210d5b4b28e
|
RNVectorIcons: 2b974a961e7ad079fafdd8af68b12210d5b4b28e
|
||||||
RNWatch: fd30ca40a5b5ef58dcbc195638e68219bc455236
|
RNWatch: fd30ca40a5b5ef58dcbc195638e68219bc455236
|
||||||
|
17
ios/PrivacyInfo.xcprivacy
Normal file
17
ios/PrivacyInfo.xcprivacy
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>CA92.1</string>
|
||||||
|
</array>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -4,13 +4,13 @@ echo "===== Installling CocoaPods ====="
|
|||||||
export HOMEBREW_NO_INSTALL_CLEANUP=TRUE
|
export HOMEBREW_NO_INSTALL_CLEANUP=TRUE
|
||||||
brew install cocoapods
|
brew install cocoapods
|
||||||
echo "===== Installing Node.js ====="
|
echo "===== Installing Node.js ====="
|
||||||
brew install node@21
|
brew install node@18
|
||||||
echo "===== Installing yarn (Xcode Cloud doenst like NPM ) ====="
|
echo "===== Installing yarn (Xcode Cloud doenst like NPM ) ====="
|
||||||
brew install yarn
|
brew install yarn
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
echo "===== Running yarn install ====="
|
echo "===== Running yarn install ====="
|
||||||
yarn install
|
npm install -y
|
||||||
echo "===== Running pod install ====="
|
echo "===== Running pod install ====="
|
||||||
cd ios
|
cd ios
|
||||||
pod install
|
pod install
|
@ -66,7 +66,7 @@ platform :ios do
|
|||||||
platform = options[:platform] || "ios" # Default to iOS if not specified
|
platform = options[:platform] || "ios" # Default to iOS if not specified
|
||||||
target_to_app_identifier.each do |target, app_identifier|
|
target_to_app_identifier.each do |target, app_identifier|
|
||||||
match(
|
match(
|
||||||
git_basic_authorization: ENV["MATCH_GIT_BASIC_AUTHORIZATION"],
|
git_basic_authorization: ENV["GIT_ACCESS_TOKEN"],
|
||||||
git_url: ENV["GIT_URL"],
|
git_url: ENV["GIT_URL"],
|
||||||
type: "appstore",
|
type: "appstore",
|
||||||
platform: platform,
|
platform: platform,
|
||||||
|
@ -403,7 +403,7 @@
|
|||||||
"details_delete": "Delete",
|
"details_delete": "Delete",
|
||||||
"details_delete_wallet": "Delete Wallet",
|
"details_delete_wallet": "Delete Wallet",
|
||||||
"details_derivation_path": "derivation path",
|
"details_derivation_path": "derivation path",
|
||||||
"details_display": "Display in Wallets List",
|
"details_display": "Display in Home Screen",
|
||||||
"details_export_backup": "Export/Backup",
|
"details_export_backup": "Export/Backup",
|
||||||
"details_export_history": "Export History to CSV",
|
"details_export_history": "Export History to CSV",
|
||||||
"details_master_fingerprint": "Master Fingerprint",
|
"details_master_fingerprint": "Master Fingerprint",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"USD": {
|
"USD": {
|
||||||
"endPointKey": "USD",
|
"endPointKey": "USD",
|
||||||
"locale": "en-US",
|
"locale": "en-US",
|
||||||
"source": "Bitstamp",
|
"source": "CoinGecko",
|
||||||
"symbol": "$"
|
"symbol": "$"
|
||||||
},
|
},
|
||||||
"AED": {
|
"AED": {
|
||||||
@ -92,13 +92,13 @@
|
|||||||
"EUR": {
|
"EUR": {
|
||||||
"endPointKey": "EUR",
|
"endPointKey": "EUR",
|
||||||
"locale": "en-IE",
|
"locale": "en-IE",
|
||||||
"source": "Bitstamp",
|
"source": "CoinGecko",
|
||||||
"symbol": "€"
|
"symbol": "€"
|
||||||
},
|
},
|
||||||
"GBP": {
|
"GBP": {
|
||||||
"endPointKey": "GBP",
|
"endPointKey": "GBP",
|
||||||
"locale": "en-GB",
|
"locale": "en-GB",
|
||||||
"source": "Bitstamp",
|
"source": "CoinGecko",
|
||||||
"symbol": "£"
|
"symbol": "£"
|
||||||
},
|
},
|
||||||
"HRK": {
|
"HRK": {
|
||||||
|
70
package-lock.json
generated
70
package-lock.json
generated
@ -68,7 +68,7 @@
|
|||||||
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4",
|
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4",
|
||||||
"react-native-elements": "3.4.3",
|
"react-native-elements": "3.4.3",
|
||||||
"react-native-fs": "2.20.0",
|
"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-handoff": "https://github.com/BlueWallet/react-native-handoff#31d005f93d31099d0e564590a3bbd052b8a02b39",
|
||||||
"react-native-haptic-feedback": "2.2.0",
|
"react-native-haptic-feedback": "2.2.0",
|
||||||
"react-native-idle-timer": "https://github.com/BlueWallet/react-native-idle-timer#8587876d68ab5920e79619726aeca9e672beaf2b",
|
"react-native-idle-timer": "https://github.com/BlueWallet/react-native-idle-timer#8587876d68ab5920e79619726aeca9e672beaf2b",
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"react-native-modal": "13.0.1",
|
"react-native-modal": "13.0.1",
|
||||||
"react-native-obscure": "https://github.com/BlueWallet/react-native-obscure.git#f4b83b4a261e39b1f5ed4a45ac5bcabc8a59eadb",
|
"react-native-obscure": "https://github.com/BlueWallet/react-native-obscure.git#f4b83b4a261e39b1f5ed4a45ac5bcabc8a59eadb",
|
||||||
"react-native-passcode-auth": "https://github.com/BlueWallet/react-native-passcode-auth#a2ff977ba92b36f8d0a5567f59c05cc608e8bd12",
|
"react-native-passcode-auth": "https://github.com/BlueWallet/react-native-passcode-auth#a2ff977ba92b36f8d0a5567f59c05cc608e8bd12",
|
||||||
"react-native-permissions": "4.1.4",
|
"react-native-permissions": "4.1.5",
|
||||||
"react-native-privacy-snapshot": "https://github.com/BlueWallet/react-native-privacy-snapshot#529e4627d93f67752a27e82a040ff7b64dca0783",
|
"react-native-privacy-snapshot": "https://github.com/BlueWallet/react-native-privacy-snapshot#529e4627d93f67752a27e82a040ff7b64dca0783",
|
||||||
"react-native-prompt-android": "https://github.com/BlueWallet/react-native-prompt-android#ed168d66fed556bc2ed07cf498770f058b78a376",
|
"react-native-prompt-android": "https://github.com/BlueWallet/react-native-prompt-android#ed168d66fed556bc2ed07cf498770f058b78a376",
|
||||||
"react-native-push-notification": "8.1.1",
|
"react-native-push-notification": "8.1.1",
|
||||||
@ -90,14 +90,14 @@
|
|||||||
"react-native-rate": "1.2.12",
|
"react-native-rate": "1.2.12",
|
||||||
"react-native-reanimated": "3.8.1",
|
"react-native-reanimated": "3.8.1",
|
||||||
"react-native-safe-area-context": "4.9.0",
|
"react-native-safe-area-context": "4.9.0",
|
||||||
"react-native-screens": "3.29.0",
|
"react-native-screens": "3.30.1",
|
||||||
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
|
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
|
||||||
"react-native-share": "10.0.2",
|
"react-native-share": "10.1.0",
|
||||||
"react-native-svg": "13.14.0",
|
"react-native-svg": "13.14.0",
|
||||||
"react-native-tcp-socket": "6.0.6",
|
"react-native-tcp-socket": "6.0.6",
|
||||||
"react-native-vector-icons": "10.0.3",
|
"react-native-vector-icons": "10.0.3",
|
||||||
"react-native-watch-connectivity": "1.1.0",
|
"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",
|
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38",
|
||||||
"readable-stream": "3.6.2",
|
"readable-stream": "3.6.2",
|
||||||
"realm": "12.6.2",
|
"realm": "12.6.2",
|
||||||
@ -19423,9 +19423,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-gesture-handler": {
|
"node_modules/react-native-gesture-handler": {
|
||||||
"version": "2.15.0",
|
"version": "2.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.0.tgz",
|
||||||
"integrity": "sha512-cmMGW8k86o/xgVTBZZOPohvR5re4Vh65PUxH4HbBBJAYTog4aN4wTVTUlnoky01HuSN8/X4h3tI/K3XLPoDnsg==",
|
"integrity": "sha512-1hFkx7RIfeJSyTQQ0Nkv4icFVZ5+XjQkd47OgZMBFzoB7ecL+nFSz8KLi3OCWOhq+nbHpSPlSG5VF3CQNCJpWA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@egjs/hammerjs": "^2.0.17",
|
"@egjs/hammerjs": "^2.0.17",
|
||||||
"hoist-non-react-statics": "^3.3.0",
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
@ -19542,9 +19542,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/react-native-permissions": {
|
"node_modules/react-native-permissions": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-4.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-4.1.5.tgz",
|
||||||
"integrity": "sha512-el6u90VZNFDEtmHpSheirwRhGvs6M5rSZcoqIqB128IPO00f2c1q+PP4kEaM1u19Q0ldQ+R+S7C/l8Zrduy6JQ==",
|
"integrity": "sha512-r6VMRacASmtRHS+GZ+5HQCp9p9kiE+UU9magHOZCXZLTJitdTuVHWZRrb4v4oqZGU+zAp3mZhTQftuMMv+WLUg==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18.1.0",
|
"react": ">=18.1.0",
|
||||||
"react-native": ">=0.70.0",
|
"react-native": ">=0.70.0",
|
||||||
@ -19671,9 +19671,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-screens": {
|
"node_modules/react-native-screens": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.30.1.tgz",
|
||||||
"integrity": "sha512-yB1GoAMamFAcYf4ku94uBPn0/ani9QG7NdI98beJ5cet2YFESYYzuEIuU+kt+CNRcO8qqKeugxlfgAa3HyTqlg==",
|
"integrity": "sha512-/muEvjocCtFb+j5J3YmLvB25+f4rIU8hnnxgGTkXcAf2omPBY8uhPjJaaFUlvj64VEoEzJcRpugbXWsjfPPIFg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-freeze": "^1.0.0",
|
"react-freeze": "^1.0.0",
|
||||||
"warn-once": "^0.1.0"
|
"warn-once": "^0.1.0"
|
||||||
@ -19689,9 +19689,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/react-native-share": {
|
"node_modules/react-native-share": {
|
||||||
"version": "10.0.2",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-10.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-10.1.0.tgz",
|
||||||
"integrity": "sha512-EZs4MtsyauAI1zP8xXT1hIFB/pXOZJNDCKcgCpEfTZFXgCUzz8MDVbI1ocP2hA59XHRSkqAQdbJ0BFTpjxOBlg==",
|
"integrity": "sha512-fKKvwaZe5s3HW0tcRKyR5AWvAfXvkk0FgTw1nYWYjI4gNqntXbMjRqWZed8Hmd1MvIJS17K/ELPges0tsxbp3g==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
@ -19819,9 +19819,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native-webview": {
|
"node_modules/react-native-webview": {
|
||||||
"version": "13.8.2",
|
"version": "13.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.8.4.tgz",
|
||||||
"integrity": "sha512-4qBb04XPiLdfAbpU0x7RsMX4iIrggIvBVfJq4yqQhQwY+uJARJaOAZw9+KfA0/kNYQGKHSKQakXLAqQulUrlvQ==",
|
"integrity": "sha512-dFoM9EfkAb++ZzycZyKRnjZtNUn85cf6bWp1iBlkgyNml7ULzR1gfaPT3qESoA3K1RfTmf5Xhw0M2In2A3a3wg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"escape-string-regexp": "2.0.0",
|
"escape-string-regexp": "2.0.0",
|
||||||
"invariant": "2.2.4"
|
"invariant": "2.2.4"
|
||||||
@ -37086,9 +37086,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-native-gesture-handler": {
|
"react-native-gesture-handler": {
|
||||||
"version": "2.15.0",
|
"version": "2.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.0.tgz",
|
||||||
"integrity": "sha512-cmMGW8k86o/xgVTBZZOPohvR5re4Vh65PUxH4HbBBJAYTog4aN4wTVTUlnoky01HuSN8/X4h3tI/K3XLPoDnsg==",
|
"integrity": "sha512-1hFkx7RIfeJSyTQQ0Nkv4icFVZ5+XjQkd47OgZMBFzoB7ecL+nFSz8KLi3OCWOhq+nbHpSPlSG5VF3CQNCJpWA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@egjs/hammerjs": "^2.0.17",
|
"@egjs/hammerjs": "^2.0.17",
|
||||||
"hoist-non-react-statics": "^3.3.0",
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
@ -37159,9 +37159,9 @@
|
|||||||
"from": "react-native-passcode-auth@https://github.com/BlueWallet/react-native-passcode-auth#a2ff977ba92b36f8d0a5567f59c05cc608e8bd12"
|
"from": "react-native-passcode-auth@https://github.com/BlueWallet/react-native-passcode-auth#a2ff977ba92b36f8d0a5567f59c05cc608e8bd12"
|
||||||
},
|
},
|
||||||
"react-native-permissions": {
|
"react-native-permissions": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-4.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-4.1.5.tgz",
|
||||||
"integrity": "sha512-el6u90VZNFDEtmHpSheirwRhGvs6M5rSZcoqIqB128IPO00f2c1q+PP4kEaM1u19Q0ldQ+R+S7C/l8Zrduy6JQ=="
|
"integrity": "sha512-r6VMRacASmtRHS+GZ+5HQCp9p9kiE+UU9magHOZCXZLTJitdTuVHWZRrb4v4oqZGU+zAp3mZhTQftuMMv+WLUg=="
|
||||||
},
|
},
|
||||||
"react-native-privacy-snapshot": {
|
"react-native-privacy-snapshot": {
|
||||||
"version": "git+ssh://git@github.com/BlueWallet/react-native-privacy-snapshot.git#529e4627d93f67752a27e82a040ff7b64dca0783",
|
"version": "git+ssh://git@github.com/BlueWallet/react-native-privacy-snapshot.git#529e4627d93f67752a27e82a040ff7b64dca0783",
|
||||||
@ -37252,9 +37252,9 @@
|
|||||||
"integrity": "sha512-/OJD9Pb8IURyvn+1tWTszWPJqsbZ4hyHBU9P0xhOmk7h5owSuqL0zkfagU0pg7Vh0G2NKQkaPpUKUMMCUMDh/w=="
|
"integrity": "sha512-/OJD9Pb8IURyvn+1tWTszWPJqsbZ4hyHBU9P0xhOmk7h5owSuqL0zkfagU0pg7Vh0G2NKQkaPpUKUMMCUMDh/w=="
|
||||||
},
|
},
|
||||||
"react-native-screens": {
|
"react-native-screens": {
|
||||||
"version": "3.29.0",
|
"version": "3.30.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.30.1.tgz",
|
||||||
"integrity": "sha512-yB1GoAMamFAcYf4ku94uBPn0/ani9QG7NdI98beJ5cet2YFESYYzuEIuU+kt+CNRcO8qqKeugxlfgAa3HyTqlg==",
|
"integrity": "sha512-/muEvjocCtFb+j5J3YmLvB25+f4rIU8hnnxgGTkXcAf2omPBY8uhPjJaaFUlvj64VEoEzJcRpugbXWsjfPPIFg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"react-freeze": "^1.0.0",
|
"react-freeze": "^1.0.0",
|
||||||
"warn-once": "^0.1.0"
|
"warn-once": "^0.1.0"
|
||||||
@ -37265,9 +37265,9 @@
|
|||||||
"from": "react-native-secure-key-store@https://github.com/BlueWallet/react-native-secure-key-store#2076b48"
|
"from": "react-native-secure-key-store@https://github.com/BlueWallet/react-native-secure-key-store#2076b48"
|
||||||
},
|
},
|
||||||
"react-native-share": {
|
"react-native-share": {
|
||||||
"version": "10.0.2",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-10.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-10.1.0.tgz",
|
||||||
"integrity": "sha512-EZs4MtsyauAI1zP8xXT1hIFB/pXOZJNDCKcgCpEfTZFXgCUzz8MDVbI1ocP2hA59XHRSkqAQdbJ0BFTpjxOBlg=="
|
"integrity": "sha512-fKKvwaZe5s3HW0tcRKyR5AWvAfXvkk0FgTw1nYWYjI4gNqntXbMjRqWZed8Hmd1MvIJS17K/ELPges0tsxbp3g=="
|
||||||
},
|
},
|
||||||
"react-native-size-matters": {
|
"react-native-size-matters": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.1",
|
||||||
@ -37352,9 +37352,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-native-webview": {
|
"react-native-webview": {
|
||||||
"version": "13.8.2",
|
"version": "13.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.8.4.tgz",
|
||||||
"integrity": "sha512-4qBb04XPiLdfAbpU0x7RsMX4iIrggIvBVfJq4yqQhQwY+uJARJaOAZw9+KfA0/kNYQGKHSKQakXLAqQulUrlvQ==",
|
"integrity": "sha512-dFoM9EfkAb++ZzycZyKRnjZtNUn85cf6bWp1iBlkgyNml7ULzR1gfaPT3qESoA3K1RfTmf5Xhw0M2In2A3a3wg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"escape-string-regexp": "2.0.0",
|
"escape-string-regexp": "2.0.0",
|
||||||
"invariant": "2.2.4"
|
"invariant": "2.2.4"
|
||||||
|
@ -154,7 +154,7 @@
|
|||||||
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4",
|
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4",
|
||||||
"react-native-elements": "3.4.3",
|
"react-native-elements": "3.4.3",
|
||||||
"react-native-fs": "2.20.0",
|
"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-handoff": "https://github.com/BlueWallet/react-native-handoff#31d005f93d31099d0e564590a3bbd052b8a02b39",
|
||||||
"react-native-haptic-feedback": "2.2.0",
|
"react-native-haptic-feedback": "2.2.0",
|
||||||
"react-native-idle-timer": "https://github.com/BlueWallet/react-native-idle-timer#8587876d68ab5920e79619726aeca9e672beaf2b",
|
"react-native-idle-timer": "https://github.com/BlueWallet/react-native-idle-timer#8587876d68ab5920e79619726aeca9e672beaf2b",
|
||||||
@ -176,14 +176,14 @@
|
|||||||
"react-native-rate": "1.2.12",
|
"react-native-rate": "1.2.12",
|
||||||
"react-native-reanimated": "3.8.1",
|
"react-native-reanimated": "3.8.1",
|
||||||
"react-native-safe-area-context": "4.9.0",
|
"react-native-safe-area-context": "4.9.0",
|
||||||
"react-native-screens": "3.29.0",
|
"react-native-screens": "3.30.1",
|
||||||
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
|
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
|
||||||
"react-native-share": "10.1.0",
|
"react-native-share": "10.1.0",
|
||||||
"react-native-svg": "13.14.0",
|
"react-native-svg": "13.14.0",
|
||||||
"react-native-tcp-socket": "6.0.6",
|
"react-native-tcp-socket": "6.0.6",
|
||||||
"react-native-vector-icons": "10.0.3",
|
"react-native-vector-icons": "10.0.3",
|
||||||
"react-native-watch-connectivity": "1.1.0",
|
"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",
|
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38",
|
||||||
"readable-stream": "3.6.2",
|
"readable-stream": "3.6.2",
|
||||||
"realm": "12.6.2",
|
"realm": "12.6.2",
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';
|
import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';
|
||||||
|
|
||||||
import { BlueAlertWalletExportReminder, BlueDismissKeyboardInputAccessory, BlueLoading } from '../../BlueComponents';
|
import { BlueDismissKeyboardInputAccessory, BlueLoading } from '../../BlueComponents';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import AmountInput from '../../components/AmountInput';
|
import AmountInput from '../../components/AmountInput';
|
||||||
import * as NavigationService from '../../NavigationService';
|
import * as NavigationService from '../../NavigationService';
|
||||||
@ -32,11 +32,13 @@ import { useTheme } from '../../components/themes';
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import { btcToSatoshi, fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
import { btcToSatoshi, fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
||||||
|
import { presentWalletExportReminder } from '../../helpers/presentWalletExportReminder';
|
||||||
|
|
||||||
const LNDCreateInvoice = () => {
|
const LNDCreateInvoice = () => {
|
||||||
const { wallets, saveToDisk, setSelectedWalletID } = useContext(BlueStorageContext);
|
const { wallets, saveToDisk, setSelectedWalletID } = useContext(BlueStorageContext);
|
||||||
const { walletID, uri } = useRoute().params;
|
const { walletID, uri } = useRoute().params;
|
||||||
const wallet = useRef(wallets.find(item => item.getID() === walletID) || wallets.find(item => item.chain === Chain.OFFCHAIN));
|
const wallet = useRef(wallets.find(item => item.getID() === walletID) || wallets.find(item => item.chain === Chain.OFFCHAIN));
|
||||||
|
const createInvoiceRef = useRef();
|
||||||
const { name } = useRoute();
|
const { name } = useRoute();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const { navigate, getParent, goBack, pop, setParams } = useNavigation();
|
const { navigate, getParent, goBack, pop, setParams } = useNavigation();
|
||||||
@ -117,9 +119,11 @@ const LNDCreateInvoice = () => {
|
|||||||
if (wallet.current.getUserHasSavedExport()) {
|
if (wallet.current.getUserHasSavedExport()) {
|
||||||
renderReceiveDetails();
|
renderReceiveDetails();
|
||||||
} else {
|
} else {
|
||||||
BlueAlertWalletExportReminder({
|
presentWalletExportReminder()
|
||||||
onSuccess: () => renderReceiveDetails(),
|
.then(() => {
|
||||||
onFailure: () => {
|
renderReceiveDetails();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
getParent().pop();
|
getParent().pop();
|
||||||
NavigationService.navigate('WalletExportRoot', {
|
NavigationService.navigate('WalletExportRoot', {
|
||||||
screen: 'WalletExport',
|
screen: 'WalletExport',
|
||||||
@ -127,8 +131,7 @@ const LNDCreateInvoice = () => {
|
|||||||
walletID,
|
walletID,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
|
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
|
||||||
@ -192,7 +195,7 @@ const LNDCreateInvoice = () => {
|
|||||||
// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
|
// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
|
||||||
/** @type LightningCustodianWallet */
|
/** @type LightningCustodianWallet */
|
||||||
const decoded = await wallet.current.decodeInvoice(invoiceRequest);
|
const decoded = await wallet.current.decodeInvoice(invoiceRequest);
|
||||||
await Notifications.tryToObtainPermissions();
|
await Notifications.tryToObtainPermissions(createInvoiceRef);
|
||||||
Notifications.majorTomToGroundControl([], [decoded.payment_hash], []);
|
Notifications.majorTomToGroundControl([], [decoded.payment_hash], []);
|
||||||
|
|
||||||
// send to lnurl-withdraw callback url if that exists
|
// send to lnurl-withdraw callback url if that exists
|
||||||
@ -315,7 +318,11 @@ const LNDCreateInvoice = () => {
|
|||||||
const renderCreateButton = () => {
|
const renderCreateButton = () => {
|
||||||
return (
|
return (
|
||||||
<View style={styles.createButton}>
|
<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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { View, Share, StyleSheet } from 'react-native';
|
import { View, Share, StyleSheet } from 'react-native';
|
||||||
import { useNavigation, useRoute } from '@react-navigation/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 navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -10,6 +10,7 @@ import presentAlert from '../../components/Alert';
|
|||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const LNDViewAdditionalInvoiceInformation = () => {
|
const LNDViewAdditionalInvoiceInformation = () => {
|
||||||
const { walletID } = useRoute().params;
|
const { walletID } = useRoute().params;
|
||||||
@ -60,7 +61,7 @@ const LNDViewAdditionalInvoiceInformation = () => {
|
|||||||
</View>
|
</View>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText>
|
<BlueText>{loc.lndViewInvoice.open_direct_channel}</BlueText>
|
||||||
<BlueCopyTextToClipboard text={walletInfo.uris[0]} />
|
<CopyTextToClipboard text={walletInfo.uris[0]} />
|
||||||
<View style={styles.share}>
|
<View style={styles.share}>
|
||||||
<Button
|
<Button
|
||||||
icon={{
|
icon={{
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
import { View, StyleSheet } from 'react-native';
|
||||||
import { useRoute } from '@react-navigation/native';
|
import { useRoute } from '@react-navigation/native';
|
||||||
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
|
import { BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const LNDViewAdditionalInvoicePreImage = () => {
|
const LNDViewAdditionalInvoicePreImage = () => {
|
||||||
// state = { walletInfo: undefined };
|
// state = { walletInfo: undefined };
|
||||||
@ -27,7 +28,7 @@ const LNDViewAdditionalInvoicePreImage = () => {
|
|||||||
<QRCodeComponent value={preImageData} size={300} logoSize={90} />
|
<QRCodeComponent value={preImageData} size={300} logoSize={90} />
|
||||||
</View>
|
</View>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<BlueCopyTextToClipboard text={preImageData} />
|
<CopyTextToClipboard text={preImageData} />
|
||||||
</View>
|
</View>
|
||||||
</SafeArea>
|
</SafeArea>
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,7 @@ import Share from 'react-native-share';
|
|||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||||
import { useNavigation, useNavigationState, useRoute } from '@react-navigation/native';
|
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 navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -15,6 +15,7 @@ import { useTheme } from '../../components/themes';
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const LNDViewInvoice = () => {
|
const LNDViewInvoice = () => {
|
||||||
const { invoice, walletID } = useRoute().params;
|
const { invoice, walletID } = useRoute().params;
|
||||||
@ -252,7 +253,7 @@ const LNDViewInvoice = () => {
|
|||||||
{loc.lndViewInvoice.for} {invoice.description}
|
{loc.lndViewInvoice.for} {invoice.description}
|
||||||
</BlueText>
|
</BlueText>
|
||||||
)}
|
)}
|
||||||
<BlueCopyTextToClipboard truncated text={invoice.payment_request} />
|
<CopyTextToClipboard truncated text={invoice.payment_request} />
|
||||||
|
|
||||||
<Button onPress={handleOnSharePressed} title={loc.receive.details_share} />
|
<Button onPress={handleOnSharePressed} title={loc.receive.details_share} />
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { View, Text, Linking, StyleSheet, Image, ScrollView } from 'react-native';
|
import { View, Linking, StyleSheet, Image, ScrollView } from 'react-native';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
import { BlueButtonLink, BlueCard, BlueLoading, BlueSpacing20, BlueSpacing40, BlueText } from '../../BlueComponents';
|
import { BlueButtonLink, BlueCard, BlueLoading, BlueSpacing20, BlueSpacing40, BlueText } from '../../BlueComponents';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
@ -86,7 +86,7 @@ export default class LnurlPaySuccess extends Component {
|
|||||||
{(preamble || url || message) && (
|
{(preamble || url || message) && (
|
||||||
<BlueCard>
|
<BlueCard>
|
||||||
<View style={styles.successContainer}>
|
<View style={styles.successContainer}>
|
||||||
<Text style={styles.successText}>{preamble}</Text>
|
<BlueText style={styles.successText}>{preamble}</BlueText>
|
||||||
{url ? (
|
{url ? (
|
||||||
<BlueButtonLink
|
<BlueButtonLink
|
||||||
title={url}
|
title={url}
|
||||||
@ -95,9 +95,7 @@ export default class LnurlPaySuccess extends Component {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Text selectable style={{ ...styles.successText, ...styles.successValue }}>
|
<BlueText selectable>{message}</BlueText>
|
||||||
{message}
|
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</BlueCard>
|
</BlueCard>
|
||||||
@ -167,9 +165,6 @@ const styles = StyleSheet.create({
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
margin: 4,
|
margin: 4,
|
||||||
},
|
},
|
||||||
successValue: {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
},
|
|
||||||
description: {
|
description: {
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
},
|
},
|
||||||
|
@ -10,19 +10,10 @@ import {
|
|||||||
TextInput,
|
TextInput,
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { useNavigation, useRoute, useFocusEffect } from '@react-navigation/native';
|
import { useRoute, useFocusEffect } from '@react-navigation/native';
|
||||||
import Share from 'react-native-share';
|
import Share from 'react-native-share';
|
||||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||||
import {
|
import { BlueLoading, BlueButtonLink, BlueText, BlueSpacing20, BlueCard, BlueSpacing40 } from '../../BlueComponents';
|
||||||
BlueLoading,
|
|
||||||
BlueCopyTextToClipboard,
|
|
||||||
BlueButtonLink,
|
|
||||||
BlueText,
|
|
||||||
BlueSpacing20,
|
|
||||||
BlueAlertWalletExportReminder,
|
|
||||||
BlueCard,
|
|
||||||
BlueSpacing40,
|
|
||||||
} from '../../BlueComponents';
|
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import BottomModal from '../../components/BottomModal';
|
import BottomModal from '../../components/BottomModal';
|
||||||
import { Chain, BitcoinUnit } from '../../models/bitcoinUnits';
|
import { Chain, BitcoinUnit } from '../../models/bitcoinUnits';
|
||||||
@ -39,6 +30,8 @@ import { useTheme } from '../../components/themes';
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import { fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
import { fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
||||||
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const ReceiveDetails = () => {
|
const ReceiveDetails = () => {
|
||||||
const { walletID, address } = useRoute().params;
|
const { walletID, address } = useRoute().params;
|
||||||
@ -53,7 +46,7 @@ const ReceiveDetails = () => {
|
|||||||
const [showPendingBalance, setShowPendingBalance] = useState(false);
|
const [showPendingBalance, setShowPendingBalance] = useState(false);
|
||||||
const [showConfirmedBalance, setShowConfirmedBalance] = useState(false);
|
const [showConfirmedBalance, setShowConfirmedBalance] = useState(false);
|
||||||
const [showAddress, setShowAddress] = useState(false);
|
const [showAddress, setShowAddress] = useState(false);
|
||||||
const { navigate, goBack, setParams } = useNavigation();
|
const { goBack, setParams } = useExtendedNavigation();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const [intervalMs, setIntervalMs] = useState(5000);
|
const [intervalMs, setIntervalMs] = useState(5000);
|
||||||
const [eta, setEta] = useState('');
|
const [eta, setEta] = useState('');
|
||||||
@ -101,34 +94,27 @@ const ReceiveDetails = () => {
|
|||||||
|
|
||||||
// re-fetching address balance periodically
|
// re-fetching address balance periodically
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('receive/defails - useEffect');
|
console.log('receive/details - useEffect');
|
||||||
|
|
||||||
if (fetchAddressInterval.current) {
|
const intervalId = setInterval(async () => {
|
||||||
// interval already exists, lets cleanup it and recreate, so theres no duplicate intervals
|
|
||||||
clearInterval(fetchAddressInterval.current);
|
|
||||||
fetchAddressInterval.current = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchAddressInterval.current = setInterval(async () => {
|
|
||||||
try {
|
try {
|
||||||
const decoded = DeeplinkSchemaMatch.bip21decode(bip21encoded);
|
const decoded = DeeplinkSchemaMatch.bip21decode(bip21encoded);
|
||||||
const address2use = address || decoded.address;
|
const addressToUse = address || decoded.address;
|
||||||
if (!address2use) return;
|
if (!addressToUse) return;
|
||||||
|
|
||||||
console.log('checking address', address2use, 'for balance...');
|
console.log('checking address', addressToUse, 'for balance...');
|
||||||
const balance = await BlueElectrum.getBalanceByAddress(address2use);
|
const balance = await BlueElectrum.getBalanceByAddress(addressToUse);
|
||||||
console.log('...got', balance);
|
console.log('...got', balance);
|
||||||
|
|
||||||
if (balance.unconfirmed > 0) {
|
if (balance.unconfirmed > 0) {
|
||||||
if (initialConfirmed === 0 && initialUnconfirmed === 0) {
|
if (initialConfirmed === 0 && initialUnconfirmed === 0) {
|
||||||
// saving initial values for later (when tx gets confirmed)
|
|
||||||
setInitialConfirmed(balance.confirmed);
|
setInitialConfirmed(balance.confirmed);
|
||||||
setInitialUnconfirmed(balance.unconfirmed);
|
setInitialUnconfirmed(balance.unconfirmed);
|
||||||
setIntervalMs(25000);
|
setIntervalMs(25000);
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.ImpactHeavy);
|
triggerHapticFeedback(HapticFeedbackTypes.ImpactHeavy);
|
||||||
}
|
}
|
||||||
|
|
||||||
const txs = await BlueElectrum.getMempoolTransactionsByAddress(address2use);
|
const txs = await BlueElectrum.getMempoolTransactionsByAddress(addressToUse);
|
||||||
const tx = txs.pop();
|
const tx = txs.pop();
|
||||||
if (tx) {
|
if (tx) {
|
||||||
const rez = await BlueElectrum.multiGetTransactionByTxid([tx.tx_hash], 10, true);
|
const rez = await BlueElectrum.multiGetTransactionByTxid([tx.tx_hash], 10, true);
|
||||||
@ -137,11 +123,9 @@ const ReceiveDetails = () => {
|
|||||||
const fees = await BlueElectrum.estimateFees();
|
const fees = await BlueElectrum.estimateFees();
|
||||||
if (satPerVbyte >= fees.fast) {
|
if (satPerVbyte >= fees.fast) {
|
||||||
setEta(loc.formatString(loc.transactions.eta_10m));
|
setEta(loc.formatString(loc.transactions.eta_10m));
|
||||||
}
|
} else if (satPerVbyte >= fees.medium) {
|
||||||
if (satPerVbyte >= fees.medium && satPerVbyte < fees.fast) {
|
|
||||||
setEta(loc.formatString(loc.transactions.eta_3h));
|
setEta(loc.formatString(loc.transactions.eta_3h));
|
||||||
}
|
} else {
|
||||||
if (satPerVbyte < fees.medium) {
|
|
||||||
setEta(loc.formatString(loc.transactions.eta_1d));
|
setEta(loc.formatString(loc.transactions.eta_1d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,7 +142,6 @@ const ReceiveDetails = () => {
|
|||||||
} else if (balance.unconfirmed === 0 && initialUnconfirmed !== 0) {
|
} 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
|
// now, handling a case when unconfirmed == 0, but in past it wasnt (i.e. it changed while user was
|
||||||
// staring at the screen)
|
// staring at the screen)
|
||||||
|
|
||||||
const balanceToShow = balance.confirmed - initialConfirmed;
|
const balanceToShow = balance.confirmed - initialConfirmed;
|
||||||
|
|
||||||
if (balanceToShow > 0) {
|
if (balanceToShow > 0) {
|
||||||
@ -166,17 +149,12 @@ const ReceiveDetails = () => {
|
|||||||
setShowConfirmedBalance(true);
|
setShowConfirmedBalance(true);
|
||||||
setShowPendingBalance(false);
|
setShowPendingBalance(false);
|
||||||
setShowAddress(false);
|
setShowAddress(false);
|
||||||
|
|
||||||
clearInterval(fetchAddressInterval.current);
|
|
||||||
fetchAddressInterval.current = undefined;
|
|
||||||
|
|
||||||
setDisplayBalance(
|
setDisplayBalance(
|
||||||
loc.formatString(loc.transactions.received_with_amount, {
|
loc.formatString(loc.transactions.received_with_amount, {
|
||||||
amt1: formatBalance(balanceToShow, BitcoinUnit.LOCAL_CURRENCY, true).toString(),
|
amt1: formatBalance(balanceToShow, BitcoinUnit.LOCAL_CURRENCY, true).toString(),
|
||||||
amt2: formatBalance(balanceToShow, BitcoinUnit.BTC, true).toString(),
|
amt2: formatBalance(balanceToShow, BitcoinUnit.BTC, true).toString(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
fetchAndSaveWalletTransactions(walletID);
|
fetchAndSaveWalletTransactions(walletID);
|
||||||
} else {
|
} else {
|
||||||
// rare case, but probable. transaction evicted from mempool (maybe cancelled by the sender)
|
// rare case, but probable. transaction evicted from mempool (maybe cancelled by the sender)
|
||||||
@ -189,6 +167,8 @@ const ReceiveDetails = () => {
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}, intervalMs);
|
}, intervalMs);
|
||||||
|
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
}, [bip21encoded, address, initialConfirmed, initialUnconfirmed, intervalMs, fetchAndSaveWalletTransactions, walletID]);
|
}, [bip21encoded, address, initialConfirmed, initialUnconfirmed, intervalMs, fetchAndSaveWalletTransactions, walletID]);
|
||||||
|
|
||||||
const renderConfirmedBalance = () => {
|
const renderConfirmedBalance = () => {
|
||||||
@ -271,7 +251,7 @@ const ReceiveDetails = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<QRCodeComponent value={bip21encoded} />
|
<QRCodeComponent value={bip21encoded} />
|
||||||
<BlueCopyTextToClipboard text={isCustom ? bip21encoded : address} ref={receiveAddressButton} />
|
<CopyTextToClipboard text={isCustom ? bip21encoded : address} ref={receiveAddressButton} />
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.share}>
|
<View style={styles.share}>
|
||||||
<BlueCard>
|
<BlueCard>
|
||||||
@ -296,7 +276,7 @@ const ReceiveDetails = () => {
|
|||||||
let newAddress;
|
let newAddress;
|
||||||
if (address) {
|
if (address) {
|
||||||
setAddressBIP21Encoded(address);
|
setAddressBIP21Encoded(address);
|
||||||
await Notifications.tryToObtainPermissions(receiveAddressButton.current);
|
await Notifications.tryToObtainPermissions(receiveAddressButton);
|
||||||
Notifications.majorTomToGroundControl([address], [], []);
|
Notifications.majorTomToGroundControl([address], [], []);
|
||||||
} else {
|
} else {
|
||||||
if (wallet.chain === Chain.ONCHAIN) {
|
if (wallet.chain === Chain.ONCHAIN) {
|
||||||
@ -324,7 +304,7 @@ const ReceiveDetails = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setAddressBIP21Encoded(newAddress);
|
setAddressBIP21Encoded(newAddress);
|
||||||
await Notifications.tryToObtainPermissions(receiveAddressButton.current);
|
await Notifications.tryToObtainPermissions(receiveAddressButton);
|
||||||
Notifications.majorTomToGroundControl([newAddress], [], []);
|
Notifications.majorTomToGroundControl([newAddress], [], []);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@ -341,22 +321,7 @@ const ReceiveDetails = () => {
|
|||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
const task = InteractionManager.runAfterInteractions(async () => {
|
const task = InteractionManager.runAfterInteractions(async () => {
|
||||||
if (wallet) {
|
if (wallet) {
|
||||||
if (!wallet.getUserHasSavedExport()) {
|
obtainWalletAddress();
|
||||||
BlueAlertWalletExportReminder({
|
|
||||||
onSuccess: obtainWalletAddress,
|
|
||||||
onFailure: () => {
|
|
||||||
navigate('WalletExportRoot', {
|
|
||||||
screen: 'WalletExport',
|
|
||||||
params: {
|
|
||||||
walletID: wallet.getID(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
anchor: receiveAddressButton.current,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
obtainWalletAddress();
|
|
||||||
}
|
|
||||||
} else if (!wallet && address) {
|
} else if (!wallet && address) {
|
||||||
setAddressBIP21Encoded(address);
|
setAddressBIP21Encoded(address);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { ActivityIndicator, findNodeHandle, ScrollView, StyleSheet, View } from 'react-native';
|
import { ActivityIndicator, ScrollView, StyleSheet, View } from 'react-native';
|
||||||
import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native';
|
import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native';
|
||||||
|
|
||||||
import { BlueSpacing20 } from '../../BlueComponents';
|
import { BlueSpacing20 } from '../../BlueComponents';
|
||||||
@ -9,19 +9,18 @@ import { SquareButton } from '../../components/SquareButton';
|
|||||||
|
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import presentAlert from '../../components/Alert';
|
import presentAlert from '../../components/Alert';
|
||||||
import { requestCameraAuthorization } from '../../helpers/scan-qr';
|
import { scanQrHelper } from '../../helpers/scan-qr';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
import { isDesktop } from '../../blue_modules/environment';
|
|
||||||
import SaveFileButton from '../../components/SaveFileButton';
|
import SaveFileButton from '../../components/SaveFileButton';
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
const fs = require('../../blue_modules/fs');
|
|
||||||
|
|
||||||
const PsbtMultisigQRCode = () => {
|
const PsbtMultisigQRCode = () => {
|
||||||
const { navigate } = useNavigation();
|
const { navigate } = useNavigation();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const openScannerButton = useRef();
|
const openScannerButton = useRef();
|
||||||
const { psbtBase64, isShowOpenScanner } = useRoute().params;
|
const { psbtBase64, isShowOpenScanner } = useRoute().params;
|
||||||
|
const { name } = useRoute();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const dynamicQRCode = useRef();
|
const dynamicQRCode = useRef();
|
||||||
const isFocused = useIsFocused();
|
const isFocused = useIsFocused();
|
||||||
@ -62,20 +61,9 @@ const PsbtMultisigQRCode = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const openScanner = () => {
|
const openScanner = async () => {
|
||||||
if (isDesktop) {
|
const scanned = await scanQrHelper(navigate, name, true);
|
||||||
fs.showActionSheet({ anchor: findNodeHandle(openScannerButton.current) }).then(data => onBarScanned({ data }));
|
onBarScanned({ data: scanned });
|
||||||
} else {
|
|
||||||
requestCameraAuthorization().then(() =>
|
|
||||||
navigate('ScanQRCodeRoot', {
|
|
||||||
screen: 'ScanQRCode',
|
|
||||||
params: {
|
|
||||||
onBarScanned,
|
|
||||||
showFileImportButton: true,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveFileButtonBeforeOnPress = () => {
|
const saveFileButtonBeforeOnPress = () => {
|
||||||
|
@ -6,7 +6,7 @@ import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native'
|
|||||||
import RNFS from 'react-native-fs';
|
import RNFS from 'react-native-fs';
|
||||||
import Biometric from '../../class/biometrics';
|
import Biometric from '../../class/biometrics';
|
||||||
|
|
||||||
import { BlueText, BlueCard, BlueSpacing20, BlueCopyToClipboardButton } from '../../BlueComponents';
|
import { BlueText, BlueCard, BlueSpacing20 } from '../../BlueComponents';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -19,6 +19,7 @@ import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/h
|
|||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
import { SecondButton } from '../../components/SecondButton';
|
import { SecondButton } from '../../components/SecondButton';
|
||||||
import SaveFileButton from '../../components/SaveFileButton';
|
import SaveFileButton from '../../components/SaveFileButton';
|
||||||
|
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
|
||||||
const BlueElectrum = require('../../blue_modules/BlueElectrum');
|
const BlueElectrum = require('../../blue_modules/BlueElectrum');
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
|
|
||||||
@ -282,7 +283,7 @@ const PsbtWithHardwareWallet = () => {
|
|||||||
</SaveFileButton>
|
</SaveFileButton>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<View style={styles.copyToClipboard}>
|
<View style={styles.copyToClipboard}>
|
||||||
<BlueCopyToClipboardButton
|
<CopyToClipboardButton
|
||||||
stringToCopy={typeof psbt === 'string' ? psbt : psbt.toBase64()}
|
stringToCopy={typeof psbt === 'string' ? psbt : psbt.toBase64()}
|
||||||
displayText={loc.send.psbt_clipboard}
|
displayText={loc.send.psbt_clipboard}
|
||||||
/>
|
/>
|
||||||
|
@ -4,13 +4,14 @@ import { ScrollView, TouchableWithoutFeedback, I18nManager, StyleSheet, Linking,
|
|||||||
import { Button as ButtonRNElements } from 'react-native-elements';
|
import { Button as ButtonRNElements } from 'react-native-elements';
|
||||||
|
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
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 loc from '../../loc';
|
||||||
import { BlueCurrentTheme, useTheme } from '../../components/themes';
|
import { BlueCurrentTheme, useTheme } from '../../components/themes';
|
||||||
import Notifications from '../../blue_modules/notifications';
|
import Notifications from '../../blue_modules/notifications';
|
||||||
import presentAlert from '../../components/Alert';
|
import presentAlert from '../../components/Alert';
|
||||||
import { Button } from '../../components/Button';
|
import { Button } from '../../components/Button';
|
||||||
import ListItem from '../../components/ListItem';
|
import ListItem from '../../components/ListItem';
|
||||||
|
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
|
||||||
|
|
||||||
const NotificationSettings = () => {
|
const NotificationSettings = () => {
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@ -147,7 +148,7 @@ const NotificationSettings = () => {
|
|||||||
|
|
||||||
{isShowTokenInfo >= 9 && (
|
{isShowTokenInfo >= 9 && (
|
||||||
<View>
|
<View>
|
||||||
<BlueCopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
|
<CopyToClipboardButton stringToCopy={tokenInfo} displayText={tokenInfo} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -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 { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StyleSheet, Keyboard } from 'react-native';
|
||||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
import Clipboard from '@react-native-clipboard/clipboard';
|
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 navigationStyle from '../../components/navigationStyle';
|
||||||
import HandoffComponent from '../../components/handoff';
|
import HandoffComponent from '../../components/handoff';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
@ -11,6 +11,7 @@ import ToolTipMenu from '../../components/TooltipMenu';
|
|||||||
import presentAlert from '../../components/Alert';
|
import presentAlert from '../../components/Alert';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
|
import CopyToClipboardButton from '../../components/CopyToClipboardButton';
|
||||||
const dayjs = require('dayjs');
|
const dayjs = require('dayjs');
|
||||||
|
|
||||||
function onlyUnique(value, index, self) {
|
function onlyUnique(value, index, self) {
|
||||||
@ -240,7 +241,7 @@ const TransactionsDetails = () => {
|
|||||||
<>
|
<>
|
||||||
<View style={styles.rowHeader}>
|
<View style={styles.rowHeader}>
|
||||||
<BlueText style={styles.rowCaption}>{loc.transactions.details_from}</BlueText>
|
<BlueText style={styles.rowCaption}>{loc.transactions.details_from}</BlueText>
|
||||||
<BlueCopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
|
<CopyToClipboardButton stringToCopy={from.filter(onlyUnique).join(', ')} />
|
||||||
</View>
|
</View>
|
||||||
{renderSection(from.filter(onlyUnique))}
|
{renderSection(from.filter(onlyUnique))}
|
||||||
<View style={styles.marginBottom18} />
|
<View style={styles.marginBottom18} />
|
||||||
@ -251,7 +252,7 @@ const TransactionsDetails = () => {
|
|||||||
<>
|
<>
|
||||||
<View style={styles.rowHeader}>
|
<View style={styles.rowHeader}>
|
||||||
<BlueText style={styles.rowCaption}>{loc.transactions.details_to}</BlueText>
|
<BlueText style={styles.rowCaption}>{loc.transactions.details_to}</BlueText>
|
||||||
<BlueCopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
|
<CopyToClipboardButton stringToCopy={to.filter(onlyUnique).join(', ')} />
|
||||||
</View>
|
</View>
|
||||||
{renderSection(arrDiff(from, to.filter(onlyUnique)))}
|
{renderSection(arrDiff(from, to.filter(onlyUnique)))}
|
||||||
<View style={styles.marginBottom18} />
|
<View style={styles.marginBottom18} />
|
||||||
@ -270,7 +271,7 @@ const TransactionsDetails = () => {
|
|||||||
<>
|
<>
|
||||||
<View style={styles.rowHeader}>
|
<View style={styles.rowHeader}>
|
||||||
<BlueText style={styles.txid}>{loc.transactions.txid}</BlueText>
|
<BlueText style={styles.txid}>{loc.transactions.txid}</BlueText>
|
||||||
<BlueCopyToClipboardButton stringToCopy={tx.hash} />
|
<CopyToClipboardButton stringToCopy={tx.hash} />
|
||||||
</View>
|
</View>
|
||||||
<BlueText style={styles.rowValue}>{tx.hash}</BlueText>
|
<BlueText style={styles.rowValue}>{tx.hash}</BlueText>
|
||||||
<View style={styles.marginBottom18} />
|
<View style={styles.marginBottom18} />
|
||||||
@ -374,7 +375,7 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
},
|
},
|
||||||
weOwnAddress: {
|
weOwnAddress: {
|
||||||
fontWeight: '600',
|
fontWeight: '700',
|
||||||
},
|
},
|
||||||
save: {
|
save: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -341,7 +341,9 @@ const TransactionsStatus = () => {
|
|||||||
if (txMetadata[tx.hash].memo) {
|
if (txMetadata[tx.hash].memo) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.memo}>
|
<View style={styles.memo}>
|
||||||
<Text style={styles.memoText}>{txMetadata[tx.hash].memo}</Text>
|
<Text selectable style={styles.memoText}>
|
||||||
|
{txMetadata[tx.hash].memo}
|
||||||
|
</Text>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@ -367,7 +369,7 @@ const TransactionsStatus = () => {
|
|||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<BlueCard>
|
<BlueCard>
|
||||||
<View style={styles.center}>
|
<View style={styles.center}>
|
||||||
<Text style={[styles.value, stylesHook.value]}>
|
<Text style={[styles.value, stylesHook.value]} selectable>
|
||||||
{formatBalanceWithoutSuffix(tx.value, wallet.current.preferredBalanceUnit, true)}{' '}
|
{formatBalanceWithoutSuffix(tx.value, wallet.current.preferredBalanceUnit, true)}{' '}
|
||||||
{wallet.current.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && (
|
{wallet.current.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && (
|
||||||
<Text style={[styles.valueUnit, stylesHook.valueUnit]}>{loc.units[wallet.current.preferredBalanceUnit]}</Text>
|
<Text style={[styles.valueUnit, stylesHook.valueUnit]}>{loc.units[wallet.current.preferredBalanceUnit]}</Text>
|
||||||
|
@ -13,7 +13,6 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
findNodeHandle,
|
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';
|
import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';
|
||||||
@ -37,12 +36,10 @@ import { useTheme } from '../../components/themes';
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
import { isDesktop } from '../../blue_modules/environment';
|
|
||||||
import SaveFileButton from '../../components/SaveFileButton';
|
import SaveFileButton from '../../components/SaveFileButton';
|
||||||
|
|
||||||
const prompt = require('../../helpers/prompt');
|
const prompt = require('../../helpers/prompt');
|
||||||
const A = require('../../blue_modules/analytics');
|
const A = require('../../blue_modules/analytics');
|
||||||
const fs = require('../../blue_modules/fs');
|
|
||||||
const staticCache = {};
|
const staticCache = {};
|
||||||
|
|
||||||
const WalletsAddMultisigStep2 = () => {
|
const WalletsAddMultisigStep2 = () => {
|
||||||
@ -468,15 +465,11 @@ const WalletsAddMultisigStep2 = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const scanOrOpenFile = () => {
|
const scanOrOpenFile = () => {
|
||||||
if (isDesktop) {
|
setIsProvideMnemonicsModalVisible(false);
|
||||||
fs.showActionSheet({ anchor: findNodeHandle(openScannerButton.current) }).then(onBarScanned);
|
InteractionManager.runAfterInteractions(async () => {
|
||||||
} else {
|
const scanned = await scanQrHelper(navigation.navigate, name, true);
|
||||||
setIsProvideMnemonicsModalVisible(false);
|
onBarScanned({ data: scanned });
|
||||||
InteractionManager.runAfterInteractions(async () => {
|
});
|
||||||
const scanned = await scanQrHelper(navigation.navigate, name, true);
|
|
||||||
onBarScanned({ data: scanned });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const dashType = ({ index, lastIndex, isChecked, isFocus }) => {
|
const dashType = ({ index, lastIndex, isChecked, isFocus }) => {
|
||||||
|
@ -32,7 +32,7 @@ import {
|
|||||||
LightningLdkWallet,
|
LightningLdkWallet,
|
||||||
} from '../../class';
|
} from '../../class';
|
||||||
import loc, { formatBalanceWithoutSuffix } from '../../loc';
|
import loc, { formatBalanceWithoutSuffix } from '../../loc';
|
||||||
import { useRoute, useNavigation } from '@react-navigation/native';
|
import { useRoute } from '@react-navigation/native';
|
||||||
import RNFS from 'react-native-fs';
|
import RNFS from 'react-native-fs';
|
||||||
import Share from 'react-native-share';
|
import Share from 'react-native-share';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -48,6 +48,7 @@ import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/h
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import { SecondButton } from '../../components/SecondButton';
|
import { SecondButton } from '../../components/SecondButton';
|
||||||
import SaveFileButton from '../../components/SaveFileButton';
|
import SaveFileButton from '../../components/SaveFileButton';
|
||||||
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
|
|
||||||
const prompt = require('../../helpers/prompt');
|
const prompt = require('../../helpers/prompt');
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ const WalletDetails = () => {
|
|||||||
const [isAdvancedModeEnabledRender, setIsAdvancedModeEnabledRender] = useState(false);
|
const [isAdvancedModeEnabledRender, setIsAdvancedModeEnabledRender] = useState(false);
|
||||||
const [isBIP47Enabled, setIsBIP47Enabled] = useState(wallet.isBIP47Enabled());
|
const [isBIP47Enabled, setIsBIP47Enabled] = useState(wallet.isBIP47Enabled());
|
||||||
const [hideTransactionsInWalletsList, setHideTransactionsInWalletsList] = useState(!wallet.getHideTransactionsInWalletsList());
|
const [hideTransactionsInWalletsList, setHideTransactionsInWalletsList] = useState(!wallet.getHideTransactionsInWalletsList());
|
||||||
const { goBack, navigate, setOptions, popToTop } = useNavigation();
|
const { goBack, setOptions, popToTop, navigate } = useExtendedNavigation();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const [masterFingerprint, setMasterFingerprint] = useState();
|
const [masterFingerprint, setMasterFingerprint] = useState();
|
||||||
const walletTransactionsLength = useMemo(() => wallet.getTransactions().length, [wallet]);
|
const walletTransactionsLength = useMemo(() => wallet.getTransactions().length, [wallet]);
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import React, { useState, useCallback, useContext, useRef, useEffect } from 'react';
|
import React, { useState, useCallback, useContext, useRef, useEffect } from 'react';
|
||||||
import { InteractionManager, ScrollView, ActivityIndicator, View, StyleSheet, AppState } from 'react-native';
|
import { InteractionManager, ScrollView, ActivityIndicator, View, StyleSheet, AppState } from 'react-native';
|
||||||
import { useNavigation, useFocusEffect, useRoute } from '@react-navigation/native';
|
import { useNavigation, useFocusEffect, useRoute } from '@react-navigation/native';
|
||||||
|
import { BlueSpacing20, BlueText, BlueCard } from '../../BlueComponents';
|
||||||
import { BlueSpacing20, BlueText, BlueCopyTextToClipboard, BlueCard } from '../../BlueComponents';
|
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import Biometric from '../../class/biometrics';
|
|
||||||
import { LegacyWallet, LightningCustodianWallet, SegwitBech32Wallet, SegwitP2SHWallet, WatchOnlyWallet } from '../../class';
|
import { LegacyWallet, LightningCustodianWallet, SegwitBech32Wallet, SegwitP2SHWallet, WatchOnlyWallet } from '../../class';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -13,6 +11,7 @@ import HandoffComponent from '../../components/handoff';
|
|||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const WalletExport = () => {
|
const WalletExport = () => {
|
||||||
const { wallets, saveToDisk } = useContext(BlueStorageContext);
|
const { wallets, saveToDisk } = useContext(BlueStorageContext);
|
||||||
@ -56,13 +55,6 @@ const WalletExport = () => {
|
|||||||
enableBlur();
|
enableBlur();
|
||||||
const task = InteractionManager.runAfterInteractions(async () => {
|
const task = InteractionManager.runAfterInteractions(async () => {
|
||||||
if (wallet) {
|
if (wallet) {
|
||||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
|
||||||
|
|
||||||
if (isBiometricsEnabled) {
|
|
||||||
if (!(await Biometric.unlockWithBiometrics())) {
|
|
||||||
return goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!wallet.getUserHasSavedExport()) {
|
if (!wallet.getUserHasSavedExport()) {
|
||||||
wallet.setUserHasSavedExport(true);
|
wallet.setUserHasSavedExport(true);
|
||||||
saveToDisk();
|
saveToDisk();
|
||||||
@ -75,7 +67,7 @@ const WalletExport = () => {
|
|||||||
disableBlur();
|
disableBlur();
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [goBack, saveToDisk, wallet]),
|
}, [wallet]),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isLoading || !wallet)
|
if (isLoading || !wallet)
|
||||||
@ -117,7 +109,7 @@ const WalletExport = () => {
|
|||||||
)}
|
)}
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
{wallet.type === LightningCustodianWallet.type || wallet.type === WatchOnlyWallet.type ? (
|
{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">
|
<BlueText style={[styles.secret, styles.secretWritingDirection, stylesHook.secret]} testID="Secret">
|
||||||
{wallet.getSecret()}
|
{wallet.getSecret()}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import React, { useCallback, useContext, useRef, useState } from 'react';
|
import React, { useCallback, useContext, useRef, useState } from 'react';
|
||||||
import { ActivityIndicator, InteractionManager, ScrollView, StyleSheet, View } from 'react-native';
|
import { ActivityIndicator, InteractionManager, ScrollView, StyleSheet, View } from 'react-native';
|
||||||
import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';
|
import { useFocusEffect, useRoute } from '@react-navigation/native';
|
||||||
import { BlueSpacing20, BlueText } from '../../BlueComponents';
|
import { BlueSpacing20, BlueText } from '../../BlueComponents';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import { DynamicQRCode } from '../../components/DynamicQRCode';
|
import { DynamicQRCode } from '../../components/DynamicQRCode';
|
||||||
import Biometric from '../../class/biometrics';
|
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { SquareButton } from '../../components/SquareButton';
|
import { SquareButton } from '../../components/SquareButton';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -21,7 +20,6 @@ const ExportMultisigCoordinationSetup = () => {
|
|||||||
const dynamicQRCode = useRef();
|
const dynamicQRCode = useRef();
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isShareButtonTapped, setIsShareButtonTapped] = useState(false);
|
const [isShareButtonTapped, setIsShareButtonTapped] = useState(false);
|
||||||
const { goBack } = useNavigation();
|
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const { enableBlur, disableBlur } = usePrivacy();
|
const { enableBlur, disableBlur } = usePrivacy();
|
||||||
const stylesHook = StyleSheet.create({
|
const stylesHook = StyleSheet.create({
|
||||||
@ -53,13 +51,6 @@ const ExportMultisigCoordinationSetup = () => {
|
|||||||
enableBlur();
|
enableBlur();
|
||||||
const task = InteractionManager.runAfterInteractions(async () => {
|
const task = InteractionManager.runAfterInteractions(async () => {
|
||||||
if (wallet) {
|
if (wallet) {
|
||||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
|
||||||
|
|
||||||
if (isBiometricsEnabled) {
|
|
||||||
if (!(await Biometric.unlockWithBiometrics())) {
|
|
||||||
return goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qrCodeContents.current = Buffer.from(wallet.getXpub(), 'ascii').toString('hex');
|
qrCodeContents.current = Buffer.from(wallet.getXpub(), 'ascii').toString('hex');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@ -68,7 +59,7 @@ const ExportMultisigCoordinationSetup = () => {
|
|||||||
task.cancel();
|
task.cancel();
|
||||||
disableBlur();
|
disableBlur();
|
||||||
};
|
};
|
||||||
}, [disableBlur, enableBlur, goBack, wallet]),
|
}, [disableBlur, enableBlur, wallet]),
|
||||||
);
|
);
|
||||||
|
|
||||||
return isLoading ? (
|
return isLoading ? (
|
||||||
|
@ -20,7 +20,7 @@ import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
|
|||||||
import ActionSheet from '../ActionSheet';
|
import ActionSheet from '../ActionSheet';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { FContainer, FButton } from '../../components/FloatButtons';
|
import { FContainer, FButton } from '../../components/FloatButtons';
|
||||||
import { useFocusEffect, useIsFocused, useNavigation, useRoute } from '@react-navigation/native';
|
import { useFocusEffect, useIsFocused, useRoute } from '@react-navigation/native';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
import { isDesktop, isTablet } from '../../blue_modules/environment';
|
import { isDesktop, isTablet } from '../../blue_modules/environment';
|
||||||
import BlueClipboard from '../../blue_modules/clipboard';
|
import BlueClipboard from '../../blue_modules/clipboard';
|
||||||
@ -30,6 +30,7 @@ import { scanQrHelper } from '../../helpers/scan-qr';
|
|||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import presentAlert from '../../components/Alert';
|
import presentAlert from '../../components/Alert';
|
||||||
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
|
|
||||||
const A = require('../../blue_modules/analytics');
|
const A = require('../../blue_modules/analytics');
|
||||||
const fs = require('../../blue_modules/fs');
|
const fs = require('../../blue_modules/fs');
|
||||||
@ -49,7 +50,7 @@ const WalletsList = () => {
|
|||||||
} = useContext(BlueStorageContext);
|
} = useContext(BlueStorageContext);
|
||||||
const { width } = useWindowDimensions();
|
const { width } = useWindowDimensions();
|
||||||
const { colors, scanImage } = useTheme();
|
const { colors, scanImage } = useTheme();
|
||||||
const { navigate, setOptions } = useNavigation();
|
const { navigate, setOptions } = useExtendedNavigation();
|
||||||
const isFocused = useIsFocused();
|
const isFocused = useIsFocused();
|
||||||
const routeName = useRoute().name;
|
const routeName = useRoute().name;
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, Text, View } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
import { BlueCopyTextToClipboard } from '../../BlueComponents';
|
|
||||||
import { PaymentCodeStackParamList } from '../../Navigation';
|
import { PaymentCodeStackParamList } from '../../Navigation';
|
||||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<PaymentCodeStackParamList, 'PaymentCode'>;
|
type Props = NativeStackScreenProps<PaymentCodeStackParamList, 'PaymentCode'>;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ export default function PaymentCode({ route }: Props) {
|
|||||||
{paymentCode && (
|
{paymentCode && (
|
||||||
<>
|
<>
|
||||||
<QRCodeComponent value={paymentCode} />
|
<QRCodeComponent value={paymentCode} />
|
||||||
<BlueCopyTextToClipboard text={paymentCode} />
|
<CopyTextToClipboard text={paymentCode} truncated={false} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { SectionList, StyleSheet, Text, View } from 'react-native';
|
import { SectionList, StyleSheet, Text, View } from 'react-native';
|
||||||
import { BlueCopyTextToClipboard } from '../../BlueComponents';
|
|
||||||
import { PaymentCodeStackParamList } from '../../Navigation';
|
import { PaymentCodeStackParamList } from '../../Navigation';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
interface DataSection {
|
interface DataSection {
|
||||||
title: string;
|
title: string;
|
||||||
@ -45,7 +45,7 @@ export default function PaymentCodesList({ route }: Props) {
|
|||||||
keyExtractor={(item, index) => item + index}
|
keyExtractor={(item, index) => item + index}
|
||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<View>
|
<View>
|
||||||
<BlueCopyTextToClipboard truncated text={item} />
|
<CopyTextToClipboard truncated text={item} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
renderSectionHeader={({ section: { title } }) => <Text style={styles.titleText}>{title}</Text>}
|
renderSectionHeader={({ section: { title } }) => <Text style={styles.titleText}>{title}</Text>}
|
||||||
|
@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
|
|||||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
import { View, StyleSheet, ScrollView, BackHandler } from 'react-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 navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -11,6 +11,7 @@ import { useTheme } from '../../components/themes';
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const PleaseBackupLNDHub = () => {
|
const PleaseBackupLNDHub = () => {
|
||||||
const { wallets } = useContext(BlueStorageContext);
|
const { wallets } = useContext(BlueStorageContext);
|
||||||
@ -63,7 +64,7 @@ const PleaseBackupLNDHub = () => {
|
|||||||
</View>
|
</View>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<QRCodeComponent value={wallet.getSecret()} size={qrCodeSize} />
|
<QRCodeComponent value={wallet.getSecret()} size={qrCodeSize} />
|
||||||
<BlueCopyTextToClipboard text={wallet.getSecret()} />
|
<CopyTextToClipboard text={wallet.getSecret()} />
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
|
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -2,7 +2,7 @@ import React, { useCallback, useContext, useEffect } from 'react';
|
|||||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
import { View, useWindowDimensions, StyleSheet, BackHandler, ScrollView } from 'react-native';
|
import { View, useWindowDimensions, StyleSheet, BackHandler, ScrollView } from 'react-native';
|
||||||
import QRCode from 'react-native-qrcode-svg';
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
import { BlueCopyTextToClipboard, BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
|
import { BlueSpacing20, BlueTextCentered } from '../../BlueComponents';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -10,6 +10,7 @@ import { useTheme } from '../../components/themes';
|
|||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
const PleaseBackupLdk = () => {
|
const PleaseBackupLdk = () => {
|
||||||
const { wallets } = useContext(BlueStorageContext);
|
const { wallets } = useContext(BlueStorageContext);
|
||||||
@ -71,7 +72,7 @@ const PleaseBackupLdk = () => {
|
|||||||
ecl="H"
|
ecl="H"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<BlueCopyTextToClipboard text={wallet.getSecret()} />
|
<CopyTextToClipboard text={wallet.getSecret()} />
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
|
<Button onPress={pop} title={loc.pleasebackup.ok_lnd} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useEffect, useRef, useContext, useState } from 'react';
|
import React, { useEffect, useRef, useContext, useState } from 'react';
|
||||||
import { StyleSheet, useColorScheme, Platform } from 'react-native';
|
import { StyleSheet, useColorScheme, Platform } from 'react-native';
|
||||||
import DraggableFlatList, { ScaleDecorator } from 'react-native-draggable-flatlist';
|
import DraggableFlatList, { ScaleDecorator } from 'react-native-draggable-flatlist';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
@ -9,6 +8,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import { WalletCarouselItem } from '../../components/WalletsCarousel';
|
import { WalletCarouselItem } from '../../components/WalletsCarousel';
|
||||||
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
root: {
|
root: {
|
||||||
@ -24,7 +24,7 @@ const ReorderWallets = () => {
|
|||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const { wallets, setWalletsWithNewOrder } = useContext(BlueStorageContext);
|
const { wallets, setWalletsWithNewOrder } = useContext(BlueStorageContext);
|
||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
const { navigate, setOptions } = useNavigation();
|
const { navigate, setOptions } = useExtendedNavigation();
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [isSearchFocused, setIsSearchFocused] = useState(false);
|
const [isSearchFocused, setIsSearchFocused] = useState(false);
|
||||||
const [walletData, setWalletData] = useState([]);
|
const [walletData, setWalletData] = useState([]);
|
||||||
|
@ -15,9 +15,8 @@ import {
|
|||||||
findNodeHandle,
|
findNodeHandle,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import { useRoute, useNavigation, useFocusEffect } from '@react-navigation/native';
|
import { useRoute, useFocusEffect } from '@react-navigation/native';
|
||||||
import { Chain } from '../../models/bitcoinUnits';
|
import { Chain } from '../../models/bitcoinUnits';
|
||||||
import { BlueAlertWalletExportReminder } from '../../BlueComponents';
|
|
||||||
import WalletGradient from '../../class/wallet-gradient';
|
import WalletGradient from '../../class/wallet-gradient';
|
||||||
import navigationStyle from '../../components/navigationStyle';
|
import navigationStyle from '../../components/navigationStyle';
|
||||||
import { LightningCustodianWallet, LightningLdkWallet, MultisigHDWallet, WatchOnlyWallet } from '../../class';
|
import { LightningCustodianWallet, LightningLdkWallet, MultisigHDWallet, WatchOnlyWallet } from '../../class';
|
||||||
@ -35,6 +34,8 @@ import PropTypes from 'prop-types';
|
|||||||
import { scanQrHelper } from '../../helpers/scan-qr';
|
import { scanQrHelper } from '../../helpers/scan-qr';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
|
import { presentWalletExportReminder } from '../../helpers/presentWalletExportReminder';
|
||||||
|
|
||||||
const fs = require('../../blue_modules/fs');
|
const fs = require('../../blue_modules/fs');
|
||||||
const BlueElectrum = require('../../blue_modules/BlueElectrum');
|
const BlueElectrum = require('../../blue_modules/BlueElectrum');
|
||||||
@ -63,7 +64,7 @@ const WalletTransactions = ({ navigation }) => {
|
|||||||
const [timeElapsed, setTimeElapsed] = useState(0);
|
const [timeElapsed, setTimeElapsed] = useState(0);
|
||||||
const [limit, setLimit] = useState(15);
|
const [limit, setLimit] = useState(15);
|
||||||
const [pageSize, setPageSize] = useState(20);
|
const [pageSize, setPageSize] = useState(20);
|
||||||
const { setParams, setOptions, navigate } = useNavigation();
|
const { setParams, setOptions, navigate } = useExtendedNavigation();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const [lnNodeInfo, setLnNodeInfo] = useState({ canReceive: 0, canSend: 0 });
|
const [lnNodeInfo, setLnNodeInfo] = useState({ canReceive: 0, canSend: 0 });
|
||||||
const walletActionButtonsRef = useRef();
|
const walletActionButtonsRef = useRef();
|
||||||
@ -518,20 +519,20 @@ const WalletTransactions = ({ navigation }) => {
|
|||||||
if (wallet.getUserHasSavedExport()) {
|
if (wallet.getUserHasSavedExport()) {
|
||||||
onManageFundsPressed({ id });
|
onManageFundsPressed({ id });
|
||||||
} else {
|
} else {
|
||||||
BlueAlertWalletExportReminder({
|
presentWalletExportReminder()
|
||||||
onSuccess: async () => {
|
.then(async () => {
|
||||||
wallet.setUserHasSavedExport(true);
|
wallet.setUserHasSavedExport(true);
|
||||||
await saveToDisk();
|
await saveToDisk();
|
||||||
onManageFundsPressed({ id });
|
onManageFundsPressed({ id });
|
||||||
},
|
})
|
||||||
onFailure: () =>
|
.catch(() => {
|
||||||
navigate('WalletExportRoot', {
|
navigate('WalletExportRoot', {
|
||||||
screen: 'WalletExport',
|
screen: 'WalletExport',
|
||||||
params: {
|
params: {
|
||||||
walletID: wallet.getID(),
|
walletID: wallet.getID(),
|
||||||
},
|
},
|
||||||
}),
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -539,6 +540,7 @@ const WalletTransactions = ({ navigation }) => {
|
|||||||
<View style={[styles.list, stylesHook.list]}>
|
<View style={[styles.list, stylesHook.list]}>
|
||||||
<FlatList
|
<FlatList
|
||||||
getItemLayout={getItemLayout}
|
getItemLayout={getItemLayout}
|
||||||
|
updateCellsBatchingPeriod={30}
|
||||||
ListHeaderComponent={renderListHeaderComponent}
|
ListHeaderComponent={renderListHeaderComponent}
|
||||||
onEndReachedThreshold={0.3}
|
onEndReachedThreshold={0.3}
|
||||||
onEndReached={async () => {
|
onEndReached={async () => {
|
||||||
@ -571,6 +573,8 @@ const WalletTransactions = ({ navigation }) => {
|
|||||||
initialNumToRender={10}
|
initialNumToRender={10}
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
contentInset={{ top: 0, left: 0, bottom: 90, right: 0 }}
|
contentInset={{ top: 0, left: 0, bottom: 90, right: 0 }}
|
||||||
|
maxToRenderPerBatch={15}
|
||||||
|
windowSize={25}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
import { useFocusEffect } from '@react-navigation/native';
|
||||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||||
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
@ -53,6 +53,7 @@ import loc from '../../loc';
|
|||||||
import { isDesktop } from '../../blue_modules/environment';
|
import { isDesktop } from '../../blue_modules/environment';
|
||||||
import ActionSheet from '../ActionSheet';
|
import ActionSheet from '../ActionSheet';
|
||||||
import SaveFileButton from '../../components/SaveFileButton';
|
import SaveFileButton from '../../components/SaveFileButton';
|
||||||
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
const prompt = require('../../helpers/prompt');
|
const prompt = require('../../helpers/prompt');
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<ViewEditMultisigCosignersStackParamsList, 'ViewEditMultisigCosigners'>;
|
type Props = NativeStackScreenProps<ViewEditMultisigCosignersStackParamsList, 'ViewEditMultisigCosigners'>;
|
||||||
@ -61,7 +62,7 @@ const ViewEditMultisigCosigners = ({ route }: Props) => {
|
|||||||
const hasLoaded = useRef(false);
|
const hasLoaded = useRef(false);
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const { wallets, setWalletsWithNewOrder, isElectrumDisabled, isAdvancedModeEnabled } = useContext(BlueStorageContext);
|
const { wallets, setWalletsWithNewOrder, isElectrumDisabled, isAdvancedModeEnabled } = useContext(BlueStorageContext);
|
||||||
const { navigate, goBack, dispatch, addListener } = useNavigation();
|
const { navigate, dispatch, addListener } = useExtendedNavigation();
|
||||||
const openScannerButtonRef = useRef();
|
const openScannerButtonRef = useRef();
|
||||||
const { walletId } = route.params;
|
const { walletId } = route.params;
|
||||||
const w = useRef(wallets.find(wallet => wallet.getID() === walletId));
|
const w = useRef(wallets.find(wallet => wallet.getID() === walletId));
|
||||||
@ -213,13 +214,6 @@ const ViewEditMultisigCosigners = ({ route }: Props) => {
|
|||||||
enableBlur();
|
enableBlur();
|
||||||
|
|
||||||
const task = InteractionManager.runAfterInteractions(async () => {
|
const task = InteractionManager.runAfterInteractions(async () => {
|
||||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
|
||||||
|
|
||||||
if (isBiometricsEnabled) {
|
|
||||||
if (!(await Biometric.unlockWithBiometrics())) {
|
|
||||||
return goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!w.current) {
|
if (!w.current) {
|
||||||
// lets create fake wallet so renderer wont throw any errors
|
// lets create fake wallet so renderer wont throw any errors
|
||||||
w.current = new MultisigHDWallet();
|
w.current = new MultisigHDWallet();
|
||||||
@ -537,11 +531,11 @@ const ViewEditMultisigCosigners = ({ route }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderProvideMnemonicsModal = () => {
|
const renderProvideMnemonicsModal = () => {
|
||||||
// @ts-ignore weird, property exists on typedefinition. might be some ts bugs
|
// @ts-ignore weird, property exists on type definition. might be some ts bugs
|
||||||
const isPad: boolean = Platform.isPad;
|
const isPad: boolean = Platform.isPad;
|
||||||
return (
|
return (
|
||||||
<BottomModal isVisible={isProvideMnemonicsModalVisible} onClose={hideProvideMnemonicsModal} coverScreen={false}>
|
<BottomModal avoidKeyboard isVisible={isProvideMnemonicsModalVisible} onClose={hideProvideMnemonicsModal} coverScreen={false}>
|
||||||
<KeyboardAvoidingView enabled={!isPad} behavior={Platform.OS === 'ios' ? 'position' : undefined}>
|
<KeyboardAvoidingView enabled={!isPad} behavior={Platform.OS === 'ios' ? 'position' : 'padding'} keyboardVerticalOffset={120}>
|
||||||
<View style={[styles.modalContent, stylesHook.modalContent]}>
|
<View style={[styles.modalContent, stylesHook.modalContent]}>
|
||||||
<BlueTextCentered>{loc.multisig.type_your_mnemonics}</BlueTextCentered>
|
<BlueTextCentered>{loc.multisig.type_your_mnemonics}</BlueTextCentered>
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
|
@ -2,9 +2,8 @@ import { NavigationProp, RouteProp, useFocusEffect, useNavigation, useRoute } fr
|
|||||||
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { ActivityIndicator, InteractionManager, View } from 'react-native';
|
import { ActivityIndicator, InteractionManager, View } from 'react-native';
|
||||||
import Share from 'react-native-share';
|
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 { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||||
import Biometric from '../../class/biometrics';
|
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
@ -12,6 +11,7 @@ import HandoffComponent from '../../components/handoff';
|
|||||||
import usePrivacy from '../../hooks/usePrivacy';
|
import usePrivacy from '../../hooks/usePrivacy';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { styles, useDynamicStyles } from './xpub.styles';
|
import { styles, useDynamicStyles } from './xpub.styles';
|
||||||
|
import CopyTextToClipboard from '../../components/CopyTextToClipboard';
|
||||||
|
|
||||||
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
|
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
|
||||||
export type RootStackParamList = {
|
export type RootStackParamList = {
|
||||||
@ -43,13 +43,6 @@ const WalletXpub: React.FC = () => {
|
|||||||
enableBlur();
|
enableBlur();
|
||||||
const task = InteractionManager.runAfterInteractions(async () => {
|
const task = InteractionManager.runAfterInteractions(async () => {
|
||||||
if (wallet) {
|
if (wallet) {
|
||||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
|
||||||
|
|
||||||
if (isBiometricsEnabled) {
|
|
||||||
if (!(await Biometric.unlockWithBiometrics())) {
|
|
||||||
return navigation.goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const walletXpub = wallet.getXpub();
|
const walletXpub = wallet.getXpub();
|
||||||
if (xpub !== walletXpub) {
|
if (xpub !== walletXpub) {
|
||||||
navigation.setParams({ xpub: walletXpub || undefined });
|
navigation.setParams({ xpub: walletXpub || undefined });
|
||||||
@ -99,7 +92,7 @@ const WalletXpub: React.FC = () => {
|
|||||||
<QRCodeComponent value={xpub} size={qrCodeSize} />
|
<QRCodeComponent value={xpub} size={qrCodeSize} />
|
||||||
|
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
<BlueCopyTextToClipboard text={xPubText} />
|
{xPubText && <CopyTextToClipboard text={xPubText} />}
|
||||||
</View>
|
</View>
|
||||||
<HandoffComponent title={loc.wallets.xpub_title} type={HandoffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
|
<HandoffComponent title={loc.wallets.xpub_title} type={HandoffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
|
||||||
<View style={styles.share}>
|
<View style={styles.share}>
|
||||||
|
@ -2,7 +2,7 @@ const fs = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const mainLocFile = './loc/en.json';
|
const mainLocFile = './loc/en.json';
|
||||||
const dirsToInterate = ['components', 'screen', 'blue_modules', 'class'];
|
const dirsToInterate = ['components', 'screen', 'blue_modules', 'class', 'hooks', 'helpers'];
|
||||||
const addFiles = ['BlueComponents.js', 'App.js', 'BlueApp.ts', 'Navigation.tsx'];
|
const addFiles = ['BlueComponents.js', 'App.js', 'BlueApp.ts', 'Navigation.tsx'];
|
||||||
const allowedLocPrefixes = ['loc.lnurl_auth', 'loc.units'];
|
const allowedLocPrefixes = ['loc.lnurl_auth', 'loc.units'];
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ describe('BlueWallet UI Tests - no wallets', () => {
|
|||||||
await element(by.text(`No, and do not ask me again.`)).tap();
|
await element(by.text(`No, and do not ask me again.`)).tap();
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
await yo('BitcoinAddressQRCodeContainer');
|
await yo('BitcoinAddressQRCodeContainer');
|
||||||
await yo('BlueCopyTextToClipboard');
|
await yo('CopyTextToClipboard');
|
||||||
await element(by.id('SetCustomAmountButton')).tap();
|
await element(by.id('SetCustomAmountButton')).tap();
|
||||||
await element(by.id('BitcoinAmountInput')).replaceText('1');
|
await element(by.id('BitcoinAmountInput')).replaceText('1');
|
||||||
await element(by.id('CustomAmountDescription')).typeText('test');
|
await element(by.id('CustomAmountDescription')).typeText('test');
|
||||||
@ -214,7 +214,7 @@ describe('BlueWallet UI Tests - no wallets', () => {
|
|||||||
await sup('1 BTC');
|
await sup('1 BTC');
|
||||||
await sup('test');
|
await sup('test');
|
||||||
await yo('BitcoinAddressQRCodeContainer');
|
await yo('BitcoinAddressQRCodeContainer');
|
||||||
await yo('BlueCopyTextToClipboard');
|
await yo('CopyTextToClipboard');
|
||||||
await device.pressBack();
|
await device.pressBack();
|
||||||
await device.pressBack();
|
await device.pressBack();
|
||||||
await helperDeleteWallet('cr34t3d');
|
await helperDeleteWallet('cr34t3d');
|
||||||
|
@ -402,7 +402,7 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
|
|||||||
// XPUB
|
// XPUB
|
||||||
await element(by.id('WalletDetailsScroll')).swipe('up', 'fast', 1);
|
await element(by.id('WalletDetailsScroll')).swipe('up', 'fast', 1);
|
||||||
await element(by.id('XPub')).tap();
|
await element(by.id('XPub')).tap();
|
||||||
await expect(element(by.id('BlueCopyTextToClipboard'))).toBeVisible();
|
await expect(element(by.id('CopyTextToClipboard'))).toBeVisible();
|
||||||
await device.pressBack();
|
await device.pressBack();
|
||||||
|
|
||||||
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');
|
process.env.TRAVIS && require('fs').writeFileSync(lockFile, '1');
|
||||||
|
Loading…
Reference in New Issue
Block a user