Merge sprint 19.

# Conflicts:
#	src/js/controllers/tab-home.js
This commit is contained in:
Brendon Duncan 2018-07-13 21:19:28 +12:00
commit 0bb4de9bd1
49 changed files with 4115 additions and 3815 deletions

View file

@ -136,6 +136,7 @@ module.exports = function(grunt) {
}, },
angular: { angular: {
src: [ src: [
'src/shim/shim.js',
'bower_components/qrcode-generator/js/qrcode.js', 'bower_components/qrcode-generator/js/qrcode.js',
'bower_components/qrcode-generator/js/qrcode_UTF8.js', 'bower_components/qrcode-generator/js/qrcode_UTF8.js',
'bower_components/moment/min/moment-with-locales.js', 'bower_components/moment/min/moment-with-locales.js',
@ -164,6 +165,7 @@ module.exports = function(grunt) {
src: [ src: [
'src/js/app.js', 'src/js/app.js',
'src/js/routes.js', 'src/js/routes.js',
'src/js/decorators/*.js',
'src/js/directives/*.js', 'src/js/directives/*.js',
'!src/js/directives/*.spec.js', '!src/js/directives/*.spec.js',

View file

@ -24,9 +24,9 @@
"windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c",
"pushSenderId": "1036948132229", "pushSenderId": "1036948132229",
"description": "A Secure Bitcoin Wallet", "description": "A Secure Bitcoin Wallet",
"version": "4.12.0", "version": "4.12.2",
"fullVersion": "4.12-rc1", "fullVersion": "4.12-rc3",
"androidVersion": "412000", "androidVersion": "412200",
"_extraCSS": "", "_extraCSS": "",
"_enabledExtensions": { "_enabledExtensions": {
"coinbase": false, "coinbase": false,

View file

@ -72,9 +72,9 @@
<plugin name="cordova-plugin-queries-schemes" spec="~0.1.5" /> <plugin name="cordova-plugin-queries-schemes" spec="~0.1.5" />
<plugin name="cordova-plugin-firebase" spec="https://github.com/arnesson/cordova-plugin-firebase.git" /> <plugin name="cordova-plugin-firebase" spec="https://github.com/arnesson/cordova-plugin-firebase.git" />
<plugin name="cordova-plugin-wkwebview-inputfocusfix" spec="https://github.com/onderceylan/cordova-plugin-wkwebview-inputfocusfix.git" /> <plugin name="cordova-plugin-wkwebview-inputfocusfix" spec="https://github.com/onderceylan/cordova-plugin-wkwebview-inputfocusfix.git" />
<plugin name="cordova-plugin-nativeaudio" spec="^3.0.9" /> <plugin name="cordova-plugin-media" spec="~5.0.2">
<!-- Changes in error descriptions may break the use of cordova-plugin-secure-storage --> <variable name="KEEP_AVAUDIOSESSION_ALWAYS_ACTIVE" value="NO" />
<plugin name="cordova-plugin-secure-storage" spec="2.6.8" /> </plugin>
<!-- Supported Platforms --> <!-- Supported Platforms -->
<engine name="ios" spec="~4.5.3" /> <engine name="ios" spec="~4.5.3" />
<engine name="android" spec="~6.3.0" /> <engine name="android" spec="~6.3.0" />

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Catalan\n" "Language-Team: Catalan\n"
"Language: ca\n" "Language: ca\n"
"PO-Revision-Date: 2018-06-22T04:02:43+0000\n" "PO-Revision-Date: 2018-07-04 09:26\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Compte"
msgid "Account Number" msgid "Account Number"
msgstr "Número de compte" msgstr "Número de compte"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Transaccions instantànies amb comissions baixes"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Comptes" msgstr "Comptes"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Czech\n" "Language-Team: Czech\n"
"Language: cs\n" "Language: cs\n"
"PO-Revision-Date: 2018-06-22T04:02:46+0000\n" "PO-Revision-Date: 2018-07-04 09:26\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Účet"
msgid "Account Number" msgid "Account Number"
msgstr "Číslo účtu" msgstr "Číslo účtu"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Okamžité transakce s nízkou platbou"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Účty" msgstr "Účty"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: German\n" "Language-Team: German\n"
"Language: de\n" "Language: de\n"
"PO-Revision-Date: 2018-06-22T04:02:49+0000\n" "PO-Revision-Date: 2018-07-04 03:57\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Benutzerkonto"
msgid "Account Number" msgid "Account Number"
msgstr "Kontonummer" msgstr "Kontonummer"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr ""
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Konten" msgstr "Konten"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"
"Language: es\n" "Language: es\n"
"PO-Revision-Date: 2018-06-22T04:02:57+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Cuenta"
msgid "Account Number" msgid "Account Number"
msgstr "Número de cuenta" msgstr "Número de cuenta"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Transacciones instantáneas con comisiones bajas"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Cuentas" msgstr "Cuentas"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Persian\n" "Language-Team: Persian\n"
"Language: fa\n" "Language: fa\n"
"PO-Revision-Date: 2018-06-22T04:02:53+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "حساب"
msgid "Account Number" msgid "Account Number"
msgstr "شماره حساب" msgstr "شماره حساب"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "معاملات فوری با پرداخت کم"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "حساب ها" msgstr "حساب ها"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: French\n" "Language-Team: French\n"
"Language: fr\n" "Language: fr\n"
"PO-Revision-Date: 2018-06-22T04:02:48+0000\n" "PO-Revision-Date: 2018-07-04 09:26\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Compte"
msgid "Account Number" msgid "Account Number"
msgstr "Numéro de compte" msgstr "Numéro de compte"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Transactions instantanées à bas frais"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Comptes" msgstr "Comptes"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Italian\n" "Language-Team: Italian\n"
"Language: it\n" "Language: it\n"
"PO-Revision-Date: 2018-06-22T04:02:50+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Conto"
msgid "Account Number" msgid "Account Number"
msgstr "Numero del Conto" msgstr "Numero del Conto"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Transazioni istantanee con commissioni basse"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Account" msgstr "Account"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Japanese\n" "Language-Team: Japanese\n"
"Language: ja\n" "Language: ja\n"
"PO-Revision-Date: 2018-06-22T04:02:51+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "ポケット"
msgid "Account Number" msgid "Account Number"
msgstr "ポケット番号" msgstr "ポケット番号"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "僅かな手数料で即時決済"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "アカウント一覧" msgstr "アカウント一覧"
@ -631,7 +635,7 @@ msgstr "翻訳に協力"
#: src/js/controllers/confirm.js:130 #: src/js/controllers/confirm.js:130
msgid "Copay only supports Bitcoin Cash using new version numbers addresses" msgid "Copay only supports Bitcoin Cash using new version numbers addresses"
msgstr "Copay のビットコインキャッシュはビットコインと完全に異なる別通貨なので、アドレスの頭文字が異なります。" msgstr "のビットコインキャッシュはビットコインと完全に異なる別通貨なので、アドレスの頭文字が異なります。"
#: src/js/services/bwcError.js:62 #: src/js/services/bwcError.js:62
msgid "Copayer already in this wallet" msgid "Copayer already in this wallet"
@ -2225,7 +2229,7 @@ msgstr "正しい順序で各単語をタップしてください。"
#: src/js/services/bwcError.js:101 #: src/js/services/bwcError.js:101
msgid "Please upgrade Copay to perform this action" msgid "Please upgrade Copay to perform this action"
msgstr "この操作を実行するにはCopayを最新バージョンに更新してください" msgstr "この操作を実行するにはを最新バージョンに更新してください"
#: www/views/walletDetails.html:142 #: www/views/walletDetails.html:142
#: www/views/walletDetails.html:62 #: www/views/walletDetails.html:62

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Korean\n" "Language-Team: Korean\n"
"Language: ko\n" "Language: ko\n"
"PO-Revision-Date: 2018-06-22T04:02:52+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "계정"
msgid "Account Number" msgid "Account Number"
msgstr "계정 번호" msgstr "계정 번호"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "낮은 수수료로 빠른 송금을"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "계정들" msgstr "계정들"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Dutch\n" "Language-Team: Dutch\n"
"Language: nl\n" "Language: nl\n"
"PO-Revision-Date: 2018-06-22T04:02:48+0000\n" "PO-Revision-Date: 2018-07-04 09:26\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Account"
msgid "Account Number" msgid "Account Number"
msgstr "Account Nummer" msgstr "Account Nummer"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Directe transacties tegen lage kosten"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Accounts" msgstr "Accounts"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Polish\n" "Language-Team: Polish\n"
"Language: pl\n" "Language: pl\n"
"PO-Revision-Date: 2018-06-22T04:02:54+0000\n" "PO-Revision-Date: 2018-07-04 03:58\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Konto"
msgid "Account Number" msgid "Account Number"
msgstr "Numer konta" msgstr "Numer konta"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr ""
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Konta" msgstr "Konta"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Portuguese, Brazilian\n" "Language-Team: Portuguese, Brazilian\n"
"Language: pt\n" "Language: pt\n"
"PO-Revision-Date: 2018-06-22T04:02:55+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Conta"
msgid "Account Number" msgid "Account Number"
msgstr "Número de conta" msgstr "Número de conta"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Transações instantâneas com taxas baixas"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Contas" msgstr "Contas"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Russian\n" "Language-Team: Russian\n"
"Language: ru\n" "Language: ru\n"
"PO-Revision-Date: 2018-06-22T04:02:56+0000\n" "PO-Revision-Date: 2018-07-04 09:27\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Учётная запись"
msgid "Account Number" msgid "Account Number"
msgstr "Номер учётной записи" msgstr "Номер учётной записи"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "Мгновенные транзакции с низкой оплатой"
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Аккаунты" msgstr "Аккаунты"

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Swedish\n" "Language-Team: Swedish\n"
"Language: sv\n" "Language: sv\n"
"PO-Revision-Date: 2018-06-22T04:02:58+0000\n" "PO-Revision-Date: 2018-07-04 03:58\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "Konto"
msgid "Account Number" msgid "Account Number"
msgstr "Kontonummer" msgstr "Kontonummer"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr ""
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "Konton" msgstr "Konton"
@ -369,7 +373,7 @@ msgstr ""
#: www/views/tab-home.html:98 #: www/views/tab-home.html:98
#: www/views/tab-settings.html:115 #: www/views/tab-settings.html:115
msgid "Bitcoin Cash Wallets" msgid "Bitcoin Cash Wallets"
msgstr "" msgstr "Bitcoin Cash plånböcker"
#: www/views/modals/chooseFeeLevel.html:4 #: www/views/modals/chooseFeeLevel.html:4
#: www/views/preferencesFee.html:4 #: www/views/preferencesFee.html:4

View file

@ -68,6 +68,10 @@ msgstr ""
msgid "Account Number" msgid "Account Number"
msgstr "" msgstr ""
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr ""
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr ""

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Vietnamese\n" "Language-Team: Vietnamese\n"
"Language: vi\n" "Language: vi\n"
"PO-Revision-Date: 2018-06-22T04:02:59+0000\n" "PO-Revision-Date: 2018-07-04 03:58\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -54,67 +54,71 @@ msgstr "A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size all
#: src/js/controllers/confirm.js:395 #: src/js/controllers/confirm.js:395
msgid "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided." msgid "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided."
msgstr "" msgstr "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided."
#: src/js/controllers/preferencesAbout.js:6 #: src/js/controllers/preferencesAbout.js:6
#: www/views/tab-settings.html:156 #: www/views/tab-settings.html:156
msgid "About" msgid "About"
msgstr "" msgstr "About"
#: src/js/controllers/modals/txpDetails.js:62 #: src/js/controllers/modals/txpDetails.js:62
#: src/js/controllers/tx-details.js:79 #: src/js/controllers/tx-details.js:79
msgid "Accepted" msgid "Accepted"
msgstr "" msgstr "Accepted"
#: www/views/preferencesInformation.html:72 #: www/views/preferencesInformation.html:72
msgid "Account" msgid "Account"
msgstr "" msgstr "Account"
#: www/views/join.html:72 #: www/views/join.html:72
#: www/views/tab-create-personal.html:45 #: www/views/tab-create-personal.html:45
#: www/views/tab-create-shared.html:74 #: www/views/tab-create-shared.html:74
#: www/views/tab-import-hardware.html:19 #: www/views/tab-import-hardware.html:19
msgid "Account Number" msgid "Account Number"
msgstr "Account Number"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr "" msgstr ""
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "" msgstr "Accounts"
#: www/views/bitpayCard.html:56 #: www/views/bitpayCard.html:56
msgid "Activity" msgid "Activity"
msgstr "" msgstr "Activity"
#: src/js/services/bitpayAccountService.js:83 #: src/js/services/bitpayAccountService.js:83
msgid "Add Account" msgid "Add Account"
msgstr "" msgstr "Add Account"
#: src/js/services/bitpayAccountService.js:69 #: src/js/services/bitpayAccountService.js:69
msgid "Add BitPay Account?" msgid "Add BitPay Account?"
msgstr "" msgstr "Add BitPay Account?"
#: www/views/addressbook.add.html:4 #: www/views/addressbook.add.html:4
#: www/views/addressbook.html:22 #: www/views/addressbook.html:22
msgid "Add Contact" msgid "Add Contact"
msgstr "" msgstr "Add Contact"
#: www/views/bitpayCard.html:28 #: www/views/bitpayCard.html:28
msgid "Add Funds" msgid "Add Funds"
msgstr "" msgstr "Add Funds"
#: www/views/confirm.html:94 #: www/views/confirm.html:94
msgid "Add Memo" msgid "Add Memo"
msgstr "" msgstr "Add Memo"
#: www/views/join.html:87 #: www/views/join.html:87
#: www/views/tab-create-personal.html:59 #: www/views/tab-create-personal.html:59
#: www/views/tab-create-shared.html:88 #: www/views/tab-create-shared.html:88
msgid "Add a password" msgid "Add a password"
msgstr "" msgstr "Add a password"
#: www/views/includes/accountSelector.html:27 #: www/views/includes/accountSelector.html:27
msgid "Add account" msgid "Add account"
msgstr "" msgstr "Add account"
#: www/views/join.html:90 #: www/views/join.html:90
#: www/views/tab-create-personal.html:62 #: www/views/tab-create-personal.html:62

View file

@ -11,7 +11,7 @@ msgstr ""
"Last-Translator: emilold\n" "Last-Translator: emilold\n"
"Language-Team: Chinese Simplified\n" "Language-Team: Chinese Simplified\n"
"Language: zh\n" "Language: zh\n"
"PO-Revision-Date: 2018-06-22T04:02:44+0000\n" "PO-Revision-Date: 2018-07-04 03:57\n"
#: www/views/modals/paypro.html:34 #: www/views/modals/paypro.html:34
msgid "(Trusted)" msgid "(Trusted)"
@ -77,6 +77,10 @@ msgstr "帐户"
msgid "Account Number" msgid "Account Number"
msgstr "帐号" msgstr "帐号"
#: www/views/tab-home.html:61
msgid "Instant transactions with low fees"
msgstr ""
#: www/views/preferencesBitpayServices.html:23 #: www/views/preferencesBitpayServices.html:23
msgid "Accounts" msgid "Accounts"
msgstr "帐户" msgstr "帐户"

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService) { angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService, soundService) {
var countDown = null; var countDown = null;
var FEE_TOO_HIGH_LIMIT_PER = 15; var FEE_TOO_HIGH_LIMIT_PER = 15;
@ -287,7 +287,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
tx.amountValueStr = tx.amountStr.split(' ')[0]; tx.amountValueStr = tx.amountStr.split(' ')[0];
tx.amountUnitStr = tx.amountStr.split(' ')[1]; tx.amountUnitStr = tx.amountStr.split(' ')[1];
txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) { txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) {
var parts = v.split(' ');
tx.alternativeAmountStr = v; tx.alternativeAmountStr = v;
tx.alternativeAmountValueStr = parts[0];
tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : '';
}); });
} }
@ -426,6 +429,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
function showSendMaxWarning(wallet, sendMaxInfo) { function showSendMaxWarning(wallet, sendMaxInfo) {
var feeAlternative = '',
msg = '';
function verifyExcludedUtxos() { function verifyExcludedUtxos() {
var warningMsg = []; var warningMsg = [];
@ -443,9 +448,18 @@ angular.module('copayApp.controllers').controller('confirmController', function(
return warningMsg.join('\n'); return warningMsg.join('\n');
}; };
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", { feeAlternative = txFormatService.formatAlternativeStr(wallet.coin, sendMaxInfo.fee);
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee) if (feeAlternative) {
}); msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", {
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee),
feeAlternative: feeAlternative
});
} else {
msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", {
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee)
});
}
var warningMsg = verifyExcludedUtxos(); var warningMsg = verifyExcludedUtxos();
if (!lodash.isEmpty(warningMsg)) if (!lodash.isEmpty(warningMsg))
@ -624,10 +638,11 @@ angular.module('copayApp.controllers').controller('confirmController', function(
(processName == 'sendingTx' && !$scope.wallet.canSign() && !$scope.wallet.isPrivKeyExternal()) (processName == 'sendingTx' && !$scope.wallet.canSign() && !$scope.wallet.isPrivKeyExternal())
) && !isOn) { ) && !isOn) {
$scope.sendStatus = 'success'; $scope.sendStatus = 'success';
if (config.soundsEnabled && $scope.wallet.coin == 'bch') {
var audio = new Audio('misc/bch_sent.mp3'); if ($state.current.name === "tabs.send.confirm") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device.
audio.play(); soundService.play('misc/payment_sent.mp3');
} }
firebaseEventsService.logEvent('sent_bitcoin', { coin: $scope.wallet.coin }); firebaseEventsService.logEvent('sent_bitcoin', { coin: $scope.wallet.coin });
$timeout(function() { $timeout(function() {
$scope.$digest(); $scope.$digest();

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('tabHomeController', angular.module('copayApp.controllers').controller('tabHomeController',
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) { function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) {
var wallet; var wallet;
var listeners = []; var listeners = [];
var notifications = []; var notifications = [];
@ -15,9 +15,19 @@ angular.module('copayApp.controllers').controller('tabHomeController',
$scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; $scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP;
$scope.isNW = platformInfo.isNW; $scope.isNW = platformInfo.isNW;
$scope.showServices = false; $scope.showServices = false;
$scope.bannerIsLoading = true;
$scope.bannerImageUrl = '';
$scope.bannerUrl = '';
$scope.$on("$ionicView.afterEnter", function() { $scope.$on("$ionicView.afterEnter", function() {
startupService.ready(); startupService.ready();
bannerService.getBanner(function (banner) {
$scope.bannerImageUrl = banner.imageURL;
$scope.bannerUrl = banner.url;
$scope.bannerIsLoading = false;
});
}); });
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
@ -117,8 +127,8 @@ angular.module('copayApp.controllers').controller('tabHomeController',
externalLinkService.open(url, optIn, title, message, okText, cancelText); externalLinkService.open(url, optIn, title, message, okText, cancelText);
}; };
$scope.openStore = function() { $scope.openBannerUrl = function() {
externalLinkService.open('https://store.bitcoin.com/', false); externalLinkService.open($scope.bannerUrl, false);
}; };
$scope.openNotificationModal = function(n) { $scope.openNotificationModal = function(n) {

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService) { angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService, soundService, clipboardService) {
var listeners = []; var listeners = [];
$scope.bchAddressType = { type: 'cashaddr' }; $scope.bchAddressType = { type: 'cashaddr' };
@ -15,22 +15,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
var config; var config;
var soundLoaded = false;
var nativeAudioAvailable = (window.plugins && window.plugins.NativeAudio);
if (nativeAudioAvailable) {
window.plugins.NativeAudio.preloadSimple('received', 'misc/coin_received.mp3', function (msg) {
$log.debug('Receive sound loaded.');
soundLoaded = true;
}, function (error) {
$log.debug('Error loading receive sound.');
$log.debug(error);
});
} else {
$log.debug('isNW: Using HTML5-Audio instead of native audio');
soundLoaded = true;
}
$scope.displayBalanceAsFiat = true; $scope.displayBalanceAsFiat = true;
$scope.requestSpecificAmount = function() { $scope.requestSpecificAmount = function() {
@ -74,6 +58,12 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
paymentSubscriptionObj.addr = $scope.addr paymentSubscriptionObj.addr = $scope.addr
} }
try {
clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr);
} catch (error) {
$log.debug("Error copying to clipboard:");
$log.debug(error);
}
// create subscription // create subscription
var msg = JSON.stringify(paymentSubscriptionObj); var msg = JSON.stringify(paymentSubscriptionObj);
currentAddressSocket.onopen = function (event) { currentAddressSocket.onopen = function (event) {
@ -143,21 +133,21 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
for (var i = 0; i < data.x.out.length; i++) { for (var i = 0; i < data.x.out.length; i++) {
if (data.x.out[i].addr == watchAddress) { if (data.x.out[i].addr == watchAddress) {
$scope.paymentReceivedAmount = txFormatService.formatAmount(data.x.out[i].value, 'full'); $scope.paymentReceivedAmount = txFormatService.formatAmount(data.x.out[i].value, 'full');
$scope.paymentReceivedAlternativeAmount = ''; // For when a subsequent payment is received.
txFormatService.formatAlternativeStr($scope.wallet.coin, data.x.out[i].value, function(alternativeStr){
if (alternativeStr) {
$scope.paymentReceivedAlternativeAmount = alternativeStr;
}
});
} }
} }
$scope.paymentReceivedCoin = $scope.wallet.coin; $scope.paymentReceivedCoin = $scope.wallet.coin;
$scope.$apply(function () {
if (config.soundsEnabled && soundLoaded) { if ($state.current.name === "tabs.receive") {
$log.debug('Play sound.'); soundService.play('misc/payment_received.mp3');
if (nativeAudioAvailable) { }
window.plugins.NativeAudio.play('received');
} else { $scope.$apply(function () {
new Audio('misc/coin_received.ogg').play(); // NW.js has no mp3 support
}
} else {
$log.debug('Sound is disabled.');
}
$scope.showingPaymentReceived = true; $scope.showingPaymentReceived = true;
}); });
} }

View file

@ -122,8 +122,11 @@ angular.module('copayApp.controllers').controller('tabScanController', function(
scannerService.openSettings(); scannerService.openSettings();
}; };
$scope.reactivationCount = 0;
$scope.attemptToReactivate = function(){ $scope.attemptToReactivate = function(){
scannerService.reinitialize(); scannerService.reinitialize(function(){
$scope.reactivationCount++;
});
}; };
$scope.toggleLight = function(){ $scope.toggleLight = function(){

View file

@ -76,8 +76,11 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
var walletList = []; var walletList = [];
lodash.each(walletsToTransfer, function(v) { lodash.each(walletsToTransfer, function(v) {
var displayBalanceAsFiat = var displayBalanceAsFiat =
v.status.alternativeBalanceAvailable && // BD got v.status as undefined here once during development, just
config.wallet.settings.priceDisplay === 'fiat'; // after creating a new wallet.
v.status &&
v.status.alternativeBalanceAvailable &&
config.wallet.settings.priceDisplay === 'fiat';
walletList.push({ walletList.push({
color: v.color, color: v.color,

View file

@ -0,0 +1,15 @@
angular.module('copayApp')
.config(['$provide', '$logProvider', function($provide, $logProvider) {
// expose a provider to reach debugEnabled in $log
$provide.value('$logProvider', $logProvider);
}])
.decorator('$log', ['$logProvider', '$delegate', function($logProvider, $delegate) {
// override $log.debug to display in Chrome
$delegate.debug = function () {
if ($logProvider.debugEnabled()) {
$delegate.info.apply($delegate, arguments);
}
};
return $delegate;
}]);

View file

@ -1,38 +1,26 @@
'use strict'; 'use strict';
angular.module('copayApp.directives') angular.module('copayApp.directives')
.directive('copyToClipboard', function(platformInfo, nodeWebkitService, gettextCatalog, ionicToast, clipboard) { .directive('copyToClipboard', function(clipboardService, ionicToast, gettextCatalog) {
return { return {
restrict: 'A', restrict: 'A',
scope: { scope: {
copyToClipboard: '=copyToClipboard' copyToClipboard: '=copyToClipboard'
}, },
link: function(scope, elem, attrs, ctrl) { link: function(scope, elem, attrs, ctrl) {
var isCordova = platformInfo.isCordova;
var isChromeApp = platformInfo.isChromeApp;
var isNW = platformInfo.isNW;
elem.bind('mouseover', function() { elem.bind('mouseover', function() {
elem.css('cursor', 'pointer'); elem.css('cursor', 'pointer');
}); });
var msg = gettextCatalog.getString('Copied to clipboard');
elem.bind('click', function() { elem.bind('click', function() {
var data = scope.copyToClipboard; var data = scope.copyToClipboard;
if (!data) return; clipboardService.copyToClipboard(data);
if (isCordova) { var msg = gettextCatalog.getString('Copied to clipboard');
cordova.plugins.clipboard.copy(data); scope.$apply(function () {
} else if (isNW) {
nodeWebkitService.writeToClipboard(data);
} else if (clipboard.supported) {
clipboard.copyText(data);
} else {
// No supported
return;
}
scope.$apply(function() {
ionicToast.show(msg, 'bottom', false, 1000); ionicToast.show(msg, 'bottom', false, 1000);
}); });
}); });
} }
} }

View file

@ -0,0 +1,78 @@
'use strict';
angular.module('copayApp.services').factory('bannerService', function ($http, $log) {
// Export
var root = {};
// Constant
var API_URL = 'https://bwscash.bitcoin.com/bws/api/v1/marketing';
// Variable
var hasFetched = false;
var banners = [];
var defaultBanner = {
id: 'default-banner',
imageURL: 'img/banner-store.png',
url: 'https://store.bitcoin.com/',
isLocal: true
};
// Private methods
var fetchSettings = function (cb) {
var req = {
method: 'GET',
url: API_URL+'/settings',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
};
$http(req).then(function (response) {
$log.info('Get banner settings: SUCCESS');
banners = response.data;
return cb(true);
}, function (error) {
$log.error('Get banner settings: ERROR ' + error.statusText);
return cb(false);
});
};
root.getBanner = function (cb) {
// If not fetch get the banner
if (!hasFetched) {
hasFetched = true;
// If never fetch, lets fetch
fetchSettings(function (isSuccess) {
root.getBanner(cb);
});
// If fetch, and got banners, lets have a look
} else if (banners.length > 0) {
var selectedBanners = [];
for(var i in banners) {
var banner = banners[i];
// Generate the URL for the banner
var fileName = banner.image.substring(0, banner.image.lastIndexOf('.'));
var extension = banner.image.substring(banner.image.lastIndexOf('.')+1);
banner.imageURL = API_URL +'/banners/'+fileName+"/"+extension;
// Add the banner
selectedBanners.push(banners[i]);
}
// If no banner activated, return the default one
if (selectedBanners.length == 0) {
return cb(defaultBanner);
} else {
return cb(selectedBanners[Math.floor(Math.random()*banners.length)]);
}
} else {
return cb(defaultBanner);
}
};
return root;
});

View file

@ -0,0 +1,24 @@
'use strict';
angular.module('copayApp.services').factory('clipboardService', function ($http, $log, platformInfo, nodeWebkitService, gettextCatalog, ionicToast, clipboard) {
var root = {};
root.copyToClipboard = function (data) {
if (!data) return;
$log.debug("Copy '"+data+"' to clipboard");
if (platformInfo.isCordova) {
cordova.plugins.clipboard.copy(data);
} else if (platformInfo.isNW) {
nodeWebkitService.writeToClipboard(data);
} else if (clipboard.supported) {
clipboard.copyText(data);
} else {
// No supported
return;
}
};
return root;
});

View file

@ -103,6 +103,7 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
_completeInitialization(status, callback); _completeInitialization(status, callback);
}); });
} else { } else {
isAvailable = true; // XX SP: Availability can change after permissions are granted after being denied.
_completeInitialization(status, callback); _completeInitialization(status, callback);
} }
}); });

View file

@ -0,0 +1,44 @@
'use strict';
angular.module('copayApp.services').service('soundService', function($log, $timeout, platformInfo, configService) {
var root = {};
/**
* Play a sound (when enabled in the configuration) using the Cordova Media-plugin (on Mobile) or html5-audio (on Desktop) relative to the www-root
* Make sure there is a .ogg file as well for NW.js (desktop) implementation
* @param soundFile
*/
root.play = function(soundFile) {
configService.whenAvailable(function(config) {
if (config.soundsEnabled) {
if (platformInfo.isCordova) {
if (platformInfo.isAndroid) {
var p = window.location.pathname;
var device_path = p.substring(0, p.lastIndexOf('/'));
soundFile = device_path + '/' + soundFile;
}
var audio = new Media(soundFile,
function () {
$log.debug("playAudio(bch_sent):Audio Success");
},
function (err) {
$log.debug("playAudio():Audio Error: " + err);
}
);
audio.play({playAudioWhenScreenIsLocked: false}); // XX SP: "Locked" is also the mute switch in iOS
} else {
if (platformInfo.isNW) {
soundFile = soundFile.substring(0, soundFile.lastIndexOf('.')) + ".ogg";
$log.debug("Playing .ogg file ("+soundFile+"), as NW.js has no mp3 support");
}
new Audio(soundFile).play();
}
}
});
};
return root;
});

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.services') angular.module('copayApp.services')
.factory('storageService', function(appConfigService, logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, secureStorageService, $timeout) { .factory('storageService', function(appConfigService, logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, $timeout) {
var root = {}; var root = {};
var storage; var storage;
@ -121,11 +121,7 @@ angular.module('copayApp.services')
root.storeProfile = function(profile, cb) { root.storeProfile = function(profile, cb) {
var profileString = profile.toObj(); var profileString = profile.toObj();
if (platformInfo.isNW) { storage.set('profile', profileString, cb);
storage.set('profile', profileString, cb);
} else {
secureStorageService.set('profile', profileString, cb);
}
}; };
/** /**
@ -205,48 +201,19 @@ angular.module('copayApp.services')
* @param {getProfileCallback} cb * @param {getProfileCallback} cb
*/ */
root.getProfile = function(cb) { root.getProfile = function(cb) {
if (platformInfo.isNW) { storage.get('profile', function(getErr, getStr) {
storage.get('profile', function(getErr, getStr) { if (getErr) {
_onOldProfileRetrieved(getErr, getStr, cb); cb(getErr, null);
}); return;
return
}
secureStorageService.get('profile', function(secureErr, secureStr) {
var secureProfile;
var oldProfile;
if (secureErr) {
return cb(secureErr, null);
} }
if (secureStr) { if (!getStr) {
try { cb(null, null);
secureProfile = Profile.fromString(secureStr); return;
$log.debug('profile: ' + JSON.stringify(secureProfile));
} catch (e) {
$log.error(e);
return cb(e, null);
}
} }
storage.get('profile', function(getErr, getStr) { var profile = Profile.fromString(getStr);
_onOldProfileRetrieved(getErr, getStr, function(oldErr, oldProfile){ cb(null, profile);
if (oldErr) {
return cb(oldErr, null);
}
if (!oldProfile) {
if (secureProfile) {
return cb(null, secureProfile);
} else {
// No profiles found. No errors either.
return cb(null, null);
}
}
_migrateProfiles(oldProfile, secureProfile, cb);
});
});
}); });
}; };

View file

@ -72,11 +72,19 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
var config = configService.getSync().wallet.settings; var config = configService.getSync().wallet.settings;
var val = function() { var val = function() {
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode, coin)).toFixed(2)); var fiatAmount = rateService.toFiat(satoshis, config.alternativeIsoCode, coin);
v1 = $filter('formatFiatAmount')(v1); var roundedStr = fiatAmount.toFixed(2);
var roundedNum = parseFloat(roundedStr);
var subcent = roundedNum === 0 && fiatAmount > 0;
var lessThanPrefix = '';
if (subcent) {
roundedNum = 0.01;
lessThanPrefix = '< ';
}
var v1 = $filter('formatFiatAmount')(roundedNum);
if (!v1) return null; if (!v1) return null;
return v1 + ' ' + config.alternativeIsoCode; return lessThanPrefix + v1 + ' ' + config.alternativeIsoCode;
}; };
// Async version // Async version

View file

@ -0,0 +1,68 @@
describe('txFormatService', function(){
var configServiceMock,
rateServiceMock,
txFormatService;
beforeEach(function(){
module('ngLodash');
module('bwcModule');
module('copayApp.filters');
module('copayApp.services');
configServiceMock = {
getSync: jasmine.createSpy()
};
rateServiceMock = {
isAvailable: jasmine.createSpy(),
toFiat: jasmine.createSpy()
};
module(function($provide) {
$provide.value('configService', configServiceMock);
$provide.value('rateService', rateServiceMock);
});
inject(function($injector){
txFormatService = $injector.get('txFormatService');
});
});
it('formatAlternativeStr 0.49 cents.', function() {
configServiceMock.getSync.and.returnValue({
wallet: {
settings: {
alternativeIsoCode: 'USD'
}
}
});
rateServiceMock.isAvailable.and.returnValue(true);
rateServiceMock.toFiat.and.returnValue(0.00499);
var formatted = txFormatService.formatAlternativeStr('bch', 123);
expect(formatted).toBe('< 0.01 USD');
});
it('formatAlternativeStr 0.5 cents.', function() {
configServiceMock.getSync.and.returnValue({
wallet: {
settings: {
alternativeIsoCode: 'USD'
}
}
});
rateServiceMock.isAvailable.and.returnValue(true);
rateServiceMock.toFiat.and.returnValue(0.005);
var formatted = txFormatService.formatAlternativeStr('bch', 123);
expect(formatted).toBe('0.01 USD');
});
});

View file

@ -1,14 +1,15 @@
qrcode { qrcode {
&.qr-icon { position: relative;
&.qr-overlay {
&::before { &::before {
content: ""; content: "";
background-size: 100% 100%; background-size: 100% 100%;
display: block; display: block;
margin-left: calc(50% - 22px); left: 88px;
margin-top: 88px; margin-top: 88px;
width: 44px; width: 44px;
height: 44px; height: 44px;
position: absolute; position:absolute;
} }
&--bch::before { &--bch::before {
background-image: url('../img/qr-overlay-bch.png'); background-image: url('../img/qr-overlay-bch.png');

View file

@ -36,6 +36,11 @@
.amount-label{ .amount-label{
line-height: 30px; line-height: 30px;
.amount{ .amount{
font-size: 16px;
color: #9B9B9B;
font-family: "Roboto-Light";
}
.alternative {
font-size: 38px; font-size: 38px;
margin-bottom: .5rem; margin-bottom: .5rem;
@ -43,11 +48,6 @@
font-family: "Roboto-Light"; font-family: "Roboto-Light";
} }
} }
.alternative {
font-size: 16px;
font-family: "Roboto-Light";
color: #9B9B9B;
}
} }
} }
.item { .item {

View file

@ -59,6 +59,9 @@
} }
} }
&-banner { &-banner {
svg {
margin: 40px auto 40px;
}
padding: 0; padding: 0;
&__img { &__img {
width: 100%; width: 100%;

11
src/shim/shim.js Normal file
View file

@ -0,0 +1,11 @@
//---------------------------------------------------------------------
//
// Add components what are missing in old JavaScript Engine
//
//---------------------------------------------------------------------
if (!ArrayBuffer['isView']) {
ArrayBuffer.isView = function(a) {
return a !== null && typeof(a) === "object" && a['buffer'] instanceof ArrayBuffer;
};
}

BIN
www/misc/payment_sent.ogg Normal file

Binary file not shown.

View file

@ -16,8 +16,8 @@
<span translate ng-if="tx.sendMax">Sending maximum amount</span> <span translate ng-if="tx.sendMax">Sending maximum amount</span>
</div> </div>
<div class="amount-label"> <div class="amount-label">
<div class="alternative">{{tx.alternativeAmountValueStr || '...'}} <span class="unit">{{tx.alternativeAmountUnitStr}}</span></div>
<div class="amount">{{tx.amountValueStr || '...'}} <span class="unit">{{tx.amountUnitStr}}</span></div> <div class="amount">{{tx.amountValueStr || '...'}} <span class="unit">{{tx.amountUnitStr}}</span></div>
<div class="alternative">{{tx.alternativeAmountStr || '...'}}</div>
</div> </div>
</div> </div>
<div class="info"> <div class="info">
@ -77,9 +77,9 @@
</a> </a>
<div class="item item-icon-right" ng-if="wallet" ng-click="chooseFeeLevel(tx, wallet)"> <div class="item item-icon-right" ng-if="wallet" ng-click="chooseFeeLevel(tx, wallet)">
<span class="label">{{'Fee:' | translate}} {{tx.feeLevelName | translate}}</span> <span class="label">{{'Fee:' | translate}} {{tx.feeLevelName | translate}}</span>
<span class="m10l">{{tx.txp[wallet.id].feeStr || '...'}}</span> <span class="m10l">{{tx.txp[wallet.id].alternativeFeeStr || '...'}}</span>
<span class="item-note m10l"> <span class="item-note m10l">
<span>{{tx.txp[wallet.id].alternativeFeeStr || '...'}}&nbsp; <span>{{tx.txp[wallet.id].feeStr || '...'}}&nbsp;
<span class="fee-rate" ng-if="tx.txp[wallet.id].feeRatePerStr"> &middot; <span class="fee-rate" ng-if="tx.txp[wallet.id].feeRatePerStr"> &middot;
<i class="ion-alert-circled warn" ng-show="tx.txp[wallet.id].feeToHigh"></i> &nbsp; <i class="ion-alert-circled warn" ng-show="tx.txp[wallet.id].feeToHigh"></i> &nbsp;
<span class="fee-rate" ng-class="{'warn':tx.txp[wallet.id].feeToHigh}" translate> {{tx.txp[wallet.id].feeRatePerStr}} of the sending amount </span> <span class="fee-rate" ng-class="{'warn':tx.txp[wallet.id].feeToHigh}" translate> {{tx.txp[wallet.id].feeRatePerStr}} of the sending amount </span>

View file

@ -41,7 +41,6 @@
<div class="subheader" ng-if="walletsBtc[0] && walletsBch[0]" translate> <div class="subheader" ng-if="walletsBtc[0] && walletsBch[0]" translate>
<div translate>Bitcoin Core (BTC)</div> <div translate>Bitcoin Core (BTC)</div>
<div translate class="subtitle">Slow transactions with high fees</div>
</div> </div>
<a <a
ng-repeat="wallet in walletsBtc track by $index" ng-repeat="wallet in walletsBtc track by $index"

View file

@ -71,7 +71,6 @@
<div class="list card"> <div class="list card">
<div class="item item-icon-right item-heading"> <div class="item item-icon-right item-heading">
<div translate>Bitcoin Core (BTC)</div> <div translate>Bitcoin Core (BTC)</div>
<div translate class="subtitle">Slow transactions with high fees</div>
<a ui-sref="tabs.add"><i class="icon ion-ios-plus-empty list-add-button"></i></a> <a ui-sref="tabs.add"><i class="icon ion-ios-plus-empty list-add-button"></i></a>
</div> </div>
<div> <div>
@ -90,9 +89,11 @@
<div class="ng-hide list card" ng-show="showServices && (walletsBch[0] || walletsBtc[0])" ng-include="'views/includes/services.html'"></div> <div class="ng-hide list card" ng-show="showServices && (walletsBch[0] || walletsBtc[0])" ng-include="'views/includes/services.html'"></div>
<div class="list card card-banner"> <div class="list card card-banner">
<a ng-click="openStore()"> <ion-spinner ng-if="bannerIsLoading"></ion-spinner>
<img class="card-banner__img" src="img/banner-store.png"/> <a ng-if="!bannerIsLoading" ng-click="openBannerUrl()">
<img class="card-banner__img" ng-src="{{bannerImageUrl}}"/>
</a> </a>
</div> </div>
<div class="ng-hide list card" ng-show="nextStepsItems.length>0 && !isWindowsPhoneApp" ng-include="'views/includes/community.html'"></div> <div class="ng-hide list card" ng-show="nextStepsItems.length>0 && !isWindowsPhoneApp" ng-include="'views/includes/community.html'"></div>

View file

@ -41,16 +41,16 @@
</button> </button>
</span> </span>
<qrcode class="qr-icon qr-icon--{{ wallet.coin }}" ng-if="addr" size="220" data="{{ protocolHandler }}:{{addr}}" color="#334"></qrcode> <qrcode class="qr-overlay qr-overlay--{{ wallet.coin }}" ng-if="addr" size="220" data="{{ protocolHandler }}:{{addr}}" color="#334"></qrcode>
<div class="address-label"> <div class="address-label">
<span class="ellipsis">{{addr}}</span> <span class="ellipsis">{{addr}}</span>
<ion-spinner ng-show="!addr" class="spinner-dark" icon="crescent"></ion-spinner> <ion-spinner ng-show="!addr" class="spinner-dark" icon="crescent"></ion-spinner>
</div> </div>
<div> </div>
<button ng-show="addr" class="button-address" ng-click="setAddress(true)"> <div>
<span translate>Generate new address</span> <button ng-show="addr" class="button-address" ng-click="setAddress(true)">
</button><br/> <span translate>Generate new address</span>
</div> </button><br/>
</div> </div>
</div> </div>
<!-- animation for payment received --> <!-- animation for payment received -->
@ -61,7 +61,8 @@
</svg> </svg>
<p class="success animated fadeIn"> <p class="success animated fadeIn">
<br/>Payment Received! <br/>Payment Received!
<span class="payment-received-amount">{{ paymentReceivedAmount }} <span class="payment-received-currency">{{ paymentReceivedCoin }}</span></span> <span ng-if="!(displayBalanceAsFiat && paymentReceivedAlternativeAmount)" class="payment-received-amount">{{ paymentReceivedAmount }} <span class="payment-received-currency">{{ paymentReceivedCoin }}</span></span>
<span ng-if="displayBalanceAsFiat && paymentReceivedAlternativeAmount" class="payment-received-amount">{{ paymentReceivedAlternativeAmount }}</span></span>
Return To Address<br/> Return To Address<br/>
</p> </p>
</div> </div>

View file

@ -16,7 +16,7 @@
<div class="zero-state-description" translate>You can scan bitcoin addresses, payment requests, paper wallets, and more.</div> <div class="zero-state-description" translate>You can scan bitcoin addresses, payment requests, paper wallets, and more.</div>
<div class="zero-state-cta"> <div class="zero-state-cta">
<div class="ng-hide zero-state-tldr" ng-show="!currentState || currentState === scannerStates.unauthorized" translate>Enable the camera to get started.</div> <div class="ng-hide zero-state-tldr" ng-show="!currentState || currentState === scannerStates.unauthorized" translate>Enable the camera to get started.</div>
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.denied" translate>Enable camera access in your device settings to get started.</div> <div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.denied || reactivationCount > 2" translate>Enable camera access in your device settings to get started.</div>
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.unavailable" translate>Please connect a camera to get started.</div> <div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.unavailable" translate>Please connect a camera to get started.</div>
<button ng-show="!currentState || currentState === scannerStates.unauthorized" class="ng-hide button button-standard button-primary" ng-click="authorize()" translate>Allow Camera Access</button> <button ng-show="!currentState || currentState === scannerStates.unauthorized" class="ng-hide button button-standard button-primary" ng-click="authorize()" translate>Allow Camera Access</button>
<button ng-show="currentState === scannerStates.denied && canOpenSettings" class="ng-hide button button-standard button-primary" ng-click="openSettings()" translate>Open Settings</button> <button ng-show="currentState === scannerStates.denied && canOpenSettings" class="ng-hide button button-standard button-primary" ng-click="openSettings()" translate>Open Settings</button>