Merge pull request #1 from bitpay/master

Sync with master
This commit is contained in:
Rich Morgan 2015-07-14 12:17:10 -04:00
commit 7af82a0e97
120 changed files with 6393 additions and 1769 deletions

9
.gitignore vendored
View file

@ -9,6 +9,15 @@ src/js/version.js
cordova/project/*
cordova/*.keystore
# node-webkit
cache
webkitbuilds/*
!webkitbuilds/README.md
!webkitbuilds/setup-win32.iss
!webkitbuilds/setup-win64.iss
!webkitbuilds/favicon.ico
!webkitbuilds/.desktop
# chrome extensions
browser-extensions/chrome/copay-chrome-extension
browser-extensions/chrome/copay-chrome-extension.zip

View file

@ -30,6 +30,12 @@ module.exports = function(grunt) {
},
clear: {
command: 'rm -Rf bower_components node_modules'
},
osx64: {
command: 'hdiutil create -megabytes 150 -volname Copay -srcfolder webkitbuilds/copay/osx64/copay.app/ -ov -format UDZO webkitbuilds/copay-osx64.dmg'
},
osx32: {
command: 'hdiutil create -megabytes 150 -volname Copay -srcfolder webkitbuilds/copay/osx32/copay.app/ -ov -format UDZO webkitbuilds/copay-osx32.dmg'
}
},
watch: {
@ -165,6 +171,12 @@ module.exports = function(grunt) {
flatten: true,
src: 'bower_components/foundation-icon-fonts/foundation-icons.*',
dest: 'public/icons/'
},
linux: {
files: [
{expand: true, cwd: 'webkitbuilds/',src: ['.desktop', 'favicon.ico'],dest: 'webkitbuilds/copay/linux32/', flatten: true, filter: 'isFile' },
{expand: true, cwd: 'webkitbuilds/',src: ['.desktop', 'favicon.ico'],dest: 'webkitbuilds/copay/linux64/', flatten: true, filter: 'isFile' },
],
}
},
karma: {
@ -184,6 +196,36 @@ module.exports = function(grunt) {
force: true,
recursive: false
}
},
nodewebkit: {
options: {
platforms: ['win','osx','linux'],
buildDir: './webkitbuilds',
version: '0.12.2',
macIcns: './public/img/icons/icon.icns',
exeIco: './public/img/icons/icon.ico'
},
src: ['./package.json', './public/**/*']
},
compress: {
linux32: {
options: {
archive: './webkitbuilds/copay-linux32.zip'
},
expand: true,
cwd: './webkitbuilds/copay/linux32/',
src: ['**/*'],
dest: 'copay-linux32/'
},
linux64: {
options: {
archive: './webkitbuilds/copay-linux64.zip'
},
expand: true,
cwd: './webkitbuilds/copay/linux64/',
src: ['**/*'],
dest: 'copay-linux64/'
}
}
});
@ -197,10 +239,11 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-exec');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-karma-coveralls');
grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.registerTask('default', [
'nggettext_compile', 'exec:version', 'concat', 'copy'
'nggettext_compile', 'exec:version', 'concat', 'copy:icons'
]);
grunt.registerTask('prod', [
'default', 'uglify'
@ -208,4 +251,5 @@ module.exports = function(grunt) {
grunt.registerTask('translate', ['nggettext_extract']);
grunt.registerTask('test', ['karma:unit']);
grunt.registerTask('test-coveralls', ['karma:prod', 'coveralls']);
grunt.registerTask('desktop', ['prod', 'nodewebkit', 'copy:linux', 'compress:linux32', 'compress:linux64', 'exec:osx32', 'exec:osx64']);
};

157
README.md
View file

@ -1,22 +1,28 @@
<img src="https://raw.githubusercontent.com/marianorod/copay-brand/master/copay-logo-full-negative.png" alt="Copay" width="300">
<img src="https://raw.githubusercontent.com/bitpay/copay/master/public/img/logo.png" alt="Copay" width="300">
[![Build Status](https://secure.travis-ci.org/bitpay/copay.svg)](http://travis-ci.org/bitpay/copay)
[![Coverage Status](https://img.shields.io/coveralls/bitpay/copay.svg)](https://coveralls.io/r/bitpay/copay?branch=master)
[![Stories in Ready](https://badge.waffle.io/bitpay/copay.svg?label=in progress&title=In progress)](https://waffle.io/bitpay/copay)
*Copay* is an easy-to-use, open-source, multiplatform, multisignature, secure bitcoin wallet platform for both individuals and companies.
Copay is an easy-to-use, open-source, multiplatform, multisignature, secure bitcoin wallet platform for both individuals and companies. Copay uses Bitcore-Wallet-Service (https://github.com/bitpay/bitcore-wallet-service) for peer synchronization and bitcore network interfacing.
*Copay* uses Bitcore-Wallet-Service (https://github.com/bitpay/bitcore-wallet-service) for peer synchronization and bitcore network interfacing.
Binary versions of Copay are available for download at [Copay.io](https://copay.io)
## Before you start
## Main Features
Current Copay version is meant to be run on *mobile devices OR desktop application*, NOT browsers.
- Multiple wallet creation and management in-app
- Intuitive multisignature security for personal or shared wallets
- Easy spending proposal flow for shared wallets and group payments
- Hierarchical deterministic (HD) address generation and wallet backups
- Device-based security: all private keys are stored locally, not in the cloud
- Support for Bitcoin testnet wallets
- Synchronous access across all major mobile and desktop platforms
- Payment protocol (BIP70-BIP73) support: easily-identifiable payment requests and verifiably secure bitcoin payments
- Support for 150+ currency pricing options and unit denomination in BTC or bits
- Email notifications for payments and transfers
- Customizable wallet naming and background colors
- Multiple languages supported
- Available for iOS, Android, Windows Phone, Chrome App, Linux, Windows and OSX.
When running Copay as a web page, and a browser extension is enabled, the browser extension
could have access to Copay internal data, and compromise the user's private key
and more.
## Installation
# Installation
```sh
git clone https://github.com/bitpay/copay.git
@ -30,131 +36,82 @@ npm install -g bower
npm install -g grunt-cli
```
Build *Copay*:
Build Copay:
```sh
bower install
npm install
grunt
```
For production environments:
```sh
grunt prod
```
Open *Copay*:
```sh
npm start
```
Then visit localhost:3000 in your browser.
## Bitcore Wallet Service
When running Copay as a web page, and a browser extension is enabled, the browser extension
could have access to Copay internal data, and compromise the user's private key
and more.
Copay depends on Bitcore Wallet Service (BWS) for blockchain information, networking and copayer synchronization. BWS can be run within minutes or you can use a public instance. Switch between BWS instances is very simple and can be done with a click from Copay. BWS also allows Copay to interoperate with others wallet like Bitcore-Wallet CLI https://github.com/bitpay/bitcore-wallet
## Build Copay App Bundles
## Android
## Tests
- Install Android SDK
- Run `make android`
Open test/index.html in your browser to test models. Install [mocha](https://www.npmjs.com/package/mocha) and [karma](https://www.npmjs.com/package/karma-cli) to test the services and controllers.
### iOS
```sh
npm install mocha
npm install karma-cli
```
- Install XCode 6.1 (or newer)
- Run `make ios-prod`
Run all tests:
### Windows Phone
```sh
mocha
karma start
```
- Install Visual Studio 2013 (or newer)
- Run `make wp8-prod`
## Troubleshooting
### Desktop versions (Windows, OSX, Linux)
### Building on Ubuntu 14.04, gyp, Python
Copay uses NW.js (also know as node-webkit) for its desktop version. NW.js an app runtime based on `Chromium` and `node.js`.
If you are using Ubuntu and encounter this error (or one similar):
- Install NW.js in your system from [nw.js](http://nwjs.io/)
- Run `grunt desktop` (*)
### Google Chrome App
```sh
gyp_main.py: error: no such option: --no-parallel
gyp ERR! configure error
gyp ERR! stack Error: `gyp` failed with exit code: 2
```
This is because Ubuntu 14.04 and 14.10 have Python 2.7 installed by default but **gyp** requires Python 2.6. See: (http://stackoverflow.com/questions/21155922/error-installing-node-gyp-on-ubuntu)
One solution to this issue is to use *Copay* with a Python version manager and install 2.6. For example, if you have pyenv installed:
```sh
pyenv install 2.6.9
pyenv global 2.6.9
```
# Development
## Google Chrome App
To build *Copay*'s Chrome App, run:
```sh
npm run-script chrome
```
- Run `npm run-script chrome`
On success, the chrome extension will be located at: `browser-extensions/chrome/copay-chrome-extension`
To install it go to `chrome://extensions/` in your Chrome browser and ensure you have the 'developer mode' option enabled in the settings. Then click on "Load unpacked chrome extension" and choose the directory mentioned above.
## Firefox Add-on
### Firefox Add-on
The *Copay* Firefox Extension has been deprecated and is no longer supported.
# QA and Bug Reporting
In the interest of improving bug reporting, for each bug that you find and want to create a ticket about, please refer to a form that contains:
* A brief description of the bug
* Steps required to reproduce it
* The platform in which you are testing
* Any screenshots, if possible
* The expected behaviour
For example, a really useful bug report should look like:
```
Problem: The application fails at login.
To reproduce:
1. Launch the app with `npm run start`
2. Click on "Join a Wallet"
3. Type an nonexistent username
4. The app stops working and throws an "Unhandled exception" error.
Expected: The app should login to the home screen after clicking login and show no errors.
Platform: Android 4.3, Android 4.4, iOS
```
# About *Copay*
# About Copay
## General
*Copay* implements a multisig wallet using [p2sh](https://en.bitcoin.it/wiki/Pay_to_script_hash) addresses. It supports multiple wallet, with with its own configuration, such as 3-of-5 (3 required signatures from 5 participant peers) or 2-of-3. To create a multisig wallet shared between multiple participants, *Copay* requires the extended public keys of all the wallet participants. Those public keys are then incorporated into the wallet configuration and combined to generate a payment address where funds can be sent into the wallet. Conversely, each participant manages their own private key and that private key is never transmitted anywhere.
Copay implements a multisig wallet using [p2sh](https://en.bitcoin.it/wiki/Pay_to_script_hash) addresses. It supports multiple wallet, with with its own configuration, such as 3-of-5 (3 required signatures from 5 participant peers) or 2-of-3. To create a multisig wallet shared between multiple participants, Copay requires the extended public keys of all the wallet participants. Those public keys are then incorporated into the wallet configuration and combined to generate a payment address where funds can be sent into the wallet. Conversely, each participant manages their own private key and that private key is never transmitted anywhere.
To unlock a payment and spend the wallet's funds, a quorum of participant signatures must be collected and assembled in the transaction. The funds cannot be spent without at least the minimum number of signatures required by the wallet configuration (2 of 3, 3 of 5, 6 of 6, etc). Once a transaction proposal is created, the proposal is distributed among the wallet participants for each to sign the transaction locally. Once the transaction is signed, the last signing participant will broadcast the transaction to the Bitcoin network.
*Copay* also implements [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) to generate new addresses for peers. The public key that each participant contributes to the wallet is a BIP32 extended public key. As additional public keys are needed for wallet operations (to produce new addresses to receive payments into the wallet, for example) new public keys can be derived from the participants' original extended public keys. Once again, it's important to stress that each participant keeps their own private keys locally - private keys are not shared - and are used to sign transaction proposals to make payments from the shared wallet.
Copay also implements [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) to generate new addresses for peers. The public key that each participant contributes to the wallet is a BIP32 extended public key. As additional public keys are needed for wallet operations (to produce new addresses to receive payments into the wallet, for example) new public keys can be derived from the participants' original extended public keys. Once again, it's important to stress that each participant keeps their own private keys locally - private keys are not shared - and are used to sign transaction proposals to make payments from the shared wallet.
For more information regarding how addresses are generated using this procedure, see: [Structure for Deterministic P2SH Multisignature Wallets](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki).
# Bitcore Wallet Service
Copay depends on [Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service) (BWS) for blockchain information, networking and copayer synchronization. BWS can be run within minutes or you can use a public instance. Switch between BWS instances is very simple and can be done with a click from Copay. BWS also allows Copay to interoperate with others wallet like Bitcore-Wallet CLI https://github.com/bitpay/bitcore-wallet.
Alternativelly, public BWS instances (like `https://bws.bitpay.com`) can be used.
# Translations
Copay uses standart gettext PO files for tranlations. It is currently translated to spanish, japanese, french, german and portuguese thank to community contributions. See https://github.com/bitpay/copay/pull/2880 as an example pull request for adding translations.
Translation Credits: Japanese: @dabura667, French: @kirvx, Portuguese: @pmichelazzo, Spanish: @cmgustavo, German: @saschad. Gracias totales!
For more information regarding how addresses are generated using this procedure, see: [Structure for Deterministic P2SH Multisignature Wallets](https://github.com/maraoz/bips/blob/master/bip-NNNN.mediawiki).
## Bitcore
Copay uses the powerful and feature-rich [Bitcore](https://github.com/bitpay/bitcore) Javascript library for Bitcoin-related functions. Bitcore should be built this way:
## Payment Protocol
Copay currently supports [BIP70 (Payment Protocol)](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki), with the following limitations:
* Only one output is allowed. Payment requests that are more that one output are not supported.
* Only standard Pay-to-pubkeyhash and Pay-to-scripthash scripts are supported (on payment requests). Other script types will cause the entire payment request to be rejected.
* Memos from the customer to the server are not supported (i.e. there is no place to write messages to the server in the current UX)

42
appstore_de Normal file
View file

@ -0,0 +1,42 @@
--------------------------------
Google Play Store Beschreibung
--------------------------------
Sichere Bitcoins zu eigenen Bedingungen, mit einem quelloffenen Gemeinschaftswallet(elektronische Brieftasche mit Mehrfachunterschriften) von BitPay.
Copay Nutzer können ihre Beträge individuell speichern oder ihre Finanzen mit anderen Nutzern in Gemeinschaftswallets teilen, die je nach Einstellung mehrere Bestätigungen (elektronische Unterschriften) benötigen und so nichtautorisierte Zahlungen verhindern.
Ein paar Einsatzmöglichkeiten, wie ein solches Wallet mit anderen Copayern genutzt werden kann:
Ansparen von Beträgen für Urlaub oder gemeinsame Anschaffungen (z.B. mit Freunden)
Überwachung von Ausgaben und Einkünften der Familie
Organisation der Ausgaben in Firmen, Vereinen oder Organisationen
Folgende Funktionen wurden in diese Version von Copay eingebaut um ein Bitcoin Wallet anzubieten das keine Kompromisse in Sichereit oder Zugänglichkeit eingeht:
Anlage und Verwaltung von mehreren Wallets innerhalb der Anwendung
Intiutive mehrfachunterschriften Sicherheit für persönliche und geteilete Wallets
Einfache Ausgabenvorschläge für geteilte Walltes und Gruppenzahlungen
Hierarchische deterministische(HD) Adresserzeugung und Sicherung der Wallets
Gerätebasierte Sicherheit: Alle privaten Schlüssel werden auf dem Gerät und nicht in der Cloud gespreichert
Unterstützung von Bitcoin Testnet Wallets
Gleichzeitiger Zugriff über alle wichtigen mobilen Systeme und Desktop-Plattformen
Zahlungsprotokoll (BIP70-BIP73) Unterstützung: Leicht identifizierbare Zahlungsanforderungen und nachvollziehbare sichere Bitcoinzahlungen.
Unterstützung von 150+ verschiedenen Währungen und Stückelung in BTC oder bits
E-Mail Benachrichtigung für Zahlungen und Transaktionen
Anpasspare Wallets: Eigene Namen und Hintergrundfarben
6 unterstützte Sprachen (deutsch, englisch, spanisch, französisch, japanisch, portugiesisch)
Copay ist eine kostenlose und quelloffene Software, die auf nicht firmeneigenen Servern läuft und es somit nicht nötig ist, sich auf ein bestimmtes Unternehmen und dessen kontinuierliche Unterstützung zu verlassen. Jeder hat die Möglichkeit den Quelltext zu überprüfen oder auf GitHub (https://github.com/bitpay/copay) eigene Änderungen beizutragen und an der Weiterentwicklung mitzuwirken.
--------------------------------
Google Play Store Release Notes: "What's new"
--------------------------------
v1.0.2
--------------------------------
Nach achtmonatigem Test hat Copay die Betaphase verlassen!
--------------------------------
v1.0.1
--------------------------------
Besserer Umgang mit Fehlern durch Netzwerkunterbrechungen
Bessere Logik nach Akzeptanz oder Ablehung von Zahlungen
Aktualisierung von ES, FR and JP Übersetzungen
Korrektur der Scroll-/Blätterfunktion in einigen Popups
--------------------------------

51
appstore_en Normal file
View file

@ -0,0 +1,51 @@
--------------------------------
Google Play store description
--------------------------------
Secure bitcoin on your own terms with an open source, multisignature wallet from BitPay.
Copay users can hold funds individually or share finances securely with other users with multisignature wallets, which prevent unauthorized payments by requiring multiple approvals. Here are some ways Copay can be used with others:
To save for vacations or joint purchases with friends
To track family spending and allowances
To manage business, club, or organization funds and expenses
We built the following features into this version of Copay for a bitcoin wallet that doesn't compromise on security or accessibility:
Multiple wallet creation and management in-app
Intuitive multisignature security for personal or shared wallets
Easy spending proposal flow for shared wallets and group payments
Hierarchical deterministic (HD) address generation and wallet backups
Device-based security: all private keys are stored locally, not in the cloud
Support for Bitcoin testnet wallets
Synchronous access across all major mobile and desktop platforms
Payment protocol (BIP70-BIP73) support: easily-identifiable payment requests and verifiably secure bitcoin payments
Support for 150+ currency pricing options and unit denomination in BTC or bits
Email notifications for payments and transfers
Customizable wallet naming and background colors
4 supported languages (EN, JP, FR, ES)
Copay is free and open source software run on non-proprietary servers, so there's no need to rely on any company for continuous support. Anyone can review or contribute to Copay's source code on GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.1.0
--------------------------------
QR Codes with specified amount for Receiving Payments
Fund Transfer Between Wallets
HTML Email Notifications
Custom Transaction Fee Settings
Send Maximum Amount of Funds
New Spending Proposal Deletion Rules
Bugs Fixes for Offline Functionality
--------------------------------
v1.0.2
--------------------------------
Copay is now out of beta! We've spent eight months testing Copay, and we're production-ready.
--------------------------------
v1.0.1
--------------------------------
Better handling of network interruption errors
Better refresh logic after accepting/rejecting payments
Updates ES, JP and FR translations
Fix scroll with in certain popups
--------------------------------

42
appstore_es Normal file
View file

@ -0,0 +1,42 @@
--------------------------------
Google Play store description
--------------------------------
Asegura tus bitcoin con tus propias reglas con el monedero de código abierto, multifirma de BitPay.
Los usuario de Copay pueden mantener sus fondos individuales o compartir sus finanzas de forma segura con otros usuarios utilizando monederos multifirmas, que previenen de pagos sin autorización al requerir múltiples aprobaciones. Estas son algunas formas en que puede ser utilizado Copay con otros usuarios:
Ahorrar para vacaciones o compras conjuntas con amigos
Controlar los gastos familiares
Manejar los fondos y gastos de negocios, clubes y organizaciones.
Construimos las siguientes características en esta versión de Copay que no compromete la seguridad ni la accesibilidad:
Creación y manejo de múltiples monederos dentro de la misma aplicación
Seguridad multifirma intuitiva para monederos personales y compartidos
Sencillo flujo de propuesta de gastos para monederos compartidos y grupos de pagos
Generación de direcciones HD (Hierarchical deterministic) y copias de seguridad
Seguridad basada en el dispositivo: todas las claves privadas se guardan localmente, no en la nube
Soporta monederos bitcoin en testnet
Acceso sincrónico desde las principales plataformas móviles y de escritorio
Soporte al protocolo de pago (BIP70-BIP73): solicitudes de pagos fácilmente identificable y verificables como pago seguro en bitcoin
Soporte a más de 150 precios de monedas y unidades de denominación en BTC o bits
Notificaciones por email de pagos y transferencias
Monederos con nombres y colores de fondo personalizables
4 idiomas soportados (EN, JP, FR, ES)
Copay es un software gratuito y de código abierto que funciona en servidores no-propietarios, por lo que no es necesario confiar en una empresa para soporte continuo. Cualquier persona puede revisar y contribuir al código fuente de Copay en GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.0.2
--------------------------------
¡Copay esta fuera de beta! Estuvimos ocho meses probando Copay, y ahora estamos listos en producción.
--------------------------------
v1.0.1
--------------------------------
Mejor manejo de errores en interrupciones de la red
Mejor lógica de actualización luego de aceptar/rechazar pagos
Actualiza traducciones en ES, JR y FR.
Corrige el desplazamiento en algunas ventanas emergentes
--------------------------------

52
appstore_fr Normal file
View file

@ -0,0 +1,52 @@
--------------------------------
Google Play store description
--------------------------------
Sécurisez vos bitcoins selon vos conditions avec un portefeuille open source et multi-signatures par BitPay.
Les utilisateurs de Copay peuvent détenir leurs fonds de manière individuelle, ou partager leurs finances de manière sécurisée avec les autres utilisateurs en utilisant des portefeuilles multi-signatures, ce qui empêche les paiements non autorisés en exigeant des approbations multiples.
Voici quelques exemples d'utilisation que vous pouvez avoir avec Copay et avec d'autres utilisateurs :
• Économiser pour des vacances ou partager des frais avec des amis.
• Suivre des dépenses et remboursements familiaux.
• Gérer des fonds et des dépenses pour une entreprise, un club ou une organisation.
Nous avons développé les fonctionnalités suivantes dans cette version de Copay pour un portefeuille bitcoin qui ne fait pas de compromis sur la sécurité ou sur l'accessibilité :
• Création et gestion de portefeuilles multiples.
• Sécurité de multi-signatures intuitive pour les portefeuilles personnels ou partagés.
• Demande de paiement facile pour les portefeuilles partagés et pour les paiements de groupe.
• Génération d'adresse déterministe hiérarchique (HD) et sauvegardes de portefeuilles.
• Sécurité basée sur l'appareil : toutes les clés privées sont stockées localement, pas dans le cloud.
• Prise en charge des portefeuilles bitcoin testnet.
• Accès synchrone sur toutes les principales plateformes mobiles et de bureau.
• Prise en charge de Payment protocol (BIP70-BIP73) : demandes de paiement facilement identifiables et paiements bitcoins sécurisés et vérifiables.
• Prise en charge de plus de 150 devises et dénomination d'unité en BTC ou en bits.
• Notifications e-mail pour les paiements et les transferts.
• Nom de portefeuille et couleurs de fond personnalisables.
• 4 langues prises en charge (EN, JP, FR, ES).
Copay est un logiciel gratuit et open source qui tourne sur des serveurs non-propriétaires, il n'y a donc pas besoin de compter sur une entreprise pour un support continuel. N'importe qui peut examiner ou contribuer au code source de Copay sur GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.1.0
--------------------------------
• Code QR avec montant personnalisable pour recevoir des paiements.
• Transfert de fonds entre portefeuilles.
• Notifications e-mail HTML.
• Frais de transactions personnalisables.
• Possibilité d'envoyer le montant maximal des fonds disponibles.
• Nouvelles règles de suppression des propositions de dépenses.
• Corrections de bugs pour les fonctionnalités hors ligne.
--------------------------------
v1.0.2
--------------------------------
Copay est sorti de sa phase beta ! Nous avons passé huit mois à tester Copay, et nous sommes prêts pour sa mise en production.
--------------------------------
v1.0.1
--------------------------------
Meilleur traitement des erreurs d'interruption réseau
Meilleure logique de rafraichissement après l'acceptation/le rejet de paiements
Mise à jour des traductions ES, JP et FR
Corrige le défilement dans certaines pop-ups
--------------------------------

52
appstore_ja Normal file
View file

@ -0,0 +1,52 @@
--------------------------------
Google Play store description
--------------------------------
ビットコインにおける高度なセキュリティーを手軽に扱えるオープンソースマルチシグネチャウォレットです。
Copayは個人のご利用はもちろんのこと、複数人によるウォレット管理の権限分散も簡単なウォレットソフトを通してご活用いただけます。
例えば:
友達との旅行や買い物のために透明性抜群の環境で貯蓄したい時
家族のお小遣いや日常の家計簿管理がしたい時
ビジネス・クラブ・団体の資金や財産管理を透明な管理分散がしたい時
下記の機能でセキュリティーも利便性も妥協しない最高のウォレットをCopayでご提供させていただきました
■ 複数のウォレットの作成・管理がアプリ内で管理可能
■ マルチシグネチャのウォレット分散管理でも個人ウォレットでも使いやすさ抜群
■ 送金の提案・承認・却下の流れが非常に直感的で分散管理が簡単
■ 階級的決定性ウォレット(HDウォレット)でアドレス生成とバックアップ管理をしているためバックアップは永久に各参加者1回ずつのみ
■ 端末に依存するセキュリティー、秘密鍵が全て端末に保管され、サーバに送ることは無い
■ ビットコインの開発テスト用ネットワークにも対応
■ メジャーなプラットフォーム全てに対応 (Windows, Mac, Linux, Android, iPhone, Windows Phone)
■ ペイメントプロトコルにも対応(BIP 70-73)、暗号通信と証明書を使ったマーチャントとの安全なペイメントの実現
■ 世界中の150個以上の通貨の表示に対応、自国通貨との為替レートを計算する必要なし。ビットコインの単位も BTC と bits にも対応
■ ペイメントや提案のメール通知も可能
■ ウォレットごとの背景色設定や通称設定も可能でカスタマイズ性抜群
■ 4ヶ国語に対応 (英日仏西)
Copayは永久無料でオープンソースのソフトです。サーバーもオープンソースなので、独自運用や法人の利用やソース流用は許可します。ソースをご覧の際に間違いなどが見つかった場合、Githubにてご報告・ソース修正のプルリクエストなどをお願いします。(https://github.com/bitpay/copay)
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.1.0
--------------------------------
■ QRコードによる指定額の受取要請。
■ ウォレット間の送金が円滑に。
■ メール通知のHTML化。
■ ビットコインネットワーク手数料が指定可能に。
■ ボタン一つで全残高を一気に送金が可能に。
■ 送金の提案の取下げ条件の変更。
■ オフライン機能のバグ修正。
--------------------------------
v1.0.2
--------------------------------
Copayがようやくベータ版を抜けてリリース版になりました 8ヶ月の時間を掛けて品質テストしてきたので、皆さんに安全に使っていただけるようになりました
--------------------------------
v1.0.1
--------------------------------
ネットワーク接続エラーの処理改善
送金の提案を承諾・却下した後の更新ロジックを改善
スペイン語、日本語、フランス語の翻訳を更新
特定のポップアップにおけるスクロール問題を改善
--------------------------------

41
appstore_pt Normal file
View file

@ -0,0 +1,41 @@
--------------------------------
Google Play store description
--------------------------------
Armazene bitcoin com seus próprios termos com uma carteira de multi-assinaturas, open source, do BitPay.
Usuários Copay podem manter fundos individualmente ou compartilhar finanças seguramente com outros usuários por meio de carteiras multi-assinadas, que previnem pagamentos não autorizados por meio de múltiplas aprovações. Algumas formas que a Copay pode ser usada com outros:
Para economizar para férias ou juntar compras com amigos
Para rastrear despesas familiares e To track family spending and descontos
Para gerenciar negócios, clube ou organizar saldos e despesas
Nós construímos as seguintes funcionalidades nesta versão da Copay para uma carteira bitcoin que não comprometa segurança ou acessibilidade:
Criação de múltiplas carteiras com gerenciamento no aplicativo
Segurança de multi-assinaturas intuitiva para carteiras pessoais ou compartilhadas
Fácil fluxo de propostas de gastos para carteiras compartilhadas e pagamentos agrupados
Geração de endereço Hierarchical deterministic (HD) e backups de carteiras
Segurança baseada em dispositivo: todas as chaves privadas são armazenadas localmente e não na nuvem
Suporte para carteiras de testes na Bitcoin testnet
Acesso síncrono entre todas as principais plataformas móveis e desktops
Suporte a protocolo de pagamento (BIP70-BIP73): solicitações de pagamento facilmente identificadas e pagamentos seguros em bitcoins verificáveis
Suporte para mais de 150 opções de moedas e denominação de unidades em BTC ou bits
Notificações por e-mail para pagamentos e transferências
Nomes e cores de fundo customizáveis para carteiras
5 idiomas suportados (EN, JP, FR, ES, PT-BR)
Copay é gratuito e um software livre rodando em servidores não-proprietários, que não precisa de nenhuma empresa para o suporte contínuo. Qualquer um pode revisar ou contribuir para o código-fonte da Copay no GitHub (https://github.com/bitpay/copay).
--------------------------------
Google Play store Release Notes: "What's new"
--------------------------------
v1.0.2
--------------------------------
Copay agora está fora do beta! Nós gastamos oito meses testando a Copay e estamos prontos para entrar em produção.
--------------------------------
v1.0.1
--------------------------------
Melhoria no tratamento de erros de interrupção de rede
Melhoria no lógica de renovação após aceitar/rejeitar pagamentos
Atualização das traduções para ES, JP e FR
Resolvida rolagem de certos popups
--------------------------------

View file

@ -1,67 +0,0 @@
# Warning
This NEEDS to be updated.
## Running in the Native Shell
Copay can be executed from within a "native" application shell, providing some
additional features such as native menus, notifications, tray integration, etc.
This is accomplished using [Atom Shell](https://github.com/atom/atom-shell).
To run and test Copay from within this context, first download the atom-shell
package to `shell/bin/{platform}` (ignored by git), by running:
```
npm run setup-shell
```
Once this script has completed, you can launch the shell-based Copay by running:
```
npm run shell
```
## Building Native Shell Binaries/Installers (OSX)
```
npm run dist
```
This script will download atom shell binaries and combine them with Copay sources
to build a DMG for osx-x64, an installer EXE for win32, and a .tar.gz for linux-x64.
It was developed to be run on OSX. The outputs are copied to the dist directory.
DMG is created with hdiutil
EXE is created with makensis (brew install makensis)
# Development
## Native Shell
To add features that enhance the native experience of Copay, first follow the
directions above under "Running in the Native Shell". It's important to ensure
that functionality within this context should either hook into existing features
or supplement the experience of those features. Copay should continue to operate
full-featured from within a modern web browser.
Shell functionality works by sending and receiving messages between the Copay
application and the shell wrapper. Native functionality should be handled mostly
from within `shell/lib/message-handler.js`, which receives messages conditionally
from the front-end Angular controllers.
Look at `js/shell.js` to see how we determine if Copay is running from within the
native shell context. If we are running within the shell, Copay has access to the
global variable `window.cshell`, which provides access to the messenger. For
instance, to Copay might want to use a native dialog alert in favor of a regular
one if running in this context. You would do this like so:
```js
if (window.cshell) {
window.cshell.send('alert', 'info', 'Please select a wallet.');
}
else {
window.alert('Please select a wallet.');
}
```

View file

@ -4,7 +4,7 @@
"copay",
"wallet",
"multisignature",
"bircore"
"bitcore"
],
"dependencies": {
"angular": "~1.3.13",
@ -15,8 +15,9 @@
"foundation": "zurb/bower-foundation#~5.5.1",
"foundation-icon-fonts": "*",
"ng-lodash": "~0.2.0",
"angular-moment": "~0.9.0",
"angular-bitcore-wallet-client": "^0.0.21",
"angular-moment": "~0.10.1",
"moment": "~2.10.3",
"angular-bitcore-wallet-client": "^0.0.26",
"angular-ui-router": "~0.2.13",
"qrcode-decoder-js": "*",
"fastclick": "*",

View file

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View file

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Before After
Before After

View file

@ -163,8 +163,8 @@ if [ $CURRENT_OS == "ANDROID" ]; then
mkdir -p $PROJECT/platforms/android/res/xml/
checkOK
cp android/AndroidManifest.xml $PROJECT/platforms/android/AndroidManifest.xml
checkOK
# cp android/AndroidManifest.xml $PROJECT/platforms/android/AndroidManifest.xml
# checkOK
cp android/project.properties $PROJECT/platforms/android/project.properties
checkOK

View file

@ -1,8 +1,8 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.bitpay.copay"
version="0.10.7"
android-versionCode="33"
ios-CFBundleVersion="0.10.7">
version="1.1.1"
android-versionCode="38"
ios-CFBundleVersion="1.1.1">
<name>Copay</name>
<description>
A secure bitcoin wallet for friends and companies.
@ -14,7 +14,6 @@
<access origin="*" />
<preference name="AndroidPersistentFileLocation" value="Internal" />
<preference name="iosPersistentFileLocation" value="Library" />
<preference name="DisallowOverscroll" value="true"/>
<preference name="HideKeyboardFormAccessoryBar" value="true"/>
<preference name="SplashScreen" value="copayscreen" />
@ -26,19 +25,4 @@
<preference name="BackupWebStorage" value="none"/>
<preference name="windows-target-version" value="8.1"/>
<preference name="Orientation" value="portrait" />
<feature name="App">
<param name="android-package" value="com.bitpay.copay" />
</feature>
<feature name="WebIntent">
<param name="android-package" value="com.borismus.webintent.WebIntent" />
</feature>
<feature name="BarcodeScanner">
<param name="android-package" value="com.phonegap.plugins.barcodescanner.BarcodeScanner" />
</feature>
<feature name="SplashScreen">
<param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" />
</feature>
<feature name="StatusBar">
<param name="android-package" onload="true" value="org.apache.cordova.statusbar.StatusBar" />
</feature>
</widget>

View file

@ -57,11 +57,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.10.7</string>
<string>1.1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.10.7</string>
<string>1.1.1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMainNibFile</key>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 177 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 225 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 515 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 479 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 524 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 561 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 177 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 561 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

After

Width:  |  Height:  |  Size: 1.9 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 427 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
<Identity Name="18C7659D.CopayWallet" Publisher="CN=F89609D1-EB3E-45FD-A58A-C2E3895FCE7B" Version="0.10.7.0" />
<Identity Name="18C7659D.CopayWallet" Publisher="CN=F89609D1-EB3E-45FD-A58A-C2E3895FCE7B" Version="1.1.1.0" />
<mp:PhoneIdentity PhoneProductId="5381aa50-9069-11e4-84cc-293caf9cbdc8" PhonePublisherId="F89609D1-EB3E-45FD-A58A-C2E3895FCE7B" />
<Properties>
<DisplayName>Copay Wallet</DisplayName>

BIN
cordova/wp/SplashScreenImage-original.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 409 KiB

Before After
Before After

BIN
cordova/wp/SplashScreenImage.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 174 KiB

Before After
Before After

View file

@ -2,7 +2,7 @@
"name": "copay",
"description": "A multisignature wallet",
"author": "BitPay",
"version": "0.10.7",
"version": "1.1.1",
"keywords": [
"wallet",
"copay",
@ -10,7 +10,23 @@
"bitcoin",
"bitcore"
],
"main": "app.js",
"main": "public/index.html",
"window": {
"toolbar": false,
"show": true,
"visible": true,
"resizable": false,
"frame": true,
"width": 400,
"height": 600,
"position": "center",
"fullscreen": false
},
"webkit": {
"page-cache": false,
"java": false,
"plugin": false
},
"id": "jid1-x7bV5evAaI1P9Q",
"homepage": "https://github.com/bitpay/copay",
"license": "MIT",
@ -43,8 +59,11 @@
"devDependencies": {
"angular": "^1.3.14",
"angular-mocks": "^1.3.14",
"grunt-contrib-compress": "^0.13.0",
"grunt-contrib-copy": "^0.8.0",
"grunt-karma": "^0.10.1",
"grunt-karma-coveralls": "^2.5.3",
"grunt-node-webkit-builder": "^1.0.2",
"karma": "^0.12.31",
"karma-cli": "0.0.4",
"karma-coverage": "^0.2.7",

1112
po/de.po Normal file

File diff suppressed because it is too large Load diff

852
po/es.po

File diff suppressed because it is too large Load diff

503
po/fr.po
View file

@ -13,30 +13,31 @@ msgstr ""
"X-Generator: Poedit 1.6.10\n"
#: public/views/modals/txp-details.html
msgid "* Only transactions created by yourself with no peer signatures can be removed"
msgstr "Seules les transactions créées par vous-même sans signatures de pairs peuvent être supprimées"
msgid "* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created."
msgstr " Une proposition de transaction peut être supprimée si 1) vous êtes le créateur, et aucun des autres copayers n'a signé, ou 2) 24 heures sont passées depuis la création de la proposition."
#: public/views/backup.html
msgid "* You can safely install your backup on other device and use your wallet from many devices at the same time."
msgid "* You can safely install your backup on another device and use your wallet from multiple devices at the same time."
msgstr "Vous pouvez installer en toute sécurité votre sauvegarde sur un autre appareil et utiliser votre portefeuille depuis plusieurs appareils en même temps."
#: public/views/splash/1.html
#: public/views/splash.html
msgid "A multisignature bitcoin wallet"
msgstr "Un portefeuille bitcoin multi-signatures"
#: src/js/services/notificationsService.js
msgid "A transaction was finally rejected"
msgstr "Une transaction a été finalement rejetée"
#: public/views/preferences.html
msgid "About Copay"
msgstr "À propos de Copay"
#: public/views/modals/txp-details.html
msgid "Accept"
msgstr "Accepter"
#: public/views/includes/sidebar.html
msgid "Add wallet"
msgstr "Ajouter un portefeuille"
#: public/views/paymentUri.html
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
msgid "Address"
msgstr "Adresse"
@ -45,17 +46,31 @@ msgstr "Adresse"
msgid "Advanced"
msgstr "Avancés"
#: public/views/disclaimer.html
msgid "Agree"
msgstr "Accepter"
#: public/views/preferencesAlias.html
msgid "Alias for <i>{{index.walletName}}</i>"
msgstr "Alias pour <i>{{index.walletName}}</i>"
#: public/views/splash.html
msgid "Already have a wallet?"
msgstr "Vous avez déjà un portefeuille ?"
#: public/views/preferences.html
msgid "Alternative Currency"
msgstr "Devise alternative"
#: public/views/paymentUri.html
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
#: public/views/modals/txp-details.html
msgid "Amount"
msgstr "Montant"
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Amount in"
msgstr "Montant en"
@ -72,6 +87,11 @@ msgstr "Êtes-vous certain de vouloir supprimer ce portefeuille ?"
msgid "Available Balance"
msgstr "Solde disponible"
#: public/views/create.html
#: public/views/join.html
msgid "BIP32 master extended private key"
msgstr "Clé privée étendue maîtresse BIP32"
#: public/views/includes/topbar.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
@ -98,6 +118,10 @@ msgstr "Options de sauvegarde"
msgid "Before receiving funds, it is highly recommended you backup your wallet keys."
msgstr "Avant de recevoir des fonds, il est fortement recommandé de sauvegarder les clés de votre portefeuille."
#: public/views/preferences.html
msgid "Bitcoin Network Fee Policy"
msgstr "Politique des frais de réseau Bitcoin"
#: public/views/paymentUri.html
msgid "Bitcoin URI is NOT valid!"
msgstr "L'URI Bitcoin n'est pas valide !"
@ -106,9 +130,17 @@ msgstr "L'URI Bitcoin n'est pas valide !"
msgid "Bitcoin address"
msgstr "Adresse Bitcoin"
#: public/views/preferencesFee.html
msgid "Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. The Emergency level should only be used when there is a network congestion."
msgstr "Les transactions Bitcoin peuvent inclure des frais collectés par les mineurs du réseau. Plus les frais sont élevés, et plus l'incitation à inclure une transaction dans un bloc est importante pour les mineurs. La priorité "Urgente" ne devrait être utilisée que lorsque le réseau présente une congestion."
#: public/views/modals/txp-details.html
msgid "Broadcast Transaction"
msgstr "Diffuser transaction"
msgid "Broadcast Payment"
msgstr "Diffuser le paiement"
#: src/js/controllers/walletHome.js
msgid "Broadcasting Payment"
msgstr "Diffusion du paiement"
#: src/js/controllers/walletHome.js
msgid "Broadcasting transaction"
@ -135,14 +167,28 @@ msgstr "Annuler"
msgid "Certified by"
msgstr "Certifié par"
#: public/views/preferencesAlias.html
msgid "Changing wallet alias only affects the local wallet name."
msgstr "La modification d'un alias de portefeuille affecte uniquement le nom du portefeuille local."
#: src/js/controllers/walletHome.js
msgid "Check you connection and try again"
msgstr "Vérifiez votre connexion internet et réessayez"
#: public/views/import.html
msgid "Choose backup file from your computer"
msgid "Choose a backup file from your computer"
msgstr "Choisissez un fichier de sauvegarde depuis votre ordinateur"
#: public/views/modals/wallets.html
msgid "Choose a wallet to send funds"
msgstr "Choisissez un portefeuille pour envoyer des fonds"
#: public/views/includes/topbar.html
#: public/views/modals/copayers.html
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
#: public/views/modals/scanner.html
#: public/views/modals/wallets.html
msgid "Close"
msgstr "Fermer"
@ -163,25 +209,37 @@ msgid "Copayers"
msgstr "Copayers"
#: public/views/backup.html
msgid "Copy backup in a safe place"
msgstr "Copiez la sauvegarde dans un endroit sûr"
msgid "Copy backup to a safe place"
msgstr "Copiez la sauvegarde vers un endroit sûr"
#: public/views/backup.html
msgid "Copy this text as it is in a safe place (notepad or email)"
msgstr "Copiez le texte dans un endroit sûr (bloc-notes ou e-mail)"
msgid "Copy this text as it is to a safe place (notepad or email)"
msgstr "Copiez ce texte présenté tel quel vers un endroit sûr (bloc-notes ou e-mail)"
#: public/views/backup.html
msgid "Copy to clipboard"
msgstr "Copier dans le presse-papier"
#: src/js/controllers/walletHome.js
msgid "Could not broadcast transaction. Please try again."
msgstr "Impossible de diffuser la transaction. Veuillez réessayer."
msgid "Could not accept payment. Check you connection and try again"
msgstr "Impossible d'accepter le paiement. Vérifiez votre connexion internet et réessayez"
#: src/js/controllers/walletHome.js
msgid "Could not broadcast payment. Check you connection and try again"
msgstr "Impossible de diffuser le paiement. Vérifiez votre connexion internet et réessayez"
#: src/js/controllers/walletHome.js
msgid "Could not connect wallet service. Check your Internet connexion and your wallet service configuration."
msgstr "Impossible de se connecter au service de portefeuille. Vérifiez votre connexion Internet et la configuration de votre service de portefeuille."
#: src/js/controllers/walletHome.js
msgid "Could not create address. Check you connection and try again"
msgstr "Impossible de créer l'adresse. Vérifiez votre connexion internet et réessayez"
#: src/js/controllers/walletHome.js
msgid "Could not create payment proposal"
msgstr "Impossible de créer la proposition de paiement"
#: src/js/services/profileService.js
msgid "Could not create using the specified extended private key"
msgstr "Impossible de créer en utilisant la clé privée étendue spécifiée"
@ -191,8 +249,8 @@ msgid "Could not decrypt file, check your password"
msgstr "Impossible de déchiffrer le fichier, vérifiez votre mot de passe"
#: src/js/controllers/walletHome.js
msgid "Could not delete transaction. Please try again."
msgstr "Impossible de supprimer la transaction. Veuillez réessayer."
msgid "Could not delete payment proposal. Check you connection and try again"
msgstr "Impossible de supprimer la proposition de paiement. Vérifiez votre connexion internet et réessayez"
#: src/js/controllers/walletHome.js
msgid "Could not fetch payment information"
@ -215,29 +273,29 @@ msgid "Could not join wallet:"
msgstr "Impossible de rejoindre le portefeuille"
#: src/js/controllers/walletHome.js
msgid "Could not reject transaction. Please try again."
msgstr "Impossible de rejeter la transaction. Veuillez réessayer."
msgid "Could not reject payment. Check you connection and try again"
msgstr "Impossible de rejeter le paiement. Vérifiez votre connexion internet réessayez"
#: src/js/controllers/walletHome.js
msgid "Could not send transaction. Please try again."
msgstr "Impossible d'envoyer la transaction. Veuillez réessayer."
#: src/js/controllers/walletHome.js
msgid "Could not sign transaction. Please try again."
msgstr "Impossible de signer la transaction. Veuillez réessayer."
msgid "Could not send payment"
msgstr "Impossible d'envoyer le paiement"
#: public/views/walletHome.html
msgid "Could not update Wallet"
msgstr "Impossible de mettre à jour le portefeuille"
#: public/views/create.html
#: public/views/walletHome.html
msgid "Create"
msgstr "Créer"
#: public/views/add.html
#: public/views/create.html
msgid "Create new wallet"
msgstr "Créer un nouveau portefeuille"
msgstr "Créer"
#: public/views/create.html
msgid "Create {{requiredCopayers}}-of-{{totalCopayers}} wallet"
msgstr "Créer un portefeuille {{requiredCopayers}}-sur-{{totalCopayers}}"
#: public/views/includes/sidebar.html
msgid "Create, join or import"
@ -247,8 +305,11 @@ msgstr "Créer, rejoindre ou importer"
msgid "Created by"
msgstr "Créée par"
#: public/views/splash.html
msgid "Creating Profile..."
msgstr "Création du profile..."
#: public/views/create.html
#: public/views/splash/1.html
msgid "Creating Wallet..."
msgstr "Création du portefeuille..."
@ -260,6 +321,10 @@ msgstr "Création de la transaction"
msgid "Date"
msgstr "Date"
#: public/views/modals/txp-details.html
msgid "Delete Payment Proposal"
msgstr "Supprimer la proposition de paiement"
#: public/views/preferencesAdvanced.html
msgid "Delete Wallet"
msgstr "Supprimer le portefeuille"
@ -273,8 +338,23 @@ msgid "Delete wallet"
msgstr "Supprimer le portefeuille"
#: src/js/controllers/walletHome.js
msgid "Deleting transaction"
msgstr "Suppression de la transaction"
msgid "Deleting payment"
msgstr "Suppression du paiement"
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Details"
msgstr "Détails"
#: src/js/controllers/index.js
msgid "Deutsch"
msgstr "Allemand"
#: public/views/preferences.html
msgid "Disabled"
msgstr "Désactivé"
#: public/views/backup.html
msgid "Download backup"
@ -284,6 +364,18 @@ msgstr "Télécharger la sauvegarde"
msgid "ENTER"
msgstr "ENTRER"
#: src/js/controllers/preferencesFee.js
msgid "Economy"
msgstr "Économique"
#: public/views/preferences.html
msgid "Email Notifications"
msgstr "Notifications e-mail"
#: src/js/controllers/preferencesFee.js
msgid "Emergency"
msgstr "Urgente"
#: public/views/preferences.html
msgid "Encrypt Private Key"
msgstr "Chiffrer la clé privée"
@ -323,7 +415,11 @@ msgstr "Impossible d'importer les portefeuilles"
#: public/views/create.html
msgid "Family vacation funds"
msgstr "Fonds pour les vacances familiales."
msgstr "Fonds pour les vacances familiales"
#: public/views/modals/txp-details.html
msgid "Fee"
msgstr "Frais"
#. Get information of payment if using Payment Protocol
#: src/js/controllers/walletHome.js
@ -338,22 +434,38 @@ msgstr "Français"
msgid "Funds received"
msgstr "Fonds reçus"
#: public/views/splash/1.html
#: public/views/splash.html
msgid "GET STARTED"
msgstr "COMMENCER"
#: public/views/modals/customized-amount.html
msgid "Generate QR Code"
msgstr "Générer un code QR"
#: public/views/walletHome.html
msgid "Generate new address"
msgstr "Générer une nouvelle adresse"
#: public/views/modals/wallets.html
msgid "Getting address for wallet {{selectedWalletName}} ..."
msgstr "Obtention d'une adresse pour le portefeuille {{selectedWalletName}} ..."
#: public/views/preferences.html
msgid "Global settings"
msgstr "Paramètres globaux"
#: public/views/disclaimer.html
msgid "Go back"
msgstr "Retour"
#: public/views/import.html
msgid "Have a Backup from Copay v0.9?"
msgstr "Vous avez une sauvegarde de Copay v0.9 ?"
#: public/views/create.html
#: public/views/join.html
msgid "Hide"
msgstr "Masquer"
msgid "Hide Advanced options"
msgstr "Masquer les options avancées"
#: src/js/controllers/index.js
msgid "History"
@ -363,10 +475,11 @@ msgstr "Historique"
msgid "Home"
msgstr "Accueil"
#: public/views/create.html
msgid "If not given, a random key will be generated"
msgstr "Si non spécifié, une clé aléatoire sera générée"
#: public/views/disclaimer.html
msgid "I affirm that I have read, understood, and agree with these terms."
msgstr "Je confirme que j'ai lu, compris et suis d'accord avec ces conditions."
#: public/views/create.html
#: public/views/join.html
msgid "If not given, a secure key will be generated"
msgstr "Si non spécifié, une clé sécurisée sera générée"
@ -376,20 +489,21 @@ msgid "Import"
msgstr "Importer"
#: public/views/import.html
#: public/views/splash.html
msgid "Import backup"
msgstr "Importer une sauvegarde"
#: public/views/add.html
msgid "Import from Copay Beta 0.9"
msgstr "Importer depuis Copay Beta 0.9"
msgstr "Importer la sauvegarde"
#: public/views/importLegacy.html
msgid "Import from the Cloud?"
msgstr "Importer depuis le Cloud ?"
#: public/views/import.html
msgid "Import here"
msgstr "Importer ici"
#: public/views/add.html
msgid "Import wallet"
msgstr "Importer un portefeuille"
msgstr "Importer"
#: public/views/import.html
msgid "Importing wallet..."
@ -399,11 +513,6 @@ msgstr "Importation du portefeuille..."
msgid "Importing..."
msgstr "Importation..."
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Information"
msgstr "Informations"
#: src/js/controllers/index.js
msgid "Japanese"
msgstr "Japonais"
@ -419,7 +528,7 @@ msgstr "Rejoindre"
#: public/views/add.html
msgid "Join shared wallet"
msgstr "Rejoindre un portefeuille partagé"
msgstr "Rejoindre"
#: public/views/join.html
msgid "Joining Wallet..."
@ -438,6 +547,7 @@ msgid "Make a payment to"
msgstr "Faire un paiement à"
#: public/views/create.html
#: public/views/join.html
msgid "Master extended private key"
msgstr "Clé privée étendue maîtresse"
@ -478,8 +588,8 @@ msgid "Network"
msgstr "Réseau"
#: src/js/services/notificationsService.js
msgid "New Transaction"
msgstr "Nouvelle transaction"
msgid "New Payment Proposal"
msgstr "Nouvelle proposition de paiement"
#: public/views/modals/confirmation.html
msgid "No"
@ -489,7 +599,12 @@ msgstr "Non"
msgid "No transactions yet"
msgstr "Aucune transaction"
#: public/views/walletHome.html
#: src/js/controllers/preferencesFee.js
msgid "Normal"
msgstr "Normale"
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Not valid"
msgstr "Non valide"
@ -503,6 +618,11 @@ msgstr "Note :"
msgid "OKAY"
msgstr "Ok"
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Participants"
msgstr "Participants"
#: public/views/import.html
#: public/views/importLegacy.html
msgid "Password"
@ -520,39 +640,88 @@ msgstr "Mot de passe nécessaire"
msgid "Passwords do not match"
msgstr "Le mot de passe ne correspond pas"
#: public/views/import.html
msgid "Paste backup plain text code"
msgstr "Coller le code texte de sauvegarde"
#: public/views/join.html
msgid "Paste invitation here"
msgstr "Collez l'invitation ici"
#: public/views/import.html
msgid "Paste the backup plain text code"
msgstr "Collez le code texte de sauvegarde"
#: public/views/modals/paypro.html
msgid "Pay To"
msgstr "Payer à"
#: public/views/modals/tx-status.html
msgid "Payment Accepted"
msgstr "Paiement accepté"
#: public/views/modals/txp-details.html
msgid "Payment Proposal"
msgstr "Proposition de paiement"
#: public/views/modals/tx-status.html
msgid "Payment Proposal Created"
msgstr "Proposition de paiement créée"
#: src/js/services/notificationsService.js
msgid "Payment Proposal Rejected"
msgstr "Proposition de paiement rejetée"
#: src/js/services/notificationsService.js
msgid "Payment Proposal Rejected by Copayer"
msgstr "Proposition de paiement rejetée par les Copayer"
#: src/js/services/notificationsService.js
msgid "Payment Proposal Signed by Copayer"
msgstr "Proposition de paiement signée par les Copayers"
#: public/views/walletHome.html
msgid "Payment Proposals"
msgstr "Propositions de paiement"
#: src/js/controllers/walletHome.js
msgid "Payment Protocol not supported on Chrome App"
msgstr "Le protocole de paiement n'est pas supporté sur l'application Chrome"
#: public/views/modals/tx-status.html
msgid "Payment Rejected"
msgstr "Paiement rejeté"
#: public/views/modals/tx-status.html
#: src/js/services/notificationsService.js
msgid "Payment Sent"
msgstr "Paiement envoyé"
#: public/views/modals/txp-details.html
msgid "Payment accepted..."
msgstr "Paiement accepté..."
#: public/views/modals/txp-details.html
msgid "Payment details"
msgstr "Détails de paiement"
msgstr "Détails du paiement"
#: public/views/modals/txp-details.html
msgid "Payment finally rejected"
msgstr "Paiement finalement rejeté"
#: public/views/modals/paypro.html
msgid "Payment protocol request"
msgstr "Demande de protocole de paiement"
msgid "Payment request"
msgstr "Demande de paiement"
#: public/views/modals/txp-details.html
msgid "Payment sent!"
msgstr "Paiement envoyé !"
#: public/views/walletHome.html
msgid "Payment to"
msgstr "Paiement à"
#: public/views/preferencesDeleteWallet.html
msgid "Permanently delete this wallet. THIS ACTION CANNONT BE REVERSED"
msgid "Permanently delete this wallet. THIS ACTION CANNOT BE REVERSED"
msgstr "Supprimer définitivement ce portefeuille. CETTE ACTION NE PEUT PAS ÊTRE ANNULÉE"
#: public/views/walletHome.html
#: public/views/create.html
msgid "Personal Wallet"
msgstr "Portefeuille personnel"
@ -565,10 +734,26 @@ msgstr "Veuillez saisir les champs requis"
msgid "Please, select your backup file"
msgstr "Veuillez sélectionner votre fichier de sauvegarde"
#: src/js/controllers/index.js
msgid "Portuguese"
msgstr "Portugais"
#: public/views/walletHome.html
msgid "Preferences"
msgstr "Préférences"
#: src/js/controllers/preferencesFee.js
msgid "Priority"
msgstr "Prioritaire"
#: public/views/modals/customized-amount.html
msgid "QR Code"
msgstr "Code QR"
#: public/views/modals/scanner.html
msgid "QR-Scanner"
msgstr "QR-Scanner"
#: src/js/controllers/index.js
msgid "Receive"
msgstr "Recevoir"
@ -594,28 +779,29 @@ msgid "Reject"
msgstr "Rejeter"
#: src/js/controllers/walletHome.js
msgid "Rejecting transaction"
msgstr ""
msgid "Rejecting payment"
msgstr "Rejet du paiement"
#: public/views/preferencesAbout.html
msgid "Release Information"
msgstr "Libérer l'information"
#: public/views/modals/txp-details.html
msgid "Remove transaction"
msgstr "Supprimer la transaction"
msgstr "Informations de version"
#: public/views/backup.html
#: public/views/includes/password.html
msgid "Repeat password"
msgstr "Répétez le mot de passe"
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Request a specific amount"
msgstr "Demander un montant précis"
#: public/views/import.html
#: public/views/join.html
msgid "Required"
msgstr "Requis"
#: public/views/splash/1.html
#: public/views/splash.html
msgid "Retrying..."
msgstr "Nouvelle tentative"
@ -627,9 +813,15 @@ msgstr "DEFINIR"
msgid "SKIP BACKUP"
msgstr "IGNORER"
#: public/views/preferencesAlias.html
#: public/views/preferencesBwsUrl.html
#: public/views/preferencesEmail.html
msgid "Save"
msgstr "Sauvegarder"
msgstr "Enregistrer"
#: public/views/preferencesEmail.html
msgid "Saving preferences..."
msgstr "Enregistrement des préférences..."
#: src/js/services/notificationsService.js
msgid "Scan Finished"
@ -660,7 +852,7 @@ msgid "Select a wallet"
msgstr "Sélectionner un portefeuille"
#: public/views/create.html
msgid "Select required signatures"
msgid "Select required number of signatures"
msgstr "Sélectionnez le nombre de signatures requises"
#: public/views/create.html
@ -673,6 +865,10 @@ msgstr "Sélectionnez le nombre total de copayers"
msgid "Send"
msgstr "Envoyer"
#: public/views/walletHome.html
msgid "Send All"
msgstr "Tout envoyer"
#: public/views/backup.html
#: public/views/preferencesLogs.html
msgid "Send by email"
@ -698,6 +894,10 @@ msgstr "Définissez un mot de passe pour votre sauvegarde"
msgid "Set up a password"
msgstr "Définir un mot de passe"
#: public/views/preferencesEmail.html
msgid "Setting up email notifications could weaken your privacy, if the wallet service provider is compromised. Information available to an attacker would include your wallet addresses and its balance, but no more."
msgstr "Définir des notifications e-mail peut affaiblir votre vie privée si le fournisseur du service de portefeuille est compromis. Les informations disponibles à un attaquant incluent les adresses de votre portefeuille et leurs soldes, mais rien de plus."
#: public/views/walletHome.html
msgid "Share address"
msgstr "Partager l'adresse"
@ -707,26 +907,25 @@ msgid "Share invitation"
msgstr "Partager l'invitation"
#: public/views/copayers.html
msgid "Share this secret with your copayers"
msgstr "Partagez ce secret avec vos copayers"
msgid "Share this invitation with your copayers"
msgstr "Partagez cette invitation avec vos copayers"
#: public/views/walletHome.html
msgid "Share this with anyone to have them send you payments. To protect your privacy, new addresses are generated automatically once you use them."
msgstr "Partagez ceci avec quiconque pour recevoir des paiements. Pour protéger votre anonymat, de nouvelles adresses sont générées automatiquement une fois que vous les utilisez."
msgid "Share this wallet address to receive payments. To protect your privacy, new addresses are generated automatically once you use them."
msgstr "Partagez cette adresse de portefeuille pour recevoir des paiements. Pour protéger votre anonymat, de nouvelles adresses sont générées automatiquement une fois que vous les utilisez."
#: public/views/create.html
#: public/views/create.html
msgid "Shared Wallet"
msgstr "Portefeuille partagé"
#: public/views/create.html
#: public/views/join.html
msgid "Show"
msgstr "Montrer"
msgid "Show Advanced options"
msgstr "Montrer les options avancées"
#: public/views/modals/txp-details.html
msgid "Sign"
msgstr "Signer"
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Signatures"
msgstr "Signatures"
#: src/js/controllers/walletHome.js
msgid "Signing payment"
msgstr "Signature du paiement"
#: src/js/controllers/walletHome.js
msgid "Signing transaction"
@ -750,34 +949,58 @@ msgstr "Succès"
msgid "Tap to retry"
msgstr "Tapez pour réessayer"
#: public/views/disclaimer.html
#: public/views/preferencesAbout.html
msgid "Terms of Use"
msgstr "Conditions d'utilisation"
#: public/views/create.html
msgid "Testnet"
msgstr "Testnet"
#: src/js/controllers/walletHome.js
msgid "The payment was created but could not be completed. Please try again from home screen"
msgstr "Le paiement a été créé mais n'a pas pu être achevé. Veuillez réessayer depuis l'écran d'accueil"
#: src/js/controllers/walletHome.js
msgid "The payment was created but could not be signed. Please try again from home screen."
msgstr "Le paiement a été créé mais n'a pas pu être signé. Veuillez réessayer depuis l'écran d'accueil"
#: public/views/modals/txp-details.html
msgid "The transaction was removed by creator"
msgstr "La transaction a été supprimée par le créateur"
msgid "The payment was removed by creator"
msgstr "Le paiement a été supprimé par le créateur"
#: public/views/backup.html
msgid "The private key for this wallet is encrypted. Exporting a backup will keep the private key encrypted in the backup archive."
msgstr "La clé privée pour ce portefeuille est chiffrée. Exporter une sauvegarde conservera le chiffrement de la clé dans l'archive de sauvegarde."
#: public/views/disclaimer.html
msgid "The software you are about to use functions as a free, open source, and multi-signature digital wallet. The software does not constitute an account where BitPay or other third parties serve as financial intermediaries or custodians of your bitcoin. While the software has undergone beta testing and continues to be improved by feedback from the open-source user and developer community, we cannot guarantee that there will be no bugs in the software. You acknowledge that your use of this software is at your own discretion and in compliance with all applicable laws. You are responsible for safekeeping your passwords, private key pairs, PINs and any other codes you use to access the software. IF YOU LOSE ACCESS TO YOUR COPAY WALLET OR YOUR ENCRYPTED PRIVATE KEYS AND YOU HAVE NOT SEPARATELY STORED A BACKUP OF YOUR WALLET AND CORRESPONDING PASSWORD, YOU ACKNOWLEDGE AND AGREE THAT ANY BITCOIN YOU HAVE ASSOCIATED WITH THAT COPAY WALLET WILL BECOME INACCESSIBLE. All transaction requests are irreversible. The authors of the software, employees and affiliates of Bitpay, copyright holders, and BitPay, Inc. cannot retrieve your private keys or passwords if you lose or forget them and cannot guarantee transaction confirmation as they do not have control over the Bitcoin network. To the fullest extent permitted by law, this software is provided “as is” and no representations or warranties can be made of any kind, express or implied, including but not limited to the warranties of merchantability, fitness or a particular purpose and noninfringement. You assume any and all risks associated with the use of the software. In no event shall the authors of the software, employees and affiliates of Bitpay, copyright holders, or BitPay, Inc. be held liable for any claim, damages or other liability, whether in an action of contract, tort, or otherwise, arising from, out of or in connection with the software. We reserve the right to modify this disclaimer from time to time."
msgstr "Le logiciel que vous êtes sur le point d'utiliser fonctionne comme un portefeuille numérique gratuit, open source et multi-signatures.\nLe logiciel ne constitue pas un compte où BitPay, ou des tiers, agissent comme des intermédiaires financiers ou dépositaires de vos bitcoins.\nBien que le logiciel ait subi des tests bêta et continue d'être amélioré par les commentaires d'utilisateurs et de développeurs de la communauté open source, nous ne pouvons pas garantir qu'il n'y aura plus de bugs dans le logiciel.\nVous reconnaissez que votre utilisation de ce logiciel est à votre propre discrétion et est en conformité avec toutes les lois applicables.\nVous êtes responsable de la sauvegarde de vos mots de passe, paires de clés privées, codes PIN et autres codes que vous utilisez pour accéder au logiciel.\nSI VOUS PERDEZ L'ACCÈS À VOTRE PORTEFEUILLE COPAY OU À VOS CLÉS PRIVÉES CHIFFRÉES ET QUE VOUS N'AVEZ PAS ENTREPOSÉ SÉPARÉMENT UNE SAUVEGARDE DE VOTRE PORTEFEUILLE ET LES MOTS DE PASSE CORRESPONDANT, VOUS RECONNAISSEZ ET ACCEPTEZ QUE LES BITCOINS QUE VOUS AVEZ ASSOCIÉ À CE PORTEFEUILLE COPAY DEVIENNENT INACCESSIBLES.\nToutes les transactions sont irréversibles.\nLes auteurs de ce logiciel, employés et sociétés affiliés à BitPay, détenteurs de droits d'auteur, et BitPay, Inc. ne peuvent pas récupérer vos clés privées ou mots de passe si vous les perdez et ne peuvent pas garantir la confirmation des transactions étant donné qu'ils n'ont pas de contrôle sur le réseau Bitcoin.\nDans toute la mesure permise par la loi, ce logiciel est fourni “tel quel” et aucune représentation ou garantie ne peut être faite de toute nature, expresse ou implicite, y compris, mais sans s'y limiter, les garanties de qualité marchande, la conformité ou un usage particulier et absent de contrefaçon.\nVous assumez tous les risques associés à l'utilisation du logiciel.\nEn aucun cas les auteurs des logiciels, employés et sociétés affiliés de Bitpay, détenteurs de droits d'auteur, ou BitPay, Inc. ne peuvent être tenus responsables de toute réclamation, dommages ou autre responsabilité, que ce soit dans une action contractuelle, délictuelle ou autre, découlant ou en étant en connexion avec le logiciel.\nNous nous réservons le droit de modifier cette clause de temps à autre."
#: src/js/controllers/copayers.js
#: src/js/controllers/preferencesDelete.js
msgid "The wallet \"{{walletName}}\" was deleted"
msgstr "Le portefeuille \"{{walletName}}\" a été supprimé"
#: public/views/paymentUri.html
msgid "There are no wallets to make this payment"
msgstr "Il n'y a pas de portefeuilles pour faire ce paiement"
#: src/js/controllers/import.js
msgid "There is an error in the form"
msgstr "Il y a une erreur dans la forme"
#: public/views/backup.html
msgid "This wallet have its private key encrypted. Exporting a backup will keep the private key encrypted on the backup."
msgstr "Ce portefeuille a sa clé privée chiffrée. Exporter une sauvegarde gardera la clé privée chiffrée lors de la sauvegarde."
#: public/views/walletHome.html
msgid "This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information."
msgstr "Ce portefeuille n'est pas enregistré dans le Bitcore Wallet Service (BWS).Vous pouvez le recréer depuis l'information locale."
#: public/views/modals/txp-details.html
msgid "Time"
msgstr "Temps"
msgstr "Heure"
#: public/views/walletHome.html
#: public/views/includes/transaction.html
#: public/views/modals/paypro.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "To"
@ -791,54 +1014,6 @@ msgstr "Solde verrouillé total"
msgid "Transaction"
msgstr "Transaction"
#: src/js/services/notificationsService.js
msgid "Transaction Rejected"
msgstr "Transaction rejetée"
#: src/js/services/notificationsService.js
msgid "Transaction Sent"
msgstr "Transaction envoyée"
#: src/js/services/notificationsService.js
msgid "Transaction Signed"
msgstr "Transaction signée"
#: public/views/modals/txp-details.html
msgid "Transaction accepted..."
msgstr "Transaction acceptée..."
#: src/js/services/txStatus.js
msgid "Transaction broadcasted"
msgstr "Transaction diffusée"
#: public/views/modals/txp-details.html
msgid "Transaction finally rejected"
msgstr "Transaction finalement rejetée"
#: src/js/controllers/walletHome.js
msgid "Transaction not broadcasted. Please try again."
msgstr "Transaction non diffusée. Veuillez réessayer."
#: public/views/modals/txp-details.html
msgid "Transaction proposal"
msgstr "Proposition de transaction"
#: src/js/services/txStatus.js
msgid "Transaction proposal created"
msgstr "Proposition de transaction créée"
#: src/js/services/txStatus.js
msgid "Transaction proposal signed"
msgstr "Proposition de transaction signée"
#: public/views/modals/txp-details.html
msgid "Transaction sent!"
msgstr "Transaction envoyée !"
#: src/js/services/txStatus.js
msgid "Transaction was rejected"
msgstr "La transaction a été rejetée"
#: src/js/controllers/walletHome.js
msgid "Unable to send transaction proposal"
msgstr "Impossible d'envoyer la proposition de transaction"
@ -864,10 +1039,6 @@ msgstr "Non-approuvé"
msgid "Updating Wallet..."
msgstr "Mise à jour du portefeuille..."
#: public/views/create.html
msgid "Use test network"
msgstr "Utiliser le réseau de test"
#: public/views/preferencesAbout.html
msgid "Version"
msgstr "Version"
@ -884,7 +1055,7 @@ msgstr "ATTENTION : Sauvegarde nécessaire"
msgid "WARNING: Wallet not registered"
msgstr "ATTENTION : Portefeuille non enregistré"
#: public/views/splash/1.html
#: public/views/splash.html
msgid "WELCOME TO COPAY"
msgstr "BIENVENUE SUR COPAY"
@ -896,6 +1067,10 @@ msgstr "Attente des copayers"
msgid "Waiting..."
msgstr "Attente..."
#: public/views/preferences.html
msgid "Wallet Alias"
msgstr "Alias de portefeuille"
#: src/js/services/profileService.js
msgid "Wallet Already Imported:"
msgstr "Portefeuille déjà importé :"
@ -937,7 +1112,7 @@ msgid "Yes"
msgstr "Oui"
#: public/views/walletHome.html
msgid "You do not have any wallet"
msgid "You do not have a wallet"
msgstr "Vous n'avez aucun portefeuille"
#: public/views/backup.html
@ -962,17 +1137,15 @@ msgstr "Votre mot de passe de profil"
msgid "Your wallet has been imported correctly"
msgstr "Votre portefeuille a été correctement importé"
#: public/views/create.html
#: public/views/join.html
msgid "advanced options"
msgstr "les options avancées"
#: public/views/preferencesEmail.html
msgid "email for wallet notifications"
msgstr "e-mail pour les notifications de portefeuille"
#: public/views/walletHome.html
msgid "in pending transactions"
msgstr "dans les transactions en attente"
msgid "locked by pending payments"
msgstr "verrouillés par les paiements en attente"
#: public/views/copayers.html
#: public/views/create.html
#: public/views/walletHome.html
#: public/views/includes/sidebar.html
msgid "of"
@ -982,17 +1155,21 @@ msgstr "de"
msgid "optional"
msgstr "optionnel"
#: public/views/preferences.html
msgid "settings"
msgstr "paramètres"
#: public/views/walletHome.html
msgid "too long!"
msgstr "trop long !"
#: public/views/create.html
msgid "wallet"
msgstr "portefeuille"
#: public/views/preferencesFee.html
msgid "{{fee.value}} bits per kB"
msgstr "{{fee.value}} bits par kB"
#: public/views/preferences.html
msgid "{{index.walletName}} settings"
msgstr "{{index.walletName}} paramètres"
#: src/js/controllers/walletHome.js
msgid "{{fee}} will be discounted for bitcoin networking fees"
msgstr "{{fee}} seront déduits pour les frais de réseau Bitcoin"
#: src/js/controllers/importLegacy.js
msgid "{{len}} wallets imported. Funds scanning in progress. Hold on to see updated balance"

677
po/ja.po

File diff suppressed because it is too large Load diff

1103
po/pt.po Normal file

File diff suppressed because it is too large Load diff

View file

@ -5,30 +5,31 @@ msgstr ""
"Project-Id-Version: \n"
#: public/views/modals/txp-details.html
msgid "* Only transactions created by yourself with no peer signatures can be removed"
msgid "* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created."
msgstr ""
#: public/views/backup.html
msgid "* You can safely install your backup on other device and use your wallet from many devices at the same time."
msgid "* You can safely install your backup on another device and use your wallet from multiple devices at the same time."
msgstr ""
#: public/views/splash/1.html
#: public/views/splash.html
msgid "A multisignature bitcoin wallet"
msgstr ""
#: src/js/services/notificationsService.js
msgid "A transaction was finally rejected"
msgstr ""
#: public/views/preferences.html
msgid "About Copay"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Accept"
msgstr ""
#: public/views/includes/sidebar.html
msgid "Add wallet"
msgstr ""
#: public/views/paymentUri.html
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
msgid "Address"
msgstr ""
@ -37,17 +38,31 @@ msgstr ""
msgid "Advanced"
msgstr ""
#: public/views/disclaimer.html
msgid "Agree"
msgstr ""
#: public/views/preferencesAlias.html
msgid "Alias for <i>{{index.walletName}}</i>"
msgstr ""
#: public/views/splash.html
msgid "Already have a wallet?"
msgstr ""
#: public/views/preferences.html
msgid "Alternative Currency"
msgstr ""
#: public/views/paymentUri.html
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
#: public/views/modals/txp-details.html
msgid "Amount"
msgstr ""
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Amount in"
msgstr ""
@ -64,6 +79,11 @@ msgstr ""
msgid "Available Balance"
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "BIP32 master extended private key"
msgstr ""
#: public/views/includes/topbar.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
@ -90,6 +110,10 @@ msgstr ""
msgid "Before receiving funds, it is highly recommended you backup your wallet keys."
msgstr ""
#: public/views/preferences.html
msgid "Bitcoin Network Fee Policy"
msgstr ""
#: public/views/paymentUri.html
msgid "Bitcoin URI is NOT valid!"
msgstr ""
@ -98,8 +122,16 @@ msgstr ""
msgid "Bitcoin address"
msgstr ""
#: public/views/preferencesFee.html
msgid "Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. The Emergency level should only be used when there is a network congestion."
msgstr ""
#: public/views/modals/txp-details.html
msgid "Broadcast Transaction"
msgid "Broadcast Payment"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Broadcasting Payment"
msgstr ""
#: src/js/controllers/walletHome.js
@ -127,14 +159,28 @@ msgstr ""
msgid "Certified by"
msgstr ""
#: public/views/preferencesAlias.html
msgid "Changing wallet alias only affects the local wallet name."
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Check you connection and try again"
msgstr ""
#: public/views/import.html
msgid "Choose backup file from your computer"
msgid "Choose a backup file from your computer"
msgstr ""
#: public/views/modals/wallets.html
msgid "Choose a wallet to send funds"
msgstr ""
#: public/views/includes/topbar.html
#: public/views/modals/copayers.html
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
#: public/views/modals/scanner.html
#: public/views/modals/wallets.html
msgid "Close"
msgstr ""
@ -155,11 +201,11 @@ msgid "Copayers"
msgstr ""
#: public/views/backup.html
msgid "Copy backup in a safe place"
msgid "Copy backup to a safe place"
msgstr ""
#: public/views/backup.html
msgid "Copy this text as it is in a safe place (notepad or email)"
msgid "Copy this text as it is to a safe place (notepad or email)"
msgstr ""
#: public/views/backup.html
@ -167,13 +213,25 @@ msgid "Copy to clipboard"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not broadcast transaction. Please try again."
msgid "Could not accept payment. Check you connection and try again"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not broadcast payment. Check you connection and try again"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not connect wallet service. Check your Internet connexion and your wallet service configuration."
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not create address. Check you connection and try again"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not create payment proposal"
msgstr ""
#: src/js/services/profileService.js
msgid "Could not create using the specified extended private key"
msgstr ""
@ -183,7 +241,7 @@ msgid "Could not decrypt file, check your password"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not delete transaction. Please try again."
msgid "Could not delete payment proposal. Check you connection and try again"
msgstr ""
#: src/js/controllers/walletHome.js
@ -207,30 +265,30 @@ msgid "Could not join wallet:"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not reject transaction. Please try again."
msgid "Could not reject payment. Check you connection and try again"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not send transaction. Please try again."
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Could not sign transaction. Please try again."
msgid "Could not send payment"
msgstr ""
#: public/views/walletHome.html
msgid "Could not update Wallet"
msgstr ""
#: public/views/create.html
#: public/views/walletHome.html
msgid "Create"
msgstr ""
#: public/views/add.html
#: public/views/create.html
msgid "Create new wallet"
msgstr ""
#: public/views/create.html
msgid "Create {{requiredCopayers}}-of-{{totalCopayers}} wallet"
msgstr ""
#: public/views/includes/sidebar.html
msgid "Create, join or import"
msgstr ""
@ -239,8 +297,11 @@ msgstr ""
msgid "Created by"
msgstr ""
#: public/views/splash.html
msgid "Creating Profile..."
msgstr ""
#: public/views/create.html
#: public/views/splash/1.html
msgid "Creating Wallet..."
msgstr ""
@ -252,6 +313,10 @@ msgstr ""
msgid "Date"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Delete Payment Proposal"
msgstr ""
#: public/views/preferencesAdvanced.html
msgid "Delete Wallet"
msgstr ""
@ -265,7 +330,22 @@ msgid "Delete wallet"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Deleting transaction"
msgid "Deleting payment"
msgstr ""
#: public/views/modals/customized-amount.html
#: public/views/modals/paypro.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Details"
msgstr ""
#: src/js/controllers/index.js
msgid "Deutsch"
msgstr ""
#: public/views/preferences.html
msgid "Disabled"
msgstr ""
#: public/views/backup.html
@ -276,6 +356,18 @@ msgstr ""
msgid "ENTER"
msgstr ""
#: src/js/controllers/preferencesFee.js
msgid "Economy"
msgstr ""
#: public/views/preferences.html
msgid "Email Notifications"
msgstr ""
#: src/js/controllers/preferencesFee.js
msgid "Emergency"
msgstr ""
#: public/views/preferences.html
msgid "Encrypt Private Key"
msgstr ""
@ -317,6 +409,10 @@ msgstr ""
msgid "Family vacation funds"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Fee"
msgstr ""
#. Get information of payment if using Payment Protocol
#: src/js/controllers/walletHome.js
msgid "Fetching Payment Information"
@ -330,21 +426,37 @@ msgstr ""
msgid "Funds received"
msgstr ""
#: public/views/splash/1.html
#: public/views/splash.html
msgid "GET STARTED"
msgstr ""
#: public/views/modals/customized-amount.html
msgid "Generate QR Code"
msgstr ""
#: public/views/walletHome.html
msgid "Generate new address"
msgstr ""
#: public/views/modals/wallets.html
msgid "Getting address for wallet {{selectedWalletName}} ..."
msgstr ""
#: public/views/preferences.html
msgid "Global settings"
msgstr ""
#: public/views/disclaimer.html
msgid "Go back"
msgstr ""
#: public/views/import.html
msgid "Have a Backup from Copay v0.9?"
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "Hide"
msgid "Hide Advanced options"
msgstr ""
#: src/js/controllers/index.js
@ -355,10 +467,11 @@ msgstr ""
msgid "Home"
msgstr ""
#: public/views/create.html
msgid "If not given, a random key will be generated"
#: public/views/disclaimer.html
msgid "I affirm that I have read, understood, and agree with these terms."
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "If not given, a secure key will be generated"
msgstr ""
@ -368,17 +481,18 @@ msgid "Import"
msgstr ""
#: public/views/import.html
#: public/views/splash.html
msgid "Import backup"
msgstr ""
#: public/views/add.html
msgid "Import from Copay Beta 0.9"
msgstr ""
#: public/views/importLegacy.html
msgid "Import from the Cloud?"
msgstr ""
#: public/views/import.html
msgid "Import here"
msgstr ""
#: public/views/add.html
msgid "Import wallet"
msgstr ""
@ -391,11 +505,6 @@ msgstr ""
msgid "Importing..."
msgstr ""
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Information"
msgstr ""
#: src/js/controllers/index.js
msgid "Japanese"
msgstr ""
@ -430,6 +539,7 @@ msgid "Make a payment to"
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "Master extended private key"
msgstr ""
@ -441,6 +551,9 @@ msgid "Me"
msgstr ""
#: public/views/modals/paypro.html
msgid "Memo"
msgstr ""
#: public/views/modals/tx-details.html
msgid "Merchant message"
msgstr ""
@ -470,7 +583,7 @@ msgid "Network"
msgstr ""
#: src/js/services/notificationsService.js
msgid "New Transaction"
msgid "New Payment Proposal"
msgstr ""
#: public/views/modals/confirmation.html
@ -481,7 +594,12 @@ msgstr ""
msgid "No transactions yet"
msgstr ""
#: src/js/controllers/preferencesFee.js
msgid "Normal"
msgstr ""
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Not valid"
msgstr ""
@ -495,6 +613,11 @@ msgstr ""
msgid "OKAY"
msgstr ""
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Participants"
msgstr ""
#: public/views/import.html
#: public/views/importLegacy.html
msgid "Password"
@ -512,28 +635,77 @@ msgstr ""
msgid "Passwords do not match"
msgstr ""
#: public/views/import.html
msgid "Paste backup plain text code"
msgstr ""
#: public/views/join.html
msgid "Paste invitation here"
msgstr ""
#: public/views/import.html
msgid "Paste the backup plain text code"
msgstr ""
#: public/views/modals/paypro.html
msgid "Pay To"
msgstr ""
#: public/views/modals/tx-status.html
msgid "Payment Accepted"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Payment Proposal"
msgstr ""
#: public/views/modals/tx-status.html
msgid "Payment Proposal Created"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Payment Proposal Rejected"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Payment Proposal Rejected by Copayer"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Payment Proposal Signed by Copayer"
msgstr ""
#: public/views/walletHome.html
msgid "Payment Proposals"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Payment Protocol not supported on Chrome App"
msgstr ""
#: public/views/modals/tx-status.html
msgid "Payment Rejected"
msgstr ""
#: public/views/modals/tx-status.html
#: src/js/services/notificationsService.js
msgid "Payment Sent"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Payment accepted..."
msgstr ""
#: public/views/modals/txp-details.html
msgid "Payment details"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Payment finally rejected"
msgstr ""
#: public/views/modals/paypro.html
msgid "Payment protocol request"
msgid "Payment request"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Payment sent!"
msgstr ""
#: public/views/walletHome.html
@ -541,10 +713,10 @@ msgid "Payment to"
msgstr ""
#: public/views/preferencesDeleteWallet.html
msgid "Permanently delete this wallet. THIS ACTION CANNONT BE REVERSED"
msgid "Permanently delete this wallet. THIS ACTION CANNOT BE REVERSED"
msgstr ""
#: public/views/walletHome.html
#: public/views/create.html
msgid "Personal Wallet"
msgstr ""
@ -557,10 +729,26 @@ msgstr ""
msgid "Please, select your backup file"
msgstr ""
#: src/js/controllers/index.js
msgid "Portuguese"
msgstr ""
#: public/views/walletHome.html
msgid "Preferences"
msgstr ""
#: src/js/controllers/preferencesFee.js
msgid "Priority"
msgstr ""
#: public/views/modals/customized-amount.html
msgid "QR Code"
msgstr ""
#: public/views/modals/scanner.html
msgid "QR-Scanner"
msgstr ""
#: src/js/controllers/index.js
msgid "Receive"
msgstr ""
@ -586,28 +774,29 @@ msgid "Reject"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Rejecting transaction"
msgid "Rejecting payment"
msgstr ""
#: public/views/preferencesAbout.html
msgid "Release Information"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Remove transaction"
msgstr ""
#: public/views/backup.html
#: public/views/includes/password.html
msgid "Repeat password"
msgstr ""
#: public/views/walletHome.html
#: public/views/modals/customized-amount.html
msgid "Request a specific amount"
msgstr ""
#: public/views/import.html
#: public/views/join.html
msgid "Required"
msgstr ""
#: public/views/splash/1.html
#: public/views/splash.html
msgid "Retrying..."
msgstr ""
@ -619,10 +808,16 @@ msgstr ""
msgid "SKIP BACKUP"
msgstr ""
#: public/views/preferencesAlias.html
#: public/views/preferencesBwsUrl.html
#: public/views/preferencesEmail.html
msgid "Save"
msgstr ""
#: public/views/preferencesEmail.html
msgid "Saving preferences..."
msgstr ""
#: src/js/services/notificationsService.js
msgid "Scan Finished"
msgstr ""
@ -652,7 +847,7 @@ msgid "Select a wallet"
msgstr ""
#: public/views/create.html
msgid "Select required signatures"
msgid "Select required number of signatures"
msgstr ""
#: public/views/create.html
@ -665,6 +860,10 @@ msgstr ""
msgid "Send"
msgstr ""
#: public/views/walletHome.html
msgid "Send All"
msgstr ""
#: public/views/backup.html
#: public/views/preferencesLogs.html
msgid "Send by email"
@ -690,6 +889,10 @@ msgstr ""
msgid "Set up a password"
msgstr ""
#: public/views/preferencesEmail.html
msgid "Setting up email notifications could weaken your privacy, if the wallet service provider is compromised. Information available to an attacker would include your wallet addresses and its balance, but no more."
msgstr ""
#: public/views/walletHome.html
msgid "Share address"
msgstr ""
@ -703,21 +906,20 @@ msgid "Share this invitation with your copayers"
msgstr ""
#: public/views/walletHome.html
msgid "Share this with anyone to have them send you payments. To protect your privacy, new addresses are generated automatically once you use them."
msgid "Share this wallet address to receive payments. To protect your privacy, new addresses are generated automatically once you use them."
msgstr ""
#: public/views/create.html
msgid "Shared Wallet"
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "Show"
msgid "Show Advanced options"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Sign"
msgstr ""
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "Signatures"
#: src/js/controllers/walletHome.js
msgid "Signing payment"
msgstr ""
#: src/js/controllers/walletHome.js
@ -728,10 +930,6 @@ msgstr ""
msgid "Spanish"
msgstr ""
#: public/views/walletHome.html
msgid "Spend proposals"
msgstr ""
#: src/js/controllers/copayers.js
#: src/js/controllers/import.js
#: src/js/controllers/preferencesDelete.js
@ -742,8 +940,37 @@ msgstr ""
msgid "Tap to retry"
msgstr ""
#: public/views/disclaimer.html
#: public/views/preferencesAbout.html
msgid "Terms of Use"
msgstr ""
#: public/views/create.html
msgid "Testnet"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "The payment was created but could not be completed. Please try again from home screen"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "The payment was created but could not be signed. Please try again from home screen."
msgstr ""
#: public/views/modals/txp-details.html
msgid "The transaction was removed by creator"
msgid "The payment was removed by creator"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "The payment was signed but could not be broadcasted. Please try again from home screen."
msgstr ""
#: public/views/backup.html
msgid "The private key for this wallet is encrypted. Exporting a backup will keep the private key encrypted in the backup archive."
msgstr ""
#: public/views/disclaimer.html
msgid "The software you are about to use functions as a free, open source, and multi-signature digital wallet. The software does not constitute an account where BitPay or other third parties serve as financial intermediaries or custodians of your bitcoin. While the software has undergone beta testing and continues to be improved by feedback from the open-source user and developer community, we cannot guarantee that there will be no bugs in the software. You acknowledge that your use of this software is at your own discretion and in compliance with all applicable laws. You are responsible for safekeeping your passwords, private key pairs, PINs and any other codes you use to access the software. IF YOU LOSE ACCESS TO YOUR COPAY WALLET OR YOUR ENCRYPTED PRIVATE KEYS AND YOU HAVE NOT SEPARATELY STORED A BACKUP OF YOUR WALLET AND CORRESPONDING PASSWORD, YOU ACKNOWLEDGE AND AGREE THAT ANY BITCOIN YOU HAVE ASSOCIATED WITH THAT COPAY WALLET WILL BECOME INACCESSIBLE. All transaction requests are irreversible. The authors of the software, employees and affiliates of Bitpay, copyright holders, and BitPay, Inc. cannot retrieve your private keys or passwords if you lose or forget them and cannot guarantee transaction confirmation as they do not have control over the Bitcoin network. To the fullest extent permitted by law, this software is provided “as is” and no representations or warranties can be made of any kind, express or implied, including but not limited to the warranties of merchantability, fitness or a particular purpose and noninfringement. You assume any and all risks associated with the use of the software. In no event shall the authors of the software, employees and affiliates of Bitpay, copyright holders, or BitPay, Inc. be held liable for any claim, damages or other liability, whether in an action of contract, tort, or otherwise, arising from, out of or in connection with the software. We reserve the right to modify this disclaimer from time to time."
msgstr ""
#: src/js/controllers/copayers.js
@ -751,12 +978,12 @@ msgstr ""
msgid "The wallet \"{{walletName}}\" was deleted"
msgstr ""
#: src/js/controllers/import.js
msgid "There is an error in the form"
#: public/views/paymentUri.html
msgid "There are no wallets to make this payment"
msgstr ""
#: public/views/backup.html
msgid "This wallet have its private key encrypted. Exporting a backup will keep the private key encrypted on the backup."
#: src/js/controllers/import.js
msgid "There is an error in the form"
msgstr ""
#: public/views/walletHome.html
@ -769,7 +996,6 @@ msgstr ""
#: public/views/walletHome.html
#: public/views/includes/transaction.html
#: public/views/modals/paypro.html
#: public/views/modals/tx-details.html
#: public/views/modals/txp-details.html
msgid "To"
@ -783,54 +1009,6 @@ msgstr ""
msgid "Transaction"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Transaction Rejected"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Transaction Sent"
msgstr ""
#: src/js/services/notificationsService.js
msgid "Transaction Signed"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Transaction accepted..."
msgstr ""
#: src/js/services/txStatus.js
msgid "Transaction broadcasted"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Transaction finally rejected"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Transaction not broadcasted. Please try again."
msgstr ""
#: public/views/modals/txp-details.html
msgid "Transaction proposal"
msgstr ""
#: src/js/services/txStatus.js
msgid "Transaction proposal created"
msgstr ""
#: src/js/services/txStatus.js
msgid "Transaction proposal signed"
msgstr ""
#: public/views/modals/txp-details.html
msgid "Transaction sent!"
msgstr ""
#: src/js/services/txStatus.js
msgid "Transaction was rejected"
msgstr ""
#: src/js/controllers/walletHome.js
msgid "Unable to send transaction proposal"
msgstr ""
@ -856,10 +1034,6 @@ msgstr ""
msgid "Updating Wallet..."
msgstr ""
#: public/views/create.html
msgid "Use test network"
msgstr ""
#: public/views/preferencesAbout.html
msgid "Version"
msgstr ""
@ -876,7 +1050,7 @@ msgstr ""
msgid "WARNING: Wallet not registered"
msgstr ""
#: public/views/splash/1.html
#: public/views/splash.html
msgid "WELCOME TO COPAY"
msgstr ""
@ -888,6 +1062,10 @@ msgstr ""
msgid "Waiting..."
msgstr ""
#: public/views/preferences.html
msgid "Wallet Alias"
msgstr ""
#: src/js/services/profileService.js
msgid "Wallet Already Imported:"
msgstr ""
@ -929,7 +1107,7 @@ msgid "Yes"
msgstr ""
#: public/views/walletHome.html
msgid "You do not have any wallet"
msgid "You do not have a wallet"
msgstr ""
#: public/views/backup.html
@ -954,17 +1132,15 @@ msgstr ""
msgid "Your wallet has been imported correctly"
msgstr ""
#: public/views/create.html
#: public/views/join.html
msgid "advanced options"
#: public/views/preferencesEmail.html
msgid "email for wallet notifications"
msgstr ""
#: public/views/walletHome.html
msgid "in pending transactions"
msgid "locked by pending payments"
msgstr ""
#: public/views/copayers.html
#: public/views/create.html
#: public/views/walletHome.html
#: public/views/includes/sidebar.html
msgid "of"
@ -974,16 +1150,20 @@ msgstr ""
msgid "optional"
msgstr ""
#: public/views/preferences.html
msgid "settings"
msgstr ""
#: public/views/walletHome.html
msgid "too long!"
msgstr ""
#: public/views/create.html
msgid "wallet"
#: public/views/preferencesFee.html
msgid "{{fee.value}} bits per kB"
msgstr ""
#: public/views/preferences.html
msgid "{{index.walletName}} settings"
#: src/js/controllers/walletHome.js
msgid "{{fee}} will be discounted for bitcoin networking fees"
msgstr ""
#: src/js/controllers/importLegacy.js

BIN
public/img/icons/icon.icns Normal file

Binary file not shown.

BIN
public/img/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="msapplication-tap-highlight" content="no">
<link rel="stylesheet" type="text/css" href="css/foundation.css">
<link rel="stylesheet" type="text/css" href="icons/foundation-icons.css">

View file

@ -1,7 +1,7 @@
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Add Wallet'; closeToHome = true; noColor = true">
ng-init="titleSection='Add wallet'; closeToHome = true; noColor = true">
</div>

View file

@ -1,5 +1,5 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Backup'; goBackToState = 'preferences'">
</div>
@ -17,36 +17,36 @@
<label for="password" translate>Set up a Password for your backup</label>
<div class="input">
<input type="password" class="form-control"
<input type="password" class="form-control"
placeholder="{{'Your backup password'|translate}}"
name="password" ng-model="backup.password">
</div>
<label for="password" translate>Repeat password</label>
<div class="input">
<input type="password" class="form-control"
<input type="password" class="form-control"
placeholder="{{'Repeat password'|translate}}"
name="password" ng-model="backup.repeatpassword">
</div>
<button class="black radius expand" ng-click="backup.downloadWalletBackup()"
ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
<button class="black round expand" ng-click="backup.downloadWalletBackup()"
ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-show="!backup.isSafari && !backup.isCordova"><i class="fi-download"></i>
<span translate>Download backup</span></button>
<button class="black radius expand" ng-click="backup.viewWalletBackup()"
<button class="black round expand" ng-click="backup.viewWalletBackup()"
ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-style="{'background-color':index.backgroundColor}"
ng-show="backup.isSafari && !backup.isCordova"><i class="fi-eye"></i>
<span translate>View backup</span></button>
<div ng-show="backup.isCordova">
<h4 translate>Backup options</h4>
<button class="black radius expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
<button class="black round expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-click="backup.copyWalletBackup()"><i class="fi-clipboard-pencil"></i>
<span translate>Copy to clipboard</span></button>
<button class="black radius expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
<button class="black round expand" ng-disabled="(!backup.password || backup.password != backup.repeatpassword)"
ng-style="{'background-color':index.backgroundColor}"
ng-click="backup.sendWalletBackup()"><i class="fi-mail"></i>
<span translate>Send by email</span></button>
</div>
@ -59,7 +59,7 @@
<textarea rows="12">{{backup.backupWalletPlainText}}</textarea>
</div>
<div class="size-12 text-gray text-right">
<i class="icon-compose"></i>
<i class="icon-compose"></i>
<span translate>Copy this text as it is to a safe place (notepad or email)</span>
</div>
</div>

View file

@ -1,14 +1,14 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Copayers'">
ng-init="">
</div>
<div class="content p20v" ng-controller="copayersController as copayers" ng-init="copayers.init()">
<div ng-show="!index.notAuthorized">
<div class="row m10t text-center">
<div class="large-12 columns">
<h1 translate>Share this invitation with your copayers</h1>
<h1 translate>Share this invitation with your copayers</h1>
</div>
</div>
@ -21,9 +21,9 @@
</div>
</div>
<div class="text-center m10t" ng-if="index.isCordova">
<span class="button outline dark-gray tiny"
<span class="button outline round dark-gray tiny"
ng-click="copayers.shareSecret(index.walletSecret)">
<i class="fi-share"></i>
<i class="fi-share"></i>
<span translate>Share invitation</span>
</span>
</div>
@ -31,7 +31,7 @@
<span translate>Waiting for copayers</span>
<span class="text-gray right">
[ {{index.m}} <span translate>of</span> {{index.n}} ]
</span>
</span>
</h4>
<div class="p10 line-b" ng-include="'views/includes/copayers.html'"></div>
<div ng-if="!index.isComplete" class="p10 line-b m20b">
@ -48,7 +48,7 @@
<h1 translate>Wallet incomplete and broken</h1>
<h4 translate>Delete it and create a new one</h4>
</div>
<button class="small warning expand" ng-click="copayers.deleteWallet()">
<button class="small warning expand round" ng-click="copayers.deleteWallet()">
<i class="fi-trash"></i> <span translate>Cancel</span>
</button>
</div>
@ -58,4 +58,3 @@
<div class="extra-margin-bottom"></div>

View file

@ -1,12 +1,12 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Create new wallet'; goBackToState = 'add'; noColor = true">
</div>
<div class="content p20v" ng-controller="createController as create">
<div class="content p20v" ng-controller="createController as create" ng-init="create.setTotalCopayers(1)">
<div class="onGoingProcess" ng-show="create.loading">
<div class="onGoingProcess-content" ng-style="{'background-color':'#222'}">
@ -21,6 +21,20 @@
</div>
</div>
<div class="create-tab small-only-text-center" ng-hide="create.hideTabs">
<div class="row">
<div class="tab-container small-6 medium-3 large-2">
<a href
ng-class="{'selected': totalCopayers == 1}"
ng-click="create.setTotalCopayers(1)" translate>Personal Wallet</a>
</div>
<div class="tab-container small-6 medium-3 large-2">
<a href
ng-class="{'selected': totalCopayers != 1}"
ng-click="create.setTotalCopayers(3)" translate>Shared Wallet</a>
</div>
</div>
</div>
<form name="setupForm" ng-submit="create.create(setupForm)" novalidate>
<div class="row">
@ -35,7 +49,7 @@
<div class="large-12 columns" ng-hide="create.hideWalletName">
<label><span translate>Wallet name</span>
<div class="input">
<input type="text" placeholder="{{'Family vacation funds'|translate}}" class="form-control" name="walletName" ng-model="walletName" ng-required="true" ng-blur="create.formFocus(false)">
<input type="text" placeholder="{{'Family vacation funds'|translate}}" class="form-control" name="walletName" ng-model="walletName" ng-required="true" ng-focus="create.formFocus('wallet-name')" ng-blur="create.formFocus(false)">
</div>
</label>
</div>
@ -47,10 +61,12 @@
</label>
</div>
</div>
<div class="row">
<div class="row" ng-show="totalCopayers != 1">
<div class="large-6 medium-6 columns">
<label><span translate>Select total number of copayers</span>
<select class="m10t" ng-model="totalCopayers" ng-options="totalCopayers as totalCopayers for totalCopayers in create.TCValues">
<select class="m10t" ng-model="totalCopayers"
ng-options="totalCopayers as totalCopayers for totalCopayers in create.TCValues"
ng-change="create.setTotalCopayers(totalCopayers)">
</select>
</label>
</div>
@ -65,9 +81,8 @@
<div class="m10t oh" ng-init="hideAdv=true">
<a class="button outline light-gray expand tiny" ng-click="hideAdv=!hideAdv">
<i class="fi-widget m3r"></i>
<span translate ng-hide="!hideAdv">Show</span>
<span translate ng-hide="hideAdv">Hide</span>
<span translate>Advanced options</span>
<span translate ng-hide="!hideAdv">Show Advanced options</span>
<span translate ng-hide="hideAdv">Hide Advanced options</span>
<i ng-if="hideAdv" class="icon-arrow-down4"></i>
<i ng-if="!hideAdv" class="icon-arrow-up4"></i>
</a>
@ -75,23 +90,27 @@
<div ng-hide="hideAdv" class="row">
<div class="large-12 columns">
<label for="network-name" class="line-b oh">
<span translate>Use test network</span>
<span translate>Testnet</span>
<switch id="network-name" name="isTestnet" ng-model="isTestnet" class="green right m5t m10b"></switch>
</label>
<label for="ext-master" class="m10t">
<span translate>Master extended private key</span>
<small translate>If not given, a random key will be generated</small>
<input id="ext-master"
type="text"
placeholder="BIP32 master extended private key"
<small translate>If not given, a secure key will be generated</small>
<input id="ext-master"
type="text"
placeholder="{{'BIP32 master extended private key'|translate}}"
name="privateKey" ng-model="privateKey">
</div>
</div>
<button type="submit" class="button black expand radius m0" ng-disabled="setupForm.$invalid">
<span translate>Create</span>
{{requiredCopayers}}-<span translate>of</span>-{{totalCopayers}} <span translate>wallet</span>
<button type="submit" class="button round black expand m0" ng-show="totalCopayers != 1" ng-disabled="setupForm.$invalid || create.loading">
<span translate>Create {{requiredCopayers}}-of-{{totalCopayers}} wallet</span>
</button>
<button type="submit" class="button round black expand m0" ng-show="totalCopayers == 1" ng-disabled="setupForm.$invalid || create.loading">
<span translate>Create new wallet</span>
</button>
</div>
</div>

View file

@ -0,0 +1,29 @@
<div
ng-if="agreed && index.hasProfile"
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Terms of Use'; goBackToState = 'about'; noColor = true">
</div>
<div class="content p20b" ng-class="{'disclaimer':!index.hasProfile}">
<h4 class="title m0" ng-show="!index.hasProfile">
<span translate>Terms of Use</span>
<img class="right" src="img/logo.svg" alt="Copay" width="40">
</h4>
<div class="p20h m10t">
<p class="enable_text_select text-light size-14 text-gray" translate>
The software you are about to use functions as a free, open source, and multi-signature digital wallet. The software does not constitute an account where BitPay or other third parties serve as financial intermediaries or custodians of your bitcoin. While the software has undergone beta testing and continues to be improved by feedback from the open-source user and developer community, we cannot guarantee that there will be no bugs in the software. You acknowledge that your use of this software is at your own discretion and in compliance with all applicable laws. You are responsible for safekeeping your passwords, private key pairs, PINs and any other codes you use to access the software. IF YOU LOSE ACCESS TO YOUR COPAY WALLET OR YOUR ENCRYPTED PRIVATE KEYS AND YOU HAVE NOT SEPARATELY STORED A BACKUP OF YOUR WALLET AND CORRESPONDING PASSWORD, YOU ACKNOWLEDGE AND AGREE THAT ANY BITCOIN YOU HAVE ASSOCIATED WITH THAT COPAY WALLET WILL BECOME INACCESSIBLE. All transaction requests are irreversible. The authors of the software, employees and affiliates of Bitpay, copyright holders, and BitPay, Inc. cannot retrieve your private keys or passwords if you lose or forget them and cannot guarantee transaction confirmation as they do not have control over the Bitcoin network. To the fullest extent permitted by law, this software is provided “as is” and no representations or warranties can be made of any kind, express or implied, including but not limited to the warranties of merchantability, fitness or a particular purpose and noninfringement. You assume any and all risks associated with the use of the software. In no event shall the authors of the software, employees and affiliates of Bitpay, copyright holders, or BitPay, Inc. be held liable for any claim, damages or other liability, whether in an action of contract, tort, or otherwise, arising from, out of or in connection with the software. We reserve the right to modify this disclaimer from time to time.
</p>
<div ng-show="!agreed">
<p translate>I affirm that I have read, understood, and agree with these terms.</p>
<button class="black round expand" ng-click="agree()">
<span translate> Agree </span>
</button>
</div>
<button ng-show="agreed && !index.hasProfile" class="round" ng-click="agree()" translate>Go back</button>
</div>
<div class="extra-margin-bottom"></div>
</div>

View file

@ -1,5 +1,5 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Import wallet'; goBackToState = 'add'; noColor = true">
</div>
@ -19,7 +19,7 @@
</div>
<div class="row" ng-show="!import.loading">
<div class="row">
<div class="large-12 columns">
<form name="importForm" ng-submit="import.import(importForm)" novalidate>
<div class="box-notification" ng-show="import.error">
@ -49,20 +49,18 @@
<input type="password" class="form-control" placeholder="{{'Your backup password'|translate}}"
name="password" ng-model="import.password">
</div>
<button translate type="submit" class="button radius expand black"
ng-disabled="importForm.$invalid || !import.password">
<button translate type="submit" class="button round expand black"
ng-disabled="importForm.$invalid || !import.password || import.loading">
Import backup
</button>
</form>
<div class="text-center text-gray p20v" ng-click="$root.go('importLegacy')">
<p class="text-gray m5b size-14" translate> Have a Backup from Copay v0.9?</p>
<button class=" outline dark-gray tiny" translate> Import here
<i class="icon-arrow-right3 size-14"></i>
</button>
</div>
<div class="text-center text-gray p20v" ng-click="$root.go('importLegacy')">
<p class="text-gray m5b size-14" translate> Have a Backup from Copay v0.9?</p>
<button class=" outline dark-gray tiny round"> <span translate>Import here</span>
<i class="icon-arrow-right3 size-14"></i>
</button>
</div>
</div>
</div>

View file

@ -1,29 +1,27 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Import legacy wallet'; goBackToState = 'import'; noColor = true">
</div>
<div class="content p20v" ng-controller="importLegacyController as importLegacy">
<div class="row m20t">
<div class="large-12 columns">
<div ng-show="importLegacy.importing">
<h1 class="m20b animated infinite flash" translate>Importing...</h1>
<ul>
<li ng-repeat="m in importLegacy.messages">
<span ng-style="{'opacity':m.opacity}">{{m.message|translate}}</span>
</ul>
</div>
<div class="large-12 columns">
<div ng-show="importLegacy.importing">
<h1 class="m20b animated infinite flash" translate>Importing...</h1>
<ul>
<li ng-repeat="m in importLegacy.messages">
<span ng-style="{'opacity':m.opacity}">{{m.message|translate}}</span>
</ul>
</div>
<div class="box-notification" ng-show="importLegacy.error">
<span class="text-warning size-14">
{{importLegacy.error|translate}}
</span>
</div>
<div class="box-notification" ng-show="importLegacy.error">
<span class="text-warning size-14">
{{importLegacy.error|translate}}
</span>
</div>
<div ng-show="!importLegacy.importing">
<div ng-show="!importLegacy.importing">
<form name="importForm" ng-submit="importLegacy.import(importForm)" novalidate>
<label for="fromCloud" class="line-b oh m20b">
@ -49,31 +47,20 @@
name="server" ng-model="importLegacy.server" required>
</label>
<button translate type="submit"
class="button black radius expand m0"
ng-disabled="deviceForm.$invalid">
Import
<button translate type="submit"
class="button black round expand m0"
ng-disabled="importForm.$invalid">
Import
</button>
</form>
<form name="importLegacyForm" ng-submit="importLegacy.import(importLegacyForm)" novalidate>
<div class="box-notification" ng-show="error">
<span class="text-warning size-14">
{{error|translate}}
</span>
</div>
</form>
<div class="text-center p20v">
<a class="m20t tiny button outline light-gray " ng-click="$root.openExternalLink('https://github.com/bitpay/copay/releases/tag/v0.10.0')" translate>
Learn more about Wallet Migration
</a>
</div>
<div class="text-center p20v">
<a class="m20t tiny button outline round light-gray " ng-click="$root.openExternalLink('https://github.com/bitpay/copay/releases/tag/v0.10.0')" translate>
Learn more about Wallet Migration
</a>
</div>
</div>
</div>
</div>
</div>

View file

@ -2,7 +2,7 @@
<div class="passModalMask">
</div>
<div ng-controller="passwordController as pass" class="passModal"
<div ng-controller="passwordController as pass" class="passModal"
ng-class="{'animated bounceInDown':index.askPassword}"
>
<div class="columns m20t">
@ -21,13 +21,13 @@
</div>
<div class="row">
<div class="small-6 columns">
<button class="radius small-6 columns outline dark-gray expand" ng-click="pass.close(index.askPassword.callback)" translate>
<button class="round small-6 columns outline dark-gray expand" ng-click="pass.close(index.askPassword.callback)" translate>
CANCEL
</button>
</div>
<div class="small-6 columns">
<button class="radius expand" ng-click="pass.set(index.askPassword.isSetup, index.askPassword.callback)" ng-disabled="!pass.password"
<button class="round expand" ng-click="pass.set(index.askPassword.isSetup, index.askPassword.callback)" ng-disabled="!pass.password"
ng-style="{'background-color':index.backgroundColor}">
<span translate ng-if="index.askPassword.isSetup" translate>SET</span>
<span translate ng-if="!index.askPassword.isSetup" translate>ENTER</span>

View file

@ -8,15 +8,15 @@
ng-repeat="item in sidebar.wallets track by $index"
ng-class="{'selected': item.id == index.walletId}"
class="nav-item">
<a ng-click="sidebar.switchWallet(item.id)">
<a ng-click="sidebar.switchWallet(item.id, index.walletId)" class="oh">
<div class="avatar-wallet"
ng-style="{'background-color':item.color}">{{(item.name || item.id) | limitTo: 1}}</div>
<div class="ellipsis name-wallet">{{item.name || item.id}}</div>
<div class="size-12">{{item.m}} <span translate>of</span> {{item.n}}</div>
<div class="name-wallet" ng-class="{'m8t':item.n == 1}">{{item.name || item.id}}</div>
<div class="size-12" ng-show="item.n > 1">{{item.m}} <span translate>of</span> {{item.n}}</div>
</a>
</li>
<li>
<a ng-click="$root.go('add')">
<a ng-click="$root.go('add')" class="oh">
<i class="icon-arrow-right3 size-18 right m10t"></i>
<i class="fi-plus size-24 db left m20r m5t"></i>
<div class="tu text-bold">

View file

@ -3,7 +3,7 @@
<a id="hamburger" class="p10" ng-show="!goBackToState && !closeToHome && !index.noFocusedWallet"
ng-click="index.openMenu()"><i class="fi-list size-24"></i>
</a>
<a ng-show="goBackToState"
<a ng-show="goBackToState"
ng-click="$root.go(goBackToState); goBackToState = null"><i class="icon-arrow-left3 icon-back"></i>
<span class="text-back">{{'Back'|translate}}</span>
</a>
@ -20,8 +20,8 @@
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" ng-style="{'color': noColor ? '#7A8C9E' : index.backgroundColor}">
{{(titleSection|translate) || index.walletName}}
<h1 class="title ellipsis" ng-style="{'color': noColor ? '#4A90E2' : index.backgroundColor}">
{{(titleSection|translate) || (index.alias || index.walletName)}}
</h1>
</section>
</nav>

View file

@ -1,5 +1,5 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Join shared wallet'; goBackToState = 'add'; noColor = true">
</div>
@ -66,24 +66,24 @@
<a class="button outline light-gray tiny expand" ng-click="join.hideAdv=!join.hideAdv">
<i class="fi-widget m3r"></i>
<span translate ng-show="!join.hideAdv">Show</span>
<span translate ng-show="join.hideAdv">Hide</span>
<span translate>Advanced options</span>
<span translate ng-show="!join.hideAdv">Show Advanced options</span>
<span translate ng-show="join.hideAdv">Hide Advanced options</span>
<i ng-show="!join.hideAdv" class="icon-arrow-down4"></i>
<i ng-show="join.hideAdv" class="icon-arrow-up4"></i>
</a>
<div ng-show="join.hideAdv" class="row">
<div class="large-12 columns">
<label for="ext-master">Master extended private key
<label for="ext-master">{{'Master extended private key'|translate}}
<small translate>If not given, a secure key will be generated</small>
<input id="ext-master"
type="text"
placeholder="BIP32 master extended private key"
placeholder="{{'BIP32 master extended private key'|translate}}"
name="privateKey" ng-model="privateKey">
</label>
</div>
</div>
<button translate type="submit" class="button expand black m0 radius" ng-disabled="joinForm.$invalid">Join</button>
<button translate type="submit" class="button expand black m0 round"
ng-disabled="joinForm.$invalid || join.loading">Join</button>
</form>
</div>
</div>

View file

@ -2,13 +2,13 @@
<div class="row">
<h1 class="text-center m20b">{{title|translate}}</h1>
<div class="large-6 medium-6 small-6 columns">
<button class="button light-gray expand outline radius" ng-disabled="loading"
<button class="button light-gray expand outline round" ng-disabled="loading"
ng-click="cancel()">
<i class="fi-x"></i> <span class="tu" translate>No</span>
</button>
</div>
<div class="large-6 medium-6 small-6 columns">
<button class="warning expand radius" ng-disabled="loading" ng-click="ok()">
<button class="button warning expand round" ng-disabled="loading" ng-click="ok()">
<i class="fi-trash"></i> <span translate>Yes</span>
</button>
</div>

View file

@ -12,14 +12,17 @@
</section>
</nav>
<ul class="no-bullet p60t">
<li class="line-b p10" ng-repeat="copayer in copayers">
<span class="size-12" ng-show="copayer.id == copayerId">
<i class="icon-contact size-24 m10r"></i> {{copayer.name}} ({{'Me'|translate}}) <i class="fi-check m5r right"></i>
</span>
<span class="size-12 text-gray" ng-show="copayer.id != copayerId">
<i class="icon-contact size-24 m10r"></i> {{copayer.name}}<i class="fi-check m5r right"></i>
</span>
</li>
</ul>
<div class="modal-content fix-modals-touch">
<ul class="no-bullet">
<li class="line-b p10" ng-repeat="copayer in copayers">
<span class="size-12" ng-show="copayer.id == copayerId">
<i class="icon-contact size-24 m10r"></i> {{copayer.name}} ({{'Me'|translate}}) <i class="fi-check m5 right"></i>
</span>
<span class="size-12 text-gray" ng-show="copayer.id != copayerId">
<i class="icon-contact size-24 m10r"></i> {{copayer.name}}<i class="fi-check m5 right"></i>
</span>
</li>
</ul>
<div class="extra-margin-bottom"></div>
</div>

View file

@ -0,0 +1,80 @@
<nav class="tab-bar">
<section class="left-small">
<a ng-click="cancel()" class="p10">
<span class="text-close" translate>Close</span>
</a>
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" ng-style="{'color':color}" translate>
Request a specific amount
</h1>
</section>
</nav>
<div class="modal-content fix-modals-touch">
<div class="m20b" ng-show="customizedAmountBtc">
<h4 class="title m0" translate>QR Code</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 oh text-center">
<qrcode size="220" data="bitcoin:{{addr + '?amount=' + customizedAmountBtc}}"></qrcode>
</li>
</ul>
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 oh">
<span class="text-gray" translate>Address</span>:
<span class="right">
<span class="text-gray enable_text_select">{{addr}}</span>
</span>
</li>
<li class="line-b p10 oh">
<span class="text-gray" translate>Amount</span>:
<span class="right">
{{customizedAmountUnit}}
<span class="label gray radius">{{customizedAlternativeUnit}}</span>
</span>
</li>
</ul>
</div>
<div ng-show="!customizedAmountBtc" class="row m20t">
<div class="large-12 large-centered columns">
<form name="amountForm" ng-submit="submitForm(amountForm)" novalidate>
<div class="right" ng-hide="amountForm.amount.$pristine && !amountForm.amount.$modelValue ">
<span class="has-error right size-12" ng-if="amountForm.amount.$invalid">
<i class="icon-close-circle size-14"></i>
<span clas="vm" translate>Not valid</span>
</span>
<small class="text-primary right" ng-if="!amountForm.amount.$invalid">
<i class="icon-checkmark-circle size-14"></i>
</small>
</div>
<div ng-if="!showAlternative">
<label for="amount">
<span translate>Amount</span>
</label>
<div class="input">
<input type="number" id="amount" name="amount" ng-attr-placeholder="{{'Amount'|translate}}"
ng-model="_customAmount" valid-amount required autocomplete="off">
<input type="number" id="alternative" name="alternative" ng-model="_customAlternative" style="display:none">
<a class="postfix" ng-click="toggleAlternative()">{{unitName}}</a>
</div>
</div>
<div ng-if="showAlternative">
<label for="alternative"><span translate>Amount in</span> {{ alternativeName }}
</label>
<div class="input">
<input type="number" id="alternative" name="alternative" ng-attr-placeholder="{{'Amount'|translate}}"
ng-model="_customAlternative" requiredautocomplete="off" required>
<input type="number" id="amount" name="amount" ng-model="_customAmount" style="display:none">
<a class="postfix" ng-click="toggleAlternative()"> {{ alternativeIsoCode }}</a>
</div>
</div>
<button type="submit" class="button black round expand" ng-disabled="amountForm.$invalid" ng-style="{'background-color':color}" translate>
Generate QR Code
</button>
</form>
</div>
</div>
<div class="extra-margin-bottom"></div>
</div>

View file

@ -6,54 +6,48 @@
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" ng-style="{'color':color}" translate>
Payment protocol request
Payment request
</h1>
</section>
</nav>
<div class="row p60t">
<div class="large-12 columns">
<div class="text-center">
<div class="size-48">
{{unitTotal}} {{unitName}}
</div>
<div class="size-18 m5t text-gray">
{{ alternative }} {{ alternativeIsoCode }}
</div>
<div class="modal-content fix-modals-touch">
<div class="header-modal text-center">
<div class="size-42">
{{unitTotal}} {{unitName}}
</div>
<div class="line-b m10v"></div>
<div class="ellipsis m10v">
<i translate>To</i>: {{paypro.domain}}
</div>
<div ng-if="paypro.toAddress" class="m10v lh140">
<i translate>Address</i>:
<span class="text-gray">
{{paypro.toAddress}}
</span>
</div>
<div class="m10v">
<i translate>Certified by</i>:
<span ng-show="paypro.verified"><i class="fi-lock color-greeni"></i> {{paypro.verifyData.caName}}</span>
<span ng-show="!paypro.verified"><i class="fi-unlock color-yellowi"></i> <span translate>Untrusted</span></span>
</div>
<div ng-if="paypro.memo" class="m10v lh140">
<i translate>Merchant message</i>:
<span class="text-gray">
{{paypro.memo}}
</span>
</div>
<div ng-if="paypro.expires" class="m10v">
<i translate>Expires</i>: {{paypro.expires * 1000 | amTimeAgo }}
<div class="size-18 m5t text-gray" ng-show="alternative">
{{ alternative }} {{ alternativeIsoCode }}
</div>
</div>
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 oh">
<span class="text-gray" translate>Pay To</span>:
<span class="right enable_text_select">{{paypro.domain}}</span>
</li>
<li class="line-b p10 oh" ng-if="paypro.toAddress">
<span class="text-gray" translate>Address</span>:
<span class="right enable_text_select">{{paypro.toAddress}}</span>
</li>
<li class="line-b p10 oh">
<span class="text-gray" translate>Certified by</span>:
<span class="right">
<span ng-show="paypro.verified"><i class="fi-lock color-greeni"></i>
{{paypro.verifyData.caName || paypro.verifyData}}</span>
<span ng-show="!paypro.verified"><i class="fi-unlock color-yellowi"></i> <span translate>Untrusted</span></span>
</span>
</li>
<li class="line-b p10 oh" ng-if="paypro.memo">
<span class="text-gray" translate>Memo</span>:
<span class="right">{{paypro.memo}}</span>
</li>
<li class="line-b p10 oh" ng-if="paypro.expires">
<span class="text-gray" translate>Expires</span>:
<span class="right">{{paypro.expires * 1000 | amTimeAgo }}</span>
</li>
</ul>
<div class="extra-margin-bottom"></div>
</div>
<div class="extra-margin-bottom"></div>

View file

@ -5,12 +5,12 @@
</a>
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis">
<h1 translate class="title ellipsis">
QR-Scanner
</h1>
</section>
</nav>
<div class="p60t text-center" ng-init="init()">
<div class="modal-content text-center fix-modals-touch" ng-init="init()">
<canvas id="qr-canvas" width="200" height="150"></canvas>
<video id="qrcode-scanner-video" width="300" height="225"></video>
</div>

View file

@ -12,7 +12,7 @@
</section>
</nav>
<div class="p45t">
<div class="modal-content fix-modals-touch">
<div class="header-modal text-center">
<div class="size-42">
<span ng-if="btx.action == 'received'">+</span><span ng-if="btx.action == 'sent'">-</span>{{btx.amountStr}} {{settings.unitName}}
@ -22,7 +22,7 @@
</div>
</div>
<h4 class="title m0" translate>Information</h4>
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li ng-if="btx.addressTo && btx.addressTo != 'N/A'" class="line-b p10 oh" ng-click="copyAddress(btx.addressTo)">
<span class="text-gray" translate>To</span>:
@ -68,7 +68,7 @@
</ul>
<div ng-if="btx.actions[0] && isShared">
<h4 class="title m0" translate>Signatures</h4>
<h4 class="title m0" translate>Participants</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 text-gray" ng-repeat="c in btx.actions">
<span class="right">
@ -82,11 +82,12 @@
<div ng-show="btx.txid" class="tx-details-blockchain">
<div class="text-center m20t">
<button class="button outline dark-gray tiny" ng-click="$root.openExternalLink('http://' + getShortNetworkName() + '.insight.is/tx/' + btx.txid)">
<button class="button outline round dark-gray tiny" ng-click="$root.openExternalLink('https://' +
(getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid)">
<span class="text-gray" translate>See it on the blockchain</span>
</button>
</div>
</div>
<div class="extra-margin-bottom"></div>
</div>
<div class="extra-margin-bottom"></div>

View file

@ -1,30 +1,43 @@
<div ng-if="statusStr && statusStr == 'Transaction broadcasted'" class="popup-txsent">
<div ng-if="type == 'broadcasted'" class="popup-txsent">
<i class="small-centered columns fi-check m20tp"></i>
<div class="text-center size-18 text-white text-bold tu p20">
<span translate>Payment Sent</span>
</div>
<div class="text-center">
<a class="button outline white small-5" ng-click="cancel()" translate>OKAY</a>
<a class="button outline round white tiny small-4" ng-click="cancel()" translate>OKAY</a>
</div>
</div>
<div ng-if="statusStr && statusStr == 'Transaction proposal signed'" class="popup-txsigned">
<div ng-if="type == 'created'" class="popup-txsigned">
<i class="small-centered columns fi-check m20tp"></i>
<div class="text-center size-18 text-primary tu text-bold p20">
{{statusStr|translate}}
<span translate>Payment Proposal Created</span>
</div>
<div class="text-center">
<a class="button outline light-gray small-5" ng-click="cancel()" translate>OKAY</a>
<a class="button outline round light-gray tiny small-4" ng-click="cancel()" translate>OKAY</a>
</div>
</div>
<div ng-if="statusStr && statusStr == 'Transaction was rejected'" class="popup-txrejected">
<i class="fi-x small-centered columns m20tp"></i>
<div class="text-center size-18 tu text-warning text-bold p20">
{{statusStr|translate}}
<div ng-if="type == 'accepted'" class="popup-txsigned">
<i class="small-centered columns fi-check m20tp"></i>
<div class="text-center size-18 text-primary tu text-bold p20">
<span translate>Payment Accepted</span>
</div>
<div class="text-center">
<a class="button outline light-gray small-5" ng-click="cancel()" translate>OKAY</a>
<a class="button outline round light-gray tiny small-4" ng-click="cancel()" translate>OKAY</a>
</div>
</div>
<div ng-if="type=='rejected'" class="popup-txrejected">
<i class="fi-x small-centered columns m20tp"></i>
<div class="text-center size-18 tu text-warning text-bold p20">
<span translate>Payment Rejected</span>
</div>
<div class="text-center">
<a class="button outline light-gray round tiny small-4" ng-click="cancel()" translate>OKAY</a>
</div>
</div>

View file

@ -1,18 +1,18 @@
<nav class="tab-bar">
<section class="left-small">
<a ng-click="cancel()">
<i class="icon-arrow-left3 icon-back"></i>
<i class="icon-arrow-left3 icon-back"></i>
<span class="text-back" translate>Back</span>
</a>
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" ng-style="{'color':color}" translate>
Transaction proposal
Payment Proposal
</h1>
</section>
</nav>
<div class="p45t" ng-init="updateCopayerList()">
<h4 class="title m0" translate>Information</h4>
<div class="modal-content fix-modals-touch" ng-init="updateCopayerList()">
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 oh" ng-click="copyAddress(tx.toAddress)">
<span class="text-gray" translate>To</span>:
@ -24,6 +24,10 @@
<span class="label gray radius">{{alternativeAmountStr}}</span>
</span>
</li>
<li class="line-b p10">
<span class="text-gray" translate>Fee</span>:
<span class="right">{{feeStr}}</span>
</li>
<li class="line-b p10">
<span class="text-gray" translate>Time</span>:
<span class="right">
@ -66,7 +70,7 @@
</div>
<div ng-if="tx.actions[0] && !txRejected && !txBroadcasted">
<h4 class="title m0" translate>Signatures</h4>
<h4 class="title m0" translate>Participants</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 text-gray" ng-repeat="ac in tx.actions">
<i class="icon-contact size-24"></i>
@ -87,23 +91,23 @@
<div class="row column m20t text-center text-warning" ng-if="tx.removed" translate>
The transaction was removed by creator
The payment was removed by creator
</div>
<div class="row m20t" ng-if="tx.pendingForUs">
<div class="large-5 medium-5 small-6 columns">
<button class="button outline dark-gray m0 expand" ng-click="reject(tx);"
<button class="button outline round dark-gray expand" ng-click="reject(tx);"
ng-disabled="loading">
<i class="fi-x"></i>
<span translate>Reject</span>
</button>
</div>
<div class="large-5 medium-5 small-6 columns text-right">
<button class="button primary m0 expand" ng-click="sign(tx)"
<button class="button primary round expand" ng-click="sign(tx)"
ng-style="{'background-color':color}"
ng-disabled="loading">
<i class="fi-check"></i>
<span translate>Sign</span>
<span translate>Accept</span>
</button>
</div>
</div>
@ -111,37 +115,37 @@
<div class="text-center text-gray" ng-show="tx.status != 'pending'">
<div class="m10t"
ng-show="tx.status=='accepted'" translate>
Transaction accepted...
Payment accepted...
</div>
<div class="m10t"
ng-show="!loading && tx.status!='broadcasted' && tx.status=='accepted' && tx.status!='rejected'">
<div translate>But not broadcasted. Try to send manually</div>
<button class="primary"
<button class="primary round"
ng-click="broadcast(tx)"
ng-disabled="loading"> <i class="fi-upload-cloud"></i>
<span translate>Broadcast Transaction</span>
<span translate>Broadcast Payment</span>
</button>
</div>
<div class="text-success m10t"
ng-show="tx.status=='broadcasted'" translate>
Transaction sent!
Payment sent!
</div>
<div class="text-center text-warning"
ng-show="tx.status=='rejected'" translate>
Transaction finally rejected
Payment finally rejected
</div>
</div>
<div class="row column m20t" ng-if="tx.couldRemove">
<div class="text-gray size-12 text-center m20b" show="tx.couldRemove" translate>
* Only transactions created by yourself with no peer signatures can be removed
<div class="row column m20t" ng-if="tx.canBeRemoved">
<div class="text-gray size-12 text-center m20b" show="tx.canBeRemoved" translate>
* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created.
</div>
<button class="tiny expand outline dark-gray" ng-click="remove(tx)"
ng-disabled="loading" ng-show="tx.couldRemove">
<button class="tiny expand round outline dark-gray" ng-click="remove(tx)"
ng-disabled="loading" ng-show="tx.canBeRemoved">
<i class="fi-trash size-14 m5r"></i>
<span translate>Remove transaction</span>
<span translate>Delete Payment Proposal</span>
</button>
</div>
<div class="extra-margin-bottom"></div>
</div>
<div class="extra-margin-bottom"></div>

View file

@ -0,0 +1,44 @@
<nav class="tab-bar">
<section class="left-small">
<a ng-click="cancel()" class="p10">
<span class="text-close" translate>Close</span>
</a>
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" ng-style="{'color':color}" translate>
Choose a wallet to send funds
</h1>
</section>
</nav>
<div class="modal-content">
<div class="onGoingProcess" ng-if="gettingAddress">
<div class="onGoingProcess-content" ng-style="{'background-color':'#222'}">
<div class="spinner">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
<span translate> Getting address for wallet {{selectedWalletName}} ...</span>
</div>
</div>
<div ng-if="!gettingAddress">
<ul class="no-bullet">
<li class="line-b" ng-repeat="w in wallets">
<a ng-click="selectWallet(w.id, w.name)" class="db oh">
<div class="avatar-wallet"
ng-style="{'background-color':w.color}">{{(w.name || w.id) | limitTo: 1}}</div>
<div class="ellipsis name-wallet text-bold">{{w.name || w.id}}</div>
<div class="size-12">{{w.m}} of {{w.n}}
<span ng-show="w.network=='testnet'">[Testnet]</span>
</div>
</a>
</li>
</ul>
</div>
<div class="extra-margin-bottom"></div>
</div>

View file

@ -5,31 +5,42 @@
</div>
<div class="content p20v row payment-uri" ng-controller="paymentUriController as payment">
<div class="large-12 columns" ng-init="uri = payment.checkBitcoinUri()">
<div class="panel text-center" ng-show="!uri">
<div class="large-12 columns" ng-init="payment.checkBitcoinUri()">
<div class="panel text-center" ng-if="!payment.uri">
<h1 translate>Bitcoin URI is NOT valid!</h1>
</div>
<div ng-show="uri">
<div ng-if="payment.uri" ng-init="wallets = payment.getWallets(payment.uri.network)">
<h1 translate>Make a payment to</h1>
<div class="panel size-14">
<div class="ellipsis"><b translate>Address</b>: {{uri.address.toString()}}</div>
<div ng-show="uri.amount"><b translate>Amount</b>: {{uri.amount}}</div>
<div ng-show="uri.message"><b translate>Message</b>: {{uri.message}}</div>
<div ng-show="uri.network == 'testnet'"><b translate>Network</b>: {{uri.network}}</div>
<div class="ellipsis"><b translate>Address</b>: {{payment.uri.address.toString()}}</div>
<div ng-show="payment.uri.amount"><b translate>Amount</b>: {{payment.uri.amount}}</div>
<div ng-show="payment.uri.message"><b translate>Message</b>: {{payment.uri.message}}</div>
<div ng-show="payment.uri.network == 'testnet'"><b translate>Network</b>: {{payment.uri.network}}</div>
</div>
<div ng-if="!wallets || !wallets.length">
<div class="box-notification">
<span class="text-warning">
<b translate>There are no wallets to make this payment</b>
<span ng-show="payment.uri.network == 'testnet'">[testnet]</span>
</span>
</div>
</div>
<div ng-if="wallets.length">
<h2 translate>Select a wallet</h2>
<ul class="no-bullet">
<li class="panel" ng-repeat="w in wallets">
<a ng-click="payment.selectWallet(w.id)">
<div class="avatar-wallet"
ng-style="{'background-color':w.color}">{{(w.name || w.id) | limitTo: 1}}</div>
<div class="ellipsis">{{w.name || w.id}}</div>
<div class="size-12">{{w.m}} of {{w.n}}
<span ng-show="w.network=='testnet'">[Testnet]</span>
</div>
</a>
</li>
</ul>
</div>
<h2 translate>Select a wallet</h2>
<ul class="no-bullet" ng-init="wallets = payment.getWallets(uri.network)">
<li class="panel" ng-repeat="w in wallets">
<a ng-click="payment.selectWallet(w.id)">
<div class="avatar-wallet"
ng-style="{'background-color':w.color}">{{(w.name || w.id) | limitTo: 1}}</div>
<div class="ellipsis">{{w.name || w.id}}</div>
<div class="size-12">{{w.m}} of {{w.n}}
<span ng-show="w.network=='testnet'">[Testnet]</span>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>

View file

@ -9,7 +9,25 @@
<div class="content preferences" ng-controller="preferencesController as preferences">
<ul class="no-bullet m0 size-14" ng-show="!index.noFocusedWallet">
<h4 class="title m0" translate>{{index.walletName}} settings</h4>
<h4 class="title m0">{{index.alias}} [{{index.walletName}}] <span translate>settings</span></h4>
<li class="line-b p20" ng-click="$root.go('preferencesAlias')">
<span translate>Wallet Alias</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
{{index.alias||index.walletName}}
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesEmail')">
<span translate>Email Notifications</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
<span ng-if="!index.preferences.email" translate>Disabled</span>
<span ng-if="index.preferences.email">{{index.preferences.email}}</span>
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesColor')">
<span translate>Color</span>
@ -59,6 +77,14 @@
{{preferences.selectedAlternative.name}}
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesFee')">
<span translate>Bitcoin Network Fee Policy</span>
<span class="right text-gray">
<i class="icon-arrow-right3 size-24 right"></i>
{{preferences.feeName|translate}}
</span>
</li>
<li class="line-b p20" ng-click="$root.go('preferencesBwsUrl')">
<span>Bitcore Wallet Service</span>

View file

@ -4,36 +4,39 @@
ng-init="titleSection='About Copay'; goBackToState = 'preferences'">
</div>
<div class="content p20v" ng-controller="preferencesAbout as about">
<ul class="no-bullet m0 size-14">
<div class="content preferences p20v" ng-controller="preferencesAbout as about">
<div class="text-center small-5 small-centered columns m20b" >
<img src="img/logo.png" alt="Copay" width="100%">
</div>
<h4 class="title m0" translate>Release Information</h4>
<div ng-controller="versionController as v">
<li class="line-b p20" ng-conf>
<span translate>Version</span>
<span class="right text-gray">
v{{v.version}}
</span>
</li>
<li class="line-b p20" ng-conf ng-click="$root.openExternalLink('https://github.com/bitpay/copay/tree/'+v.commitHash)">
<span translate>Commit hash</span>
<span class="right text-gray">
#{{v.commitHash}}
</span>
</li>
<ul class="no-bullet m0 size-14">
<li class="line-b p20" ng-conf>
<span translate>Version</span>
<span class="right text-gray">
v{{v.version}}
</span>
</li>
<li class="line-b p20" ng-conf ng-click="$root.openExternalLink('https://github.com/bitpay/copay/tree/'+v.commitHash)">
<span translate>Commit hash</span>
<span class="right text-gray">
#{{v.commitHash}}
</span>
</li>
</ul>
</div>
<h4 class="title m0">&nbsp;</h4>
<li class="line-b p20" ng-conf ng-click="$root.go('logs')">
<span translate>Session log</span>
<span class="right text-gray">
<ul class="no-bullet m0 size-14">
<li class="line-b p20" ng-click="$root.go('disclaimer')">
<i class="icon-arrow-right3 size-24 right text-gray"></i>
</span>
</li>
</ul>
<span translate>Terms of Use</span>
</li>
<li class="line-b p20" ng-conf ng-click="$root.go('logs')">
<i class="icon-arrow-right3 size-24 right text-gray"></i>
<span translate>Session log</span>
</li>
</ul>
</div>

View file

@ -0,0 +1,16 @@
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Wallet Alias'; goBackToState = 'preferences'">
</div>
<div class="content preferences p20v" ng-controller="preferencesAliasController as prefAlias">
<form name="settingsAliasForm" ng-submit="prefAlias.save()" class="columns">
<label><span translate>Alias for <i>{{index.walletName}}</i></span></label>
<input type="text" id="alias2" type="text" name="alias2" ng-model="prefAlias.alias">
<input type="submit" class="button expand black round" value="{{'Save'|translate}}"
ng-style="{'background-color':index.backgroundColor}">
</form>
<p class="text-gray text-center columns size-14" translate>Changing wallet alias only affects the local wallet name.</p>
</div>
<div class="extra-margin-bottom"></div>

View file

@ -1,5 +1,5 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Bitcore Wallet Service'; goBackToState = 'preferences'; noColor = true">
</div>
@ -10,7 +10,7 @@
<form name="settingsBwsUrlForm" ng-submit="prefBwsUrl.save()" class="columns">
<label>Bitcore Wallet Service URL</label>
<input type="text" id="bwsurl" type="text" name="bwsurl" ng-model="prefBwsUrl.bwsurl">
<input type="submit" class="button expand black radius" value="{{'Save'|translate}}"
<input type="submit" class="button expand black round" value="{{'Save'|translate}}"
ng-style="{'background-color':index.backgroundColor}">
</form>
</div>

View file

@ -1,5 +1,5 @@
<div
class="topbar-container"
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Delete Wallet'; goBackToState = 'preferencesAdvanced'">
</div>
@ -13,8 +13,8 @@
</span>
</div>
<div class="columns text-center m10t">
<p translate class="size-14 text-gray">Permanently delete this wallet. THIS ACTION CANNONT BE REVERSED</p>
<button class="button expand warning" ng-click="preferences.deleteWallet()" translate>
<p translate class="size-14 text-gray">Permanently delete this wallet. THIS ACTION CANNOT BE REVERSED</p>
<button class="button round expand warning" ng-click="preferences.deleteWallet()" translate>
Delete wallet
</button>
</div>

View file

@ -0,0 +1,39 @@
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Email Notifications'; goBackToState = 'preferences'">
</div>
<div class="content preferences p20v" ng-controller="preferencesEmailController as prefEmail">
<div class="onGoingProcess" ng-show="prefEmail.saving && !index.isOffline">
<div class="onGoingProcess-content" ng-style="{'background-color':index.backgroundColor}">
<div class="spinner">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
<span translate>Saving preferences...</span>
</div>
</div>
<form name="emailForm" ng-submit="prefEmail.save(emailForm)" class="columns" novalidate ng-init="prefEmail.email = index.preferences.email">
<div class="box-notification" ng-show="prefEmail.error">
<span class="text-warning size-14">
{{prefEmail.error|translate}}
</span>
</div>
<label translate>email for wallet notifications</label>
<input type="email" id="email" name="email" ng-model="prefEmail.email" required>
<input type="submit" class="button expand black round" value="{{'Save'|translate}}"
ng-style="{'background-color':index.backgroundColor}" ng-disabled="emailForm.$invalid && !index.preferences.email">
</form>
<p class="text-gray text-center columns size-14" translate>Setting up email notifications could weaken your privacy, if the wallet service provider is compromised. Information available to an attacker would include your wallet addresses and its balance, but no more.</p>
</div>
<div class="extra-margin-bottom"></div>

View file

@ -0,0 +1,22 @@
<div
class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="titleSection='Bitcoin Network Fee Policy'; goBackToState = 'preferences'; noColor = true">
</div>
<div class="content preferences" ng-controller="preferencesFeeController as prefFee">
<div ng-repeat="fee in prefFee.feeOpts" ng-click="prefFee.save(fee)" class="line-b p20 size-14">
<span ng-if="fee.red" style="color:red">{{fee.name|translate}} (<span translate>{{fee.value}} bits per kB</span>)</span>
<span ng-if="!fee.red">{{fee.name|translate}} (<span translate>{{fee.value}} bits per kB</span>)</span>
<i class="fi-check size-16 right" ng-show="prefFee.feeName == fee.name"></i>
</div>
<div class="row column m20t">
<div class="text-gray size-12 text-center m20b" translate>
Bitcoin transactions may include a fee collected by miners on the network. The higher the fee, the greater the incentive a miner has to include that transaction in a block. The Emergency level should only be used when there is a network congestion.
</div>
</div>
</div>
<div class="extra-margin-bottom"></div>

View file

@ -26,8 +26,8 @@
</div>
</div>
<div class="row columns start-button" ng-show="!creatingProfile">
<button ng-click="create()" class="button black expand radius size-12 text-spacing" translate> GET STARTED </button>
<button ng-click="create()" class="button black expand round size-12 text-spacing" translate> GET STARTED </button>
<p class="text-gray m5b size-12" translate>Already have a wallet?</p>
<button ng-click="create(true)" class="outline dark-gray tiny" translate>Import backup </button>
<button ng-click="create(true)" class="button round outline dark-gray tiny" translate>Import backup </button>
</div>
</div>

View file

@ -1,5 +1,5 @@
<div class="topbar-container"
<div class="topbar-container"
ng-include="'views/includes/topbar.html'"
ng-init="showCamera = true">
</div>
@ -9,10 +9,10 @@
<div class="text-center text-warning m20b">
<i class="fi-alert"></i> <span translate>You do not have a wallet</span>
</div>
<button class="button black expand" ng-click="$root.go('add')" translate>Create</button>
<button class="button black round expand" ng-click="$root.go('add')" translate>Create</button>
<div class="text-center text-gray p20v" ng-click="$root.go('preferences')">
<button class=" outline dark-gray tiny" translate> Preferences </button>
<button class=" outline round dark-gray tiny" translate> Preferences </button>
</div>
</div>
@ -46,6 +46,7 @@
"> Updating Wallet... </span>
<span translate ng-show="index.onGoingProcessName == 'scanning'">Scanning Wallet funds...</span>
<span translate ng-show="index.onGoingProcessName == 'recreating'">Recreating Wallet...</span>
<span translate ng-show="index.onGoingProcessName == 'generatingCSV'">Generating .csv file...</span>
</div>
</div>
@ -74,9 +75,9 @@
<div class="oh">
<div class="amount" ng-style="{'background-color':index.backgroundColor}">
<div ng-if="!index.anyOnGoingProcess && !index.notAuthorized">
<div ng-show="index.updateError" ng-click='index.openWallet()'>
<span translate>Could not update Wallet</span>
<br><span translate>Tap to retry</span>
<div ng-show="index.updateError" ng-click='index.openWallet(); index.updateTxHistory()'>
<span class="size-12 db m10b" translate>Could not update Wallet</span>
<button class="outline white tiny round" translate>Tap to retry</button>
</div>
<div ng-show="index.walletScanStatus == 'error'" ng-click='index.retryScan()'>
@ -84,7 +85,7 @@
<br><span translate>Tap to retry</span>
</div>
<div ng-click='index.updateAll()' ng-show="!index.updateError && index.walletScanStatus != 'error'">
<div ng-click='index.updateAll(); index.updateTxHistory()' ng-show="!index.updateError && index.walletScanStatus != 'error'">
<strong class="size-36">{{index.totalBalanceStr}}</strong>
<div class="size-14"
ng-if="index.totalBalanceAlternative">
@ -102,10 +103,10 @@
<div class="pr columns line-b">
<div class="avatar-wallet left"
ng-style="{'background-color':index.backgroundColor}">{{index.walletName | limitTo: 1}}
ng-style="{'background-color':index.backgroundColor}">{{ (index.alias || index.walletName) | limitTo: 1}}
</div>
<div class="right">
<a ng-click="$root.go('preferences')" class="button outline light-gray tiny m0">
<a ng-click="$root.go('preferences')" class="button outline round light-gray tiny preferences-icon m0">
<i class="fi-widget size-18 vm"></i>
<span class="show-for-medium-up" translate>Preferences</span>
</a>
@ -113,18 +114,19 @@
<div class="wallet-info">
<div ng-show="index.isShared" ng-click="openCopayersModal(index.copayers, index.copayerId)">
<p class="m0">
{{index.m}} <span translate>of</span> {{index.n}}
{{(index.alias || index.walletName)}}
</p>
<div class="size-12 text-gray">
<span translate>Multisignature wallet</span> <span ng-if="index.network != 'livenet'">- Testnet</span>
<span translate>Multisignature wallet</span> ({{index.m}} <span translate>of</span> {{index.n}})
<span ng-if="index.network != 'livenet'">- Testnet</span>
</div>
</div>
<div ng-show="!index.isShared">
<p class="m0">
{{index.m}} <span translate>of</span> {{index.n}}
{{(index.alias || index.walletName)}}
</p>
<div class="size-12 text-gray">
<span translate>Personal Wallet</span> <span ng-if="index.network != 'livenet'">- Testnet</span>
<div class="size-12 text-gray" ng-if="index.network != 'livenet'">
Testnet
</div>
</div>
</div>
@ -143,7 +145,7 @@
This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information.
</div>
<div class="text-center m10t ">
<span class="button outline dark-gray tiny"
<span class="button outline round dark-gray tiny"
ng-click="index.recreate()">
<span translate>Recreate</span>
</span>
@ -152,7 +154,7 @@
<div ng-if="index.txps[0]">
<div ng-show="index.requiresMultipleSignatures">
<h4 class="title m0" translate>Spend proposals</h4>
<h4 class="title m0" translate>Payment Proposals</h4>
<div class="last-transactions pr" ng-repeat="tx in index.txps"
ng-include="'views/includes/transaction.html'">
</div>
@ -195,13 +197,13 @@
</div>
<div class="small-6 columns m20t">
<span class="button expand outline dark-gray tiny"
<span class="button expand outline round dark-gray tiny"
ng-click="home.skipBackup = true">
<span translate>SKIP BACKUP</span>
</span>
</div>
<div class="small-6 columns m20t">
<span class="button black expand radius tiny"
<span class="button black expand round tiny"
ng-click="$root.go('backup')" ng-style="{'background-color':index.backgroundColor}" >
<span translate>Backup now</span>
</span>
@ -213,8 +215,16 @@
<div class="large-12 columns">
<h2 class="text-center m10t" translate>My Bitcoin address</h2>
<div >
<div class="text-center" ng-click="home.copyAddress(home.addr)">
<qrcode size="220" data="bitcoin:{{home.addr}}"></qrcode>
<div class="box-notification" ng-show="home.addrError">
<span class="text-warning">
{{home.addrError|translate}}
</span>
</div>
<div class="text-center" ng-click="home.copyAddress(home.addr[index.walletId])">
<qrcode size="220" data="bitcoin:{{home.addr[index.walletId]}}"></qrcode>
<div ng-show="home.generatingAddress" style="position:relative; top:-226px; height:0px">
<div style="height:220px; width:220px; margin:auto; background: url(img/qr.png) white">
<div class="spinner" style="margin-top:80px">
@ -228,7 +238,7 @@
</div>
<div class="m10t" >
<h4 ng-class="{'enable_text_select': !index.isCordova}" class="size-12">
{{home.generatingAddress ? '...' : home.addr}}
{{home.generatingAddress ? '...' : home.addr[index.walletId]}}
</h4>
</div>
@ -236,8 +246,8 @@
</div>
<div class="m10t text-center" ng-show="index.isCordova">
<span class="button outline dark-gray tiny"
ng-click="home.shareAddress(home.addr)">
<span class="button outline dark-gray tiny round"
ng-click="home.shareAddress(home.addr[index.walletId])">
<i class="fi-share"></i>
<span translate>Share address</span>
</span>
@ -249,12 +259,18 @@
</div>
<div class="row m20t">
<div class="large-12 columns">
<button class="button black expand radius" ng-click="home.setNewAddress()"
<button class="button black expand round m0" ng-click="home.setAddress(true)"
ng-style="{'background-color':index.backgroundColor}" ng-disabled="home.blockUx || index.isOffline ||home.generatingAddress" translate>
Generate new address
</button>
</div>
</div>
<div class="m20t text-center" ng-show="!home.generatingAddress && home.addr[index.walletId]">
<a class="size-12 text-gray" ng-click="home.openCustomizedAmountModal(home.addr[index.walletId])">
<i class="fi-bitcoin"></i>
<span translate>Request a specific amount</span>
</a>
</div>
</div>
<div class="extra-margin-bottom"></div>
</div> <!-- END Receive -->
@ -266,20 +282,37 @@
-->
<div id="send" class="send tab-view">
<div ng-show="index.lockedBalance">
<div>
<h4 class="title m0">
<div class="left">
<i class="fi-info size-36 m10r lh"></i>
<a class="right lh"
ng-if="index.feeToSendMaxStr && index.availableBalance > 0 && !home.blockUx && !home.lockAmount"
ng-click="home.sendAll(index.availableMaxBalance, index.feeToSendMaxStr)"
translate> Send All
</a>
<div ng-show="!index.lockedBalance && index.availableBalanceStr">
<div class="size-10">
<span class="db text-bold">
<span translate>Available Balance</span>:
{{index.availableBalanceStr }}
</span>
</div>
</div>
<div class="size-12">
<span class="db text-bold">
<span translate>Available Balance</span>:
{{index.availableBalanceStr }}
</span>
<span class="text-gray">
{{index.lockedBalanceStr}}
<span translate>in pending transactions</span>
</span>
<div ng-show="index.lockedBalance">
<div class="left">
<i class="fi-info size-24 m10r"></i>
</div>
<div class="size-10">
<span class="db text-bold">
<span translate>Available Balance</span>:
{{index.availableBalanceStr }}
</span>
<span class="text-gray" >
{{index.lockedBalanceStr}}
<span translate>locked by pending payments</span>
</span>
</div>
</div>
</h4>
</div>
@ -295,11 +328,9 @@
<div ng-hide="home._paypro || home.hideAddress">
<div class="row collapse">
<label for="address" class="left" >
<span translate>To</span>
</label>
<span ng-hide="sendForm.address.$pristine">
<span class="has-error right size-12" ng-show="sendForm.address.$invalid && _address">
<i class="icon-close-circle size-14"></i>
@ -313,6 +344,9 @@
<div class="input">
<input type="text" id="address" name="address" ng-disabled="home.blockUx || home.lockAddress" ng-attr-placeholder="{{'Bitcoin address'|translate}}" ng-model="_address" valid-address required ng-focus="home.formFocus('address')" ng-blur="home.formFocus(false)">
<a class="postfix size-12 m0 text-gray" ng-click="openWalletsModal(index.otherWallets)" ng-if="index.otherWallets && index.otherWallets.length>0">
<i class="icon-wallet size-18"></i>
</a>
</div>
</div>
<div ng-show="home._paypro && !home.hideAddress">
@ -377,11 +411,11 @@
</div>
<div class="row" ng-show="!home.onGoingProcess">
<div class="large-6 medium-6 small-6 columns" ng-show="!home.blockUx && (home._paypro || home.lockAddress)">
<a ng-click="home.resetForm(sendForm)" class="button expand outline dark-gray" translate>Cancel</a>
<div class="large-6 medium-6 small-6 columns" ng-show="!home.blockUx && (home._paypro || home.lockAddress || home.lockAmount)">
<a ng-click="home.resetForm(sendForm)" class="button expand outline dark-gray round" translate>Cancel</a>
</div>
<div class="columns" ng-class="{'small-6 medium-6 large-6':(home._paypro || home.lockAddress)}">
<button type="submit" class="button black radius expand" ng-disabled="sendForm.$invalid || home.blockUx || index.isOffline"
<div class="columns" ng-class="{'small-6 medium-6 large-6':(home._paypro || home.lockAddress || home.lockAmount)}">
<button type="submit" class="button black round expand" ng-disabled="sendForm.$invalid || home.blockUx || index.isOffline"
ng-style="{'background-color':index.backgroundColor}" translate>
Send
</button>
@ -404,8 +438,8 @@
<div class="large-12 columns">
<div class="oh text-center">
<span ng-show="index.txHistoryError && !index.notAuthorized" ng-click='index.updateTxHistory()'>
<span translate>Could not fetch transaction history</span>
<br> <span translate>Tap to retry</span>
<p class="size-12 m10b db text-gray" translate>Could not fetch transaction history</p>
<button class="outline round light-gray tiny" translate>Tap to retry</button>
</span>
<span ng-if="!index.txHistoryError" translate>
No transactions yet
@ -413,7 +447,7 @@
</div>
</div>
</div>
<div ng-show="index.txHistory[0]" class="scroll">
<div ng-show="index.txHistory[0]">
<div ng-repeat="btx in index.txHistory"
ng-click="home.openTxModal(btx)"
class="row collapse last-transactions-content">
@ -448,8 +482,9 @@
{{btx.message || btx.addressTo}}
</div>
</div>
<div class="m20t columns text-center" ng-show="index.txHistoryPaging || index.updatingTxHistory">
<button class="outline light-gray small expand m0"
<div class="row m20t text-center" ng-show="index.txHistoryPaging || index.updatingTxHistory">
<div class="columns large-12 medium-12 small-12">
<button class="outline light-gray round small expand m0"
ng-click="index.updateTxHistory(index.skipHistory)"
ng-if="!index.updatingTxHistory">
<span translate>More</span> <i class="icon-arrow-down4 ng-scope"></i>
@ -461,8 +496,16 @@
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
</div>
</div>
<div ng-if="!index.isCordova && index.txHistory[0] && !index.updatingTxHistory" class="m20t text-center">
<input id="export_file" type="file" nwsaveas="Copay-{{index.alias || index.walletName}}.csv" accept=".csv" style="display:none">
<a class="text-gray size-12" ng-click="index.csvHistory();">
<i class="fi-page-export-csv"></i>
<span translate>Download CSV file</span>
</a>
</div>
<div class="extra-margin-bottom"></div>
</div> <!-- END History -->

View file

@ -3,6 +3,11 @@
* Copay main CSS
*
*/
body {
font-family: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.panel h1, .panel h2, .panel h3, .panel h4, .panel h5, .panel h6, .panel p, .panel li, .panel dl {
color: #2C3E50;
}
@ -44,6 +49,13 @@ h4.title {
font-size: 0.7rem;
}
h4.title a {
text-transform: none;
font-weight: 400;
padding: 7px;
font-size: 12px;
}
body, html{
height:100%;
width:100%;
@ -147,11 +159,14 @@ input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill, inpu
.content {
width:100%;
position: absolute;
top: 46px;
top: 45px;
bottom: 0;
overflow: auto;
}
.content.disclaimer {
top: 0;
}
.logo-setup {
text-align: center;
@ -338,6 +353,7 @@ ul.manage li {
.size-72 { font-size: 72px; }
.m5 {margin: 5px;}
.m5t {margin-top: 5px;}
.m8t {margin-top: 8px;}
.m5b {margin-bottom: 5px;}
.m5r {margin-right: 5px;}
.m10 {margin: 10px;}
@ -610,7 +626,6 @@ table tbody tr:last-child td {
button.outline,
button.outline:hover,
button.outline:focus {
border-radius: 3px;
background: transparent;
}
@ -620,7 +635,6 @@ button.outline:focus {
button.outline.tiny,
button.outline.tiny:hover,
button.outline.tiny:focus {
border-radius: 3px;
background: transparent;
}
@ -647,7 +661,12 @@ button.outline.light-gray:focus {
color: #7A8C9E;
}
.button.outline.white {
.button.outline.white,
.button.outline.white:hover,
.button.outline.white:focus,
button.outline.white,
button.outline.white:hover,
button.outline.white:focus {
background-color: transparent;
border: 1px solid #fff;
color: #fff;
@ -662,7 +681,6 @@ button.secondary:focus,
.button.secondary:focus {
background-color: #008CC1;
color: #fff;
border-radius: 3px;
}
/* PRIMARY */
@ -674,7 +692,6 @@ button.primary:focus,
.button.primary:focus {
background-color: #1ABC9C;
color: #fff;
border-radius: 3px;
}
/* WARNING */
@ -686,55 +703,47 @@ button.warning:focus,
.button.warning:focus {
background-color: #ED4A43;
color: #fff;
border-radius: 3px;
}
/* WHITE */
button.white,
.button.white {
button.white:hover,
button.white:focus,
.button.white,
.button.white:hover,
.button.white:focus {
background-color: #fff;
color: #2C3E50;
}
/* BLACK */
button.black,
.button.black {
button.black:hover,
button.black:focus,
.button.black,
.button.black:hover,
.button.black:focus {
background-color: #2C3E50;
color: #fff;
}
/* GRAY */
button.gray,
.button.gray {
button.gray:hover,
button.gray:focus,
.button.gray,
.button.gray:hover,
.button.gray:focus {
background-color: #A9B2B8;
color: #2C3E50;
}
button.disabled.black,
button[disabled].black,
.button.disabled.black,
.button[disabled].black,
button.disabled.white,
button[disabled].white,
.button.disabled.white,
.button[disabled].white,
button.disabled.warning,
button[disabled].warning,
.button.disabled.warning,
.button[disabled].warning,
button.disabled.primary,
button[disabled].primary,
.button.disabled.primary,
.button[disabled].primary,
button.disabled.secondary,
button[disabled].secondary,
.button.disabled.secondary,
.button[disabled].secondary {
button.disabled, button[disabled], .button.disabled, .button[disabled] {
border-color: transparent !important;
background-color: #A5B2BF !important;
color: #fff;
color: #fff !important;
}
.button, button {
text-transform: uppercase;
transition: none !important;
@ -797,47 +806,14 @@ label.postfix, a.postfix {
width: 40px;
}
.photo-container {
margin-right: 3px;
display: inline-block;
width: 35px;
height: 35px;
color: #fff;
background: #7A8C9E;
border-radius: 100%;
vertical-align: middle;
overflow: hidden;
text-align: center;
}
.photo-container.profile {
width: 80px;
height: 80px;
}
.need-backup {
background: #ED4A43;
-moz-box-shadow: 1px 1px 0px 0px #A02F23;
box-shadow: 1px 1px 0px 0px #A02F23;
position: absolute;
top: 22px;
left: 0px;
width: 14px;
height: 14px;
border-radius: 100%;
font-size: 9px;
padding-top: 2px;
color: #fff;
}
.pointer {
cursor: pointer;
}
.input.block i {
position: absolute;
top: 5px;
left: 10px;
top: 2px;
left: 15px;
font-size: 20px;
color: #7A8C9E;
border-right: 1px solid #ccc;
@ -1138,6 +1114,10 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
cursor: pointer !important;
}
.preferences-icon {
padding: 0.6rem 0.8rem !important;
}
.passModal {
background: #FFFFFF;
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);

View file

@ -11,6 +11,8 @@ body {
-khtml-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none !important;
-webkit-overflow-scrolling: touch;
}
input {
@ -24,10 +26,11 @@ input {
-webkit-user-drag: none;
-ms-user-drag: none;
user-drag: none;
-webkit-tap-highlight-color:rgba(0,0,0,0);
}
body, div, .row {
-webkit-overflow-scrolling: touch;
.fix-modals-touch {
-webkit-overflow-scrolling: auto;
}
.enable_text_select {
@ -88,12 +91,8 @@ _:-ms-fullscreen, :root .main {
.tab-bar {
background: #FFFFFF;
box-shadow: 0px 1px 1px 0px rgba(0,0,0,0.10);
display: block;
position: fixed;
width: 100%;
z-index: 5;
line-height: 3.2rem;
border-bottom: 1px solid #E9E9EC;
}
.tab-bar h1 {
@ -204,8 +203,8 @@ _:-ms-fullscreen, :root .main {
.walletHome .wallet-info {
margin-left: 85px;
line-height: 110%;
float: left;
margin-bottom: 20px;
height: 60px;
overflow: hidden;
}
.copayers {
@ -246,6 +245,7 @@ ul.copayer-list img {
font-size: 14px;
}
a.missing-copayers {
bottom: -34px;
text-align: center;
@ -255,6 +255,8 @@ a.missing-copayers {
.button, button {
padding: 1rem 1.2rem 1.0625rem;
border: 1px solid transparent;
font-family: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.box-setup {
@ -272,7 +274,6 @@ a.missing-copayers {
.sidebar {
background: #2C3E50;
box-shadow: inset -2px 0px 1px 0px rgba(0,0,0,0.40);
}
.sidebar li {
@ -282,10 +283,9 @@ a.missing-copayers {
.sidebar li.nav-item.selected {
background-color: #122232;
box-shadow: inset -1px 0px 1px 0px rgba(0,0,0,0.20);
}
.sidebar .avatar-wallet, .payment-uri .avatar-wallet {
.sidebar .avatar-wallet, .payment-uri .avatar-wallet, .modal-content .avatar-wallet {
background-color: #2C3E50;
color: #fff;
font-size: 20px;
@ -301,9 +301,7 @@ a.missing-copayers {
}
.sidebar header {
width: 100%;
text-align: center;
height: 7rem;
padding: 1.7rem;
border-bottom: 1px solid #384B5F;
}
@ -322,7 +320,7 @@ a.missing-copayers {
margin-bottom: 30px;
}
.sidebar ul.off-canvas-list li a {
.sidebar ul.off-canvas-list li a, .modal-content ul li a {
font-size: 12px;
font-weight: 300;
border-bottom: transparent;
@ -358,13 +356,6 @@ ul.off-canvas-list li a:hover {
background: none;
}
a, button, .button, input, textarea, select {
-webkit-box-shadow: none !important;
-moz-box-shadow: none !important;
box-shadow: none !important;
-webkit-tap-highlight-color:rgba(0,0,0,0);
}
.move-right .close-menu {
cursor: pointer;
box-shadow: none;
@ -381,7 +372,7 @@ a, button, .button, input, textarea, select {
/* === */
/* Have to set height explicity on ui-view
/* Have to set height explicity on ui-view
to prevent collapsing during animation*/
.main[ui-view]{
height: 100%; /* TODO */
@ -408,7 +399,7 @@ to prevent collapsing during animation*/
animation-duration: .3s;
animation-iteration-count: 1;
animation-fill-mode: both;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-duration: .3s;
-webkit-animation-iteration-count: 1;
@ -416,8 +407,6 @@ to prevent collapsing during animation*/
}
.CslideInUp {
transform: translate3d(0, 100%, 0);
-webkit-transform: translate3d(0, 100%, 0);
-webkit-animation-name: slideInUp;
animation-name: slideInUp;
z-index: 1003;
@ -433,8 +422,6 @@ to prevent collapsing during animation*/
z-index: 1003;
}
.CslideInRight {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
-webkit-animation-name: slideInRight;
animation-name: slideInRight;
z-index: 1003;
@ -572,18 +559,34 @@ to prevent collapsing during animation*/
top: 0 !important;
}
.modal-content {
position: fixed;
overflow-y: auto;
height: 100%;
width: 100%;
top: 45px;
padding-bottom: 33px;
-webkit-transform: translate3d(0,0,0);
background: #fff;
}
body.modal-open {
position: fixed;
overflow: hidden;
}
.reveal-modal {
padding: 0;
border: none;
border-radius: 0;
overflow-y: auto;
padding-bottom: 20px;
outline: 0;
box-shadow: none;
}
.reveal-modal.animated.slideInRight,
.reveal-modal.animated.slideOutRight,
.reveal-modal.animated.fadeOutUp,
.reveal-modal.animated.slideInUp,
.reveal-modal.animated.slideInRight,
.reveal-modal.animated.slideOutRight,
.reveal-modal.animated.fadeOutUp,
.reveal-modal.animated.slideInUp,
.reveal-modal.animated.slideInDown {
-webkit-animation-duration: 0.3s;
animation-duration: 0.3s;
@ -603,6 +606,8 @@ input[type="text"],
input[type="time"],
input[type="url"],
input[type="week"],
input,
select,
textarea,
input[type="text"]:focus,
input[type="password"]:focus,
@ -618,8 +623,11 @@ input[type="tel"]:focus,
input[type="time"]:focus,
input[type="url"]:focus,
input[type="color"]:focus,
input:focus,
select:focus,
textarea:focus
{
outline: 0;
opacity: 1;
/*CSS transitions*/
-o-transition-property: none !important;
@ -713,7 +721,7 @@ textarea:focus
transform: translate3d(-100%, 0, 0);
width:100%;
position: absolute;
top: 46px;
top: 45px;
bottom: 37px;
overflow: auto;
padding-bottom: 40px;
@ -729,6 +737,39 @@ textarea:focus
transform: translate3d(-100%, 0, 0) !important;
}
.create-tab {
width: 100%;
border-bottom: 1px solid #DEDFE1;
margin-bottom: 25px;
padding: 0 0 .5rem 1rem;
overflow: hidden;
}
.create-tab .tab-container {
float: left;
}
.create-tab a {
font-size: .7rem;
padding: 0 0 .6rem;
color: #929396;
text-transform: uppercase;
font-weight: 500;
}
.create-tab a:hover,
.create-tab a:focus {
border-bottom: 3px solid #929396;
}
.create-tab a.selected,
.create-tab a:active {
font-weight: 600;
color: #2C3E50;
border-bottom: 3px solid #2C3E50;
}
/* removes 300ms in IE */
-ms-touch-action: manipulation; /* IE10 /
touch-action: manipulation; /* IE11+ */

View file

@ -1,4 +1,3 @@
'use strict';
angular.module('copayApp.controllers').controller('backupController',
@ -45,6 +44,9 @@ angular.module('copayApp.controllers').controller('backupController',
}
window.plugins.toast.showShortCenter('Preparing backup...');
var name = (fc.credentials.walletName || fc.credentials.walletId);
if (fc.alias) {
name = fc.alias + ' [' + name + ']';
}
var ew = this.getBackup();
var properties = {
subject: 'Copay Wallet Backup: ' + name,

View file

@ -29,18 +29,19 @@ angular.module('copayApp.controllers').controller('createController',
}
var updateRCSelect = function(n) {
$scope.totalCopayers = n;
var maxReq = COPAYER_PAIR_LIMITS[n];
self.RCValues = lodash.range(1, maxReq + 1);
$scope.requiredCopayers = Math.min(parseInt(n / 2 + 1), maxReq);
};
$scope.$watch('totalCopayers', function(tc) {
updateRCSelect(tc);
});
this.TCValues = lodash.range(1, defaults.limits.totalCopayers + 1);
this.TCValues = lodash.range(2, defaults.limits.totalCopayers + 1);
$scope.totalCopayers = defaults.wallet.totalCopayers;
this.setTotalCopayers = function(tc) {
updateRCSelect(tc);
};
this.create = function(form) {
if (form && form.$invalid) {
this.error = gettext('Please enter the required fields');
@ -75,9 +76,14 @@ angular.module('copayApp.controllers').controller('createController',
if (what && what == 'my-name') {
this.hideWalletName = true;
this.hideTabs = true;
}
else if (what && what == 'wallet-name'){
this.hideTabs = true;
}
else {
this.hideWalletName = false;
this.hideTabs = false;
}
$timeout(function() {
$rootScope.$digest();

View file

@ -1,7 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, gettextCatalog, gettext, amMoment) {
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit) {
var self = this;
self.isCordova = isCordova;
self.onGoingProcess = {};
@ -38,6 +37,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.tab = 'walletHome';
self.availableLanguages = [{
name: gettext('Deutsch'),
isoCode: 'de',
}, {
name: gettext('English'),
isoCode: 'en',
}, {
@ -49,6 +51,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
}, {
name: gettext('Japanese'),
isoCode: 'ja',
}, {
name: gettext('Portuguese'),
isoCode: 'pt',
}];
self.setOngoingProcess = function(processName, isOn) {
@ -75,6 +80,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
// Clean status
self.lockedBalance = null;
self.availableBalanceStr = null;
self.totalBalanceStr = null;
self.lockedBalanceStr = null;
self.totalBalanceStr = null;
self.alternativeBalanceAvailable = false;
self.totalBalanceAlternative = null;
@ -82,7 +90,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.txHistory = [];
self.txHistoryPaging = false;
self.pendingTxProposalsCountForUs = null;
$timeout(function() {
self.hasProfile = true;
self.noFocusedWallet = false;
@ -102,6 +109,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.txps = [];
self.copayers = [];
self.updateColor();
self.updateAlias();
storageService.getBackupFlag(self.walletId, function(err, val) {
self.needsBackup = self.network == 'testnet' ? false : !val;
@ -144,17 +152,84 @@ angular.module('copayApp.controllers').controller('indexController', function($r
$rootScope.$emit('Local/TabChanged', tab);
};
self.updateAll = function(walletStatus) {
self._updateRemotePreferencesFor = function(clients, prefs, cb) {
var client = clients.shift();
if (!client)
return cb();
$log.debug('Saving remote preferences', client.credentials.walletName, prefs);
client.savePreferences(prefs, function(err) {
// we ignore errors here
if (err) $log.warn(err);
self._updateRemotePreferencesFor(clients, prefs, cb);
});
};
self.updateRemotePreferences = function(opts, cb) {
var prefs = opts.preferences || {};
var fc = profileService.focusedClient;
// Update this JIC.
var config = configService.getSync().wallet.settings;
//prefs.email (may come from arguments)
prefs.language = self.defaultLanguageIsoCode;
prefs.unit = config.unitCode;
var clients = [];
if (opts.saveAll) {
clients = lodash.values(profileService.walletClients);
} else {
clients = [fc];
};
self._updateRemotePreferencesFor(clients, prefs, function(err) {
if (err) return cb(err);
if (!fc) return cb();
fc.getPreferences(function(err, preferences) {
if (err) {
return cb(err);
}
self.preferences = preferences;
return cb();
});
});
};
var _walletStatusHash = function(walletStatus) {
var bal;
if (walletStatus) {
bal = walletStatus.balance.totalAmount;
} else {
bal = self.totalBalanceSat;
}
return bal;
};
self.updateAll = function(opts, initStatusHash, tries) {
tries = tries || 0;
opts = opts || {};
if (opts.untilItChanges && lodash.isUndefined(initStatusHash)) {
initStatusHash = _walletStatusHash();
$log.debug('Updating status until it changes. initStatusHash:' + initStatusHash)
}
var get = function(cb) {
if (walletStatus)
return cb(null, walletStatus);
if (opts.walletStatus)
return cb(null, opts.walletStatus);
else {
self.updateError = false;
return fc.getStatus(function(err, ret) {
if (err) {
self.updateError = true;
} else {
self.setOngoingProcess('scanning', ret.wallet.scanning);
if (!opts.quiet)
self.setOngoingProcess('scanning', ret.wallet.scanning);
}
return cb(err, ret);
});
@ -165,10 +240,27 @@ angular.module('copayApp.controllers').controller('indexController', function($r
if (!fc) return;
$timeout(function() {
self.setOngoingProcess('updatingStatus', true);
$log.debug('Updating Status:', fc);
if (!opts.quiet)
self.setOngoingProcess('updatingStatus', true);
$log.debug('Updating Status:', fc, tries);
get(function(err, walletStatus) {
self.setOngoingProcess('updatingStatus', false);
var currentStatusHash = _walletStatusHash(walletStatus);
$log.debug('Status update. hash:' + currentStatusHash + ' Try:' + tries);
if (!err && opts.untilItChanges && initStatusHash == currentStatusHash && tries < 7) {
return $timeout(function() {
$log.debug('Retrying update... Try:' + tries)
return self.updateAll({
walletStatus: null,
untilItChanges: true,
triggerTxUpdate: opts.triggerTxUpdate,
}, initStatusHash, ++tries);
}, 1400 * tries);
}
if (!opts.quiet)
self.setOngoingProcess('updatingStatus', false);
if (err) {
self.handleError(err);
return;
@ -182,8 +274,18 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.walletStatus = walletStatus.wallet.status;
self.walletScanStatus = walletStatus.wallet.scanStatus;
self.copayers = walletStatus.wallet.copayers;
self.preferences = walletStatus.preferences;
self.setBalance(walletStatus.balance);
self.otherWallets = lodash.filter(profileService.getWallets(self.network), function(w) {
return w.id != self.walletId;
});;
$rootScope.$apply();
if (opts.triggerTxUpdate) {
$timeout(function() {
self.updateTxHistory();
}, 1);
}
});
});
};
@ -245,7 +347,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.updatingTxHistory = false;
if (err) {
$log.debug('TxHistory ERROR:', err);
self.handleError(err);
// We do not should errors here, since history is usually
// fetched AFTER others requests.
//self.handleError(err);
self.txHistoryError = true;
} else {
$log.debug('Wallet Transaction History:', txs);
@ -281,7 +385,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
return;
}
$log.debug('Wallet Opened');
self.updateAll(lodash.isObject(walletStatus) ? walletStatus : null);
self.updateAll(lodash.isObject(walletStatus) ? {
walletStatus: walletStatus
} : null);
$rootScope.$apply();
});
});
@ -293,6 +399,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
lodash.each(txps, function(tx) {
var amount = tx.amount * self.satToUnit;
tx.amountStr = profileService.formatAmount(tx.amount) + ' ' + config.unitName;
tx.feeStr = profileService.formatAmount(tx.fee) + ' ' + config.unitName;
tx.alternativeAmount = rateService.toFiat(tx.amount, config.alternativeIsoCode) ? rateService.toFiat(tx.amount, config.alternativeIsoCode).toFixed(2) : 'N/A';
tx.alternativeAmountStr = tx.alternativeAmount + " " + config.alternativeIsoCode;
tx.alternativeIsoCode = config.alternativeIsoCode;
@ -315,9 +422,8 @@ angular.module('copayApp.controllers').controller('indexController', function($r
tx.statusForUs = 'pending';
}
if (tx.creatorId == self.copayerId && tx.actions.length == 1) {
tx.couldRemove = true;
};
if (!tx.deleteLockTime)
tx.canBeRemoved = true;
if (tx.creatorId != self.copayerId) {
self.pendingTxProposalsCountForUs = self.pendingTxProposalsCountForUs + 1;
@ -327,14 +433,15 @@ angular.module('copayApp.controllers').controller('indexController', function($r
};
self.setTxHistory = function(txs) {
var now = new Date();
var now = Math.floor(Date.now() / 1000);
var c = 0;
self.txHistoryPaging = txs[self.limitHistory] ? true : false;
lodash.each(txs, function(tx) {
tx.ts = tx.minedTs || tx.sentTs;
// no future transaction...
if (tx.ts > now)
ts.ts = now;
// no future transactions...
if (tx.time > now)
tx.time = now;
tx.rateTs = Math.floor((tx.ts || now) / 1000);
tx.amountStr = profileService.formatAmount(tx.amount); //$filter('noFractionNumber')(
if (c < self.limitHistory) {
@ -344,10 +451,18 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
};
self.updateAlias = function() {
var config = configService.getSync();
config.aliasFor = config.aliasFor || {};
self.alias = config.aliasFor[self.walletId];
var fc = profileService.focusedClient;
fc.alias = self.alias;
};
self.updateColor = function() {
var config = configService.getSync();
config.colorFor = config.colorFor || {};
self.backgroundColor = config.colorFor[self.walletId] || '#7A8C9E';
self.backgroundColor = config.colorFor[self.walletId] || '#4A90E2';
var fc = profileService.focusedClient;
fc.backgroundColor = self.backgroundColor;
};
@ -379,6 +494,16 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.lockedBalanceBTC = strip(self.lockedBalanceSat / COIN);
self.availableBalanceBTC = strip(self.availableBalanceBTC / COIN);
// KB to send max
self.feePerKbSat = config.feeValue || 10000;
if (balance.totalKbToSendMax) {
var feeToSendMaxSat = balance.totalKbToSendMax * self.feePerKbSat;
self.availableMaxBalance = strip((self.availableBalanceSat - feeToSendMaxSat) * self.satToUnit);
self.feeToSendMaxStr = profileService.formatAmount(feeToSendMaxSat) + ' ' + self.unitName;
} else {
self.feeToSendMaxStr = null;
}
//STR
self.totalBalanceStr = profileService.formatAmount(self.totalBalanceSat) + ' ' + self.unitName;
@ -389,7 +514,12 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.alternativeIsoCode = config.alternativeIsoCode;
// Check address
self.checkLastAddress(balance.byAddress);
addressService.isUsed(self.walletId, balance.byAddress, function(err, used) {
if (used) {
$log.debug('Address used. Creating new');
$rootScope.$emit('Local/NeedNewAddress');
}
});
rateService.whenAvailable(function() {
@ -413,22 +543,116 @@ angular.module('copayApp.controllers').controller('indexController', function($r
}
};
self.checkLastAddress = function(byAddress, cb) {
storageService.getLastAddress(self.walletId, function(err, addr) {
var used = lodash.find(byAddress, {
address: addr
});
if (used) {
$log.debug('Address ' + addr + ' was used. Cleaning Cache.')
storageService.clearLastAddress(self.walletId, function(err) {
$rootScope.$emit('Local/NeedNewAddress', err);
if (cb) return cb();
this.csvHistory = function() {
function saveFile(name, data) {
var chooser = document.querySelector(name);
chooser.addEventListener("change", function(evt) {
var fs = require('fs');
fs.writeFile(this.value, data, function(err) {
if (err) {
$log.debug(err);
}
});
};
}, false);
chooser.click();
}
function formatDate(date) {
var dateObj = new Date(date);
if (!dateObj) {
$log.debug('Error formating a date');
return 'DateError'
}
if (!dateObj.toJSON()) {
return '';
}
return dateObj.toJSON();
}
function formatString(str) {
if (!str) return '';
if (str.indexOf('"') !== -1) {
//replace all
str = str.replace(new RegExp('"', 'g'), '\'');
}
//escaping commas
str = '\"' + str + '\"';
return str;
}
function getHistory(skip, cb) {
skip = skip || 0;
fc.getTxHistory({
skip: skip,
limit: 100
}, function(err, txs) {
if (err) return cb(err);
if (txs && txs.length > 0) {
allTxs.push(txs);
return getHistory(skip + 100, cb);
}
else {
return cb(null, lodash.flatten(allTxs));
}
});
};
if (isCordova) {
$log.info('Not available on mobile');
return;
}
var isNode = nodeWebkit.isDefined();
var fc = profileService.focusedClient;
if (!fc.isComplete()) return;
var self = this;
var allTxs = [];
$log.debug('Generating CSV from History');
self.setOngoingProcess('generatingCSV', true);
$timeout(function() {
getHistory(null, function(err, txs) {
self.setOngoingProcess('generatingCSV', false);
if (err) {
$log.debug('TxHistory ERROR:', err);
} else {
$log.debug('Wallet Transaction History:', txs);
self.satToUnit = 1 / self.unitToSatoshi;
var data = txs;
var satToBtc = 1 / 100000000;
var filename = 'Copay-' + (self.alias || self.walletName ) + '.csv';
var csvContent = '';
if (!isNode) csvContent = 'data:text/csv;charset=utf-8,';
csvContent += 'Date,Destination,Note,Amount,Currency,Spot Value,Total Value,Tax Type,Category\n';
var _amount;
var dataString;
data.forEach(function(it, index) {
_amount = (it.action == 'sent' ? '-' : '') + (it.amount * satToBtc).toFixed(8);
dataString = formatDate(it.time * 1000) + ',' + formatString(it.addressTo) + ',' + formatString(it.message) + ',' + _amount + ',BTC,,,,';
csvContent += index < data.length ? dataString + "\n" : dataString;
});
if (isNode) {
saveFile('#export_file', csvContent);
}
else {
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", filename);
link.click();
}
}
$rootScope.$apply();
});
});
};
self.clientError = function(err) {
if (isCordova) {
navigator.notification.confirm(
@ -496,49 +720,35 @@ angular.module('copayApp.controllers').controller('indexController', function($r
c.startScan({
includeCopayerBranches: true,
}, function(err) {
if (err) {
if (self.walletId == walletId)
self.setOngoingProcess('scanning', false);
if (err && self.walletId == walletId) {
self.setOngoingProcess('scanning', false);
self.handleError(err);
$rootScope.$apply();
}
});
};
self.setDefaultLanguage = function(setLang) {
var userLang;
if (!setLang) {
userLang = configService.getSync().wallet.settings.defaultLanguage;
if (!userLang) {
// Auto-detect browser language
var androidLang;
self.setUxLanguage = function() {
var userLang = configService.getSync().wallet.settings.defaultLanguage;
if (!userLang) {
// Auto-detect browser language
var androidLang;
if (navigator && navigator.userAgent && (androidLang = navigator.userAgent.match(/android.*\W(\w\w)-(\w\w)\W/i))) {
userLang = androidLang[1];
} else {
// works for iOS and Android 4.x
userLang = navigator.userLanguage || navigator.language;
}
userLang = userLang ? (userLang.split('-', 1)[0] || 'en') : 'en';
if (navigator && navigator.userAgent && (androidLang = navigator.userAgent.match(/android.*\W(\w\w)-(\w\w)\W/i))) {
userLang = androidLang[1];
} else {
// works for iOS and Android 4.x
userLang = navigator.userLanguage || navigator.language;
}
if (userLang != gettextCatalog.getCurrentLanguage()) {
$log.debug('Setting default language: ' + userLang);
gettextCatalog.setCurrentLanguage(userLang);
amMoment.changeLocale(userLang);
}
} else {
configService.set({
wallet: {
settings: {
defaultLanguage: setLang
}
}
}, function() {
gettextCatalog.setCurrentLanguage(setLang);
amMoment.changeLocale(setLang);
});
userLang = userLang ? (userLang.split('-', 1)[0] || 'en') : 'en';
}
self.defaultLanguageIsoCode = setLang || userLang;
if (userLang != gettextCatalog.getCurrentLanguage()) {
$log.debug('Setting default language: ' + userLang);
gettextCatalog.setCurrentLanguage(userLang);
amMoment.changeLocale(userLang);
}
self.defaultLanguageIsoCode = userLang;
self.defaultLanguageName = lodash.result(lodash.find(self.availableLanguages, {
'isoCode': self.defaultLanguageIsoCode
}), 'name');
@ -552,14 +762,59 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
});
$rootScope.$on('Local/AliasUpdated', function(event) {
self.updateAlias();
$timeout(function() {
$rootScope.$apply();
});
});
$rootScope.$on('Local/ProfileBound', function() {
storageService.getRemotePrefsStoredFlag(function(err, val) {
if (err || val) return;
self.updateRemotePreferences({
saveAll: true
}, function() {
$log.debug('Remote preferences saved')
storageService.setRemotePrefsStoredFlag(function() {});
});
});
});
$rootScope.$on('Local/NewFocusedWallet', function() {
self.setUxLanguage();
});
$rootScope.$on('Local/LanguageSettingUpdated', function() {
self.setUxLanguage();
self.updateRemotePreferences({
saveAll: true
}, function() {
$log.debug('Remote preferences saved')
});
});
$rootScope.$on('Local/UnitSettingUpdated', function(event) {
self.updateAll();
self.updateTxHistory();
self.updateRemotePreferences({
saveAll: true
}, function() {
$log.debug('Remote preferences saved')
});
});
$rootScope.$on('Local/EmailSettingUpdated', function(event, email, cb) {
self.updateRemotePreferences({
preferences: {
email: email
},
}, cb);
});
$rootScope.$on('Local/BWSUpdated', function(event) {
profileService.applyConfig();
storageService.setCleanAndScanAddresses(function() {});
});
$rootScope.$on('Local/WalletCompleted', function(event) {
@ -568,7 +823,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
self.debouncedUpdate = lodash.throttle(function() {
self.updateAll();
self.updateAll({
quiet: true
});
self.updateTxHistory();
}, 4000, {
leading: false,
@ -576,31 +833,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
// No need ot listing to Local/Resume since
// reconnection and Local/Online will be triggered
lodash.each(['Local/Online', 'Local/Resume'], function(eventName) {
$rootScope.$on(eventName, function(event) {
$log.debug('### ' + eventName + ' event');
self.debouncedUpdate();
});
});
$rootScope.$on('Local/Online', function(event) {
self.isOffline = false;
self.offLineSince = null;
});
self.offLineSince = null;;
$rootScope.$on('Local/Offline', function(event) {
$log.debug('### Offline event');
if (!self.offLineSince) self.offLineSince = Date.now();
if (Date.now() - self.offLineSince > 10000) {
self.isOffline = true;
$timeout(function() {
$rootScope.$apply();
});
}
$rootScope.$on('Local/Resume', function(event) {
$log.debug('### Resume event');
self.debouncedUpdate();
});
$rootScope.$on('Local/BackupDone', function(event) {
@ -631,13 +866,13 @@ angular.module('copayApp.controllers').controller('indexController', function($r
go.walletHome();
} else if (err && err.cors == 'rejected') {
$log.debug('CORS error:', err);
} else if (err.code === 'ETIMEDOUT') {
} else if (err.code === 'ETIMEDOUT' || err.code === 'CONNERROR') {
$log.debug('Time out:', err);
} else {
var msg = 'Error at Wallet Service: ';
if (err.message) msg = msg + err.message;
else if (err.error) msg = msg + err.error;
else msg = msg + err;
else msg = msg + (lodash.isObject(err) ? JSON.stringify(err) : err);
self.clientError(msg);
}
$rootScope.$apply();
@ -646,59 +881,37 @@ angular.module('copayApp.controllers').controller('indexController', function($r
$rootScope.$on('Local/WalletImported', function(event, walletId) {
self.needsBackup = false;
storageService.setBackupFlag(walletId, function() {
storageService.clearLastAddress(walletId, function(err) {
addressService.expireAddress(walletId, function(err) {
self.startScan(walletId);
});
});
});
$rootScope.$on('Local/DefaultLanguage', function(event, setLang) {
self.setDefaultLanguage(setLang);
});
$rootScope.$on('Animation/Disable', function(event) {
$timeout(function() {
self.slideLeft = false;
self.slideRight = false;
self.slideUp = false;
self.slideDown = false;
}, 400);
});
$rootScope.$on('Animation/SlideLeft', function(event) {
self.slideLeft = true;
});
$rootScope.$on('Animation/SlideRight', function(event) {
self.slideRight = true;
});
$rootScope.$on('Animation/SlideUp', function(event) {
self.slideUp = true;
});
$rootScope.$on('Animation/SlideDown', function(event) {
self.slideDown = true;
});
$rootScope.$on('NewIncomingTx', function() {
self.updateBalance();
$timeout(function() {
self.updateTxHistory();
}, 5000);
self.updateAll({
walletStatus: null,
untilItChanges: true,
triggerTxUpdate: true,
});
});
$rootScope.$on('NewOutgoingTx', function() {
self.updateAll({
walletStatus: null,
untilItChanges: true,
triggerTxUpdate: true,
});
});
// remove transactionProposalRemoved (only for compat)
lodash.each(['NewOutgoingTx', 'NewTxProposal', 'TxProposalFinallyRejected', 'transactionProposalRemoved', 'TxProposalRemoved',
lodash.each(['NewTxProposal', 'TxProposalFinallyRejected', 'TxProposalRemoved',
'Local/NewTxProposal', 'Local/TxProposalAction', 'ScanFinished'
], function(eventName) {
$rootScope.$on(eventName, function() {
self.updateAll();
$timeout(function() {
self.updateTxHistory();
}, 3000);
$rootScope.$on(eventName, function(event, untilItChanges) {
self.updateAll({
walletStatus: null,
untilItChanges: untilItChanges,
triggerTxUpdate: true,
});
});
});
@ -729,6 +942,18 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.setFocusedWallet();
self.updateTxHistory();
go.walletHome();
storageService.getCleanAndScanAddresses(function(err, val) {
if (val) {
$log.debug('Clear last address cache and Scan');
lodash.each(lodash.keys(profileService.walletClients), function(walletId) {
addressService.expireAddress(walletId, function(err) {
self.startScan(walletId);
});
});
storageService.removeCleanAndScanAddresses(function() {});
}
});
});
$rootScope.$on('Local/SetTab', function(event, tab, reset) {

View file

@ -29,30 +29,16 @@ angular.module('copayApp.controllers').controller('paymentUriController',
var satToUnit = 1 / unitToSatoshi;
var unitName = config.unitName;
uri.amount = strip(uri.amount * satToUnit) + ' ' + unitName;
if (uri.amount) {
uri.amount = strip(uri.amount * satToUnit) + ' ' + unitName;
}
uri.network = uri.address.network.name;
return uri;
this.uri = uri;
}
};
this.getWallets = function(network) {
if (!profileService.profile) return;
var config = configService.getSync();
config.colorFor = config.colorFor || {};
var ret = lodash.map(profileService.profile.credentials, function(c) {
return {
m: c.m,
n: c.n,
name: c.walletName,
id: c.walletId,
network: c.network,
color: config.colorFor[c.walletId] || '#2C3E50'
};
});
ret = lodash.filter(ret, function(w) {
return (w.network == network);
});
return lodash.sortBy(ret, 'walletName');
return profileService.getWallets(network);
};
this.selectWallet = function(wid) {

View file

@ -4,6 +4,7 @@ angular.module('copayApp.controllers').controller('preferencesController',
function($scope, $rootScope, $filter, $timeout, $modal, $log, lodash, configService, profileService) {
var config = configService.getSync();
this.unitName = config.wallet.settings.unitName;
this.feeName = config.wallet.settings.feeName || 'Priority';
this.bwsurl = config.bws.url;
this.selectedAlternative = {
name: config.wallet.settings.alternativeName,

View file

@ -0,0 +1,32 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesAliasController',
function($scope, $timeout, configService, profileService, go) {
var config = configService.getSync();
var fc = profileService.focusedClient;
var walletId = fc.credentials.walletId;
var config = configService.getSync();
config.aliasFor = config.aliasFor || {};
this.alias = config.aliasFor[walletId] || fc.credentials.walletName;
this.save = function() {
var self = this;
var opts = {
aliasFor: {}
};
opts.aliasFor[walletId] = self.alias;
configService.set(opts, function(err) {
if (err) {
$scope.$emit('Local/DeviceError', err);
return;
}
$scope.$emit('Local/AliasUpdated');
$timeout(function(){
go.path('preferences');
}, 50);
});
};
});

View file

@ -21,8 +21,7 @@ angular.module('copayApp.controllers').controller('preferencesBwsUrlController',
configService.set(opts, function(err) {
if (err) console.log(err);
$scope.$emit('Local/BWSUpdated');
applicationService.restart(true);
go.walletHome();
applicationService.restart();
});
};

View file

@ -4,14 +4,17 @@ angular.module('copayApp.controllers').controller('preferencesColorController',
function($scope, configService, profileService, go) {
var config = configService.getSync();
this.colorOpts = [
'#7A8C9E',
'#F38F12',
'#F4D03F',
'#FAA77F',
'#FADA58',
'#9EDD72',
'#77DADA',
'#4A90E2',
'#484ED3',
'#9B59B6',
'#E856EF',
'#F883B4',
'#FF599E',
'#7A8C9E',
];
var fc = profileService.focusedClient;
@ -19,7 +22,7 @@ angular.module('copayApp.controllers').controller('preferencesColorController',
var config = configService.getSync();
config.colorFor = config.colorFor || {};
this.color = config.colorFor[walletId] || '#7A8C9E';
this.color = config.colorFor[walletId] || '#4A90E2';
this.save = function(color) {
var self = this;

View file

@ -34,14 +34,15 @@ angular.module('copayApp.controllers').controller('preferencesDeleteWalletContro
var _deleteWallet = function() {
var fc = profileService.focusedClient;
var walletName = fc.credentials.walletName;
var name = fc.credentials.walletName;
var walletName = (fc.alias||'') + ' [' + name + ']';
var self = this;
profileService.deleteWalletFC({}, function(err) {
if (err) {
self.error = err.message || err;
} else {
notification.success(gettext('Success'), gettextCatalog.getString('The wallet "{{walletName}}" was deleted', {walletName: walletName}));
notification.success(gettext('Success'), gettextCatalog.getString('The wallet "{{walletName}}" was deleted', {walletName: name}));
}
});
};

View file

@ -0,0 +1,16 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesEmailController',
function($scope, go, profileService, gettext, $log) {
this.save = function(form) {
var self = this;
this.error = null;
var fc = profileService.focusedClient;
this.saving = true;
$scope.$emit('Local/EmailSettingUpdated', self.email, function() {
self.saving = false;
go.path('preferences');
});
};
});

View file

@ -0,0 +1,38 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesFeeController',
function($rootScope, $scope, configService, go, gettext) {
var config = configService.getSync();
this.feeName = config.wallet.settings.feeName || 'Priority';
this.feeOpts = [{
name: gettext('Priority'),
value: 100,
}, {
name: gettext('Normal'),
value: 50,
}, {
name: gettext('Economy'),
value: 10,
}, {
name: gettext('Emergency'),
red: true,
value: 500,
}, ];
this.save = function(newFee) {
var opts = {
wallet: {
settings: {
feeName: newFee.name,
feeValue: newFee.value * 100,
}
}
};
this.feeName = newFee.name;
configService.set(opts, function(err) {
if (err) console.log(err);
});
};
});

View file

@ -1,12 +1,24 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesLanguageController',
function($scope, $timeout, go) {
function($scope, $log, $timeout, configService, go) {
this.save = function(newLang) {
$scope.$emit('Local/DefaultLanguage', newLang);
$timeout(function() {
go.preferences();
}, 100);
var opts = {
wallet: {
settings: {
defaultLanguage: newLang
}
}
};
configService.set(opts, function(err) {
if (err) $log.warn(err);
$scope.$emit('Local/LanguageSettingUpdated');
$timeout(function() {
go.preferences();
}, 100);
});
};
});

View file

@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesUnitController',
function($rootScope, $scope, configService, go) {
function($rootScope, $scope, $log, configService, go) {
var config = configService.getSync();
this.unitName = config.wallet.settings.unitName;
this.unitOpts = [
@ -51,8 +51,9 @@ angular.module('copayApp.controllers').controller('preferencesUnitController',
this.unitName = newUnit.shortName;
configService.set(opts, function(err) {
if (err) console.log(err);
if (err) $log.warn(err);
$scope.$emit('Local/UnitSettingUpdated');
go.preferences();
});
};

View file

@ -15,13 +15,19 @@ angular.module('copayApp.controllers').controller('sidebarController',
self.setWallets();
});
$rootScope.$on('Local/AliasUpdated', function(event) {
self.setWallets();
});
self.signout = function() {
profileService.signout();
};
self.switchWallet = function(wid) {
self.switchWallet = function(selectedWalletId, currentWalletId) {
if (selectedWalletId == currentWalletId) return;
self.walletSelection = false;
profileService.setAndStoreFocus(wid, function() {
profileService.setAndStoreFocus(selectedWalletId, function() {
});
};
@ -35,16 +41,17 @@ angular.module('copayApp.controllers').controller('sidebarController',
if (!profileService.profile) return;
var config = configService.getSync();
config.colorFor = config.colorFor || {};
config.aliasFor = config.aliasFor || {};
var ret = lodash.map(profileService.profile.credentials, function(c) {
return {
m: c.m,
n: c.n,
name: c.walletName,
name: config.aliasFor[c.walletId] || c.walletName,
id: c.walletId,
color: config.colorFor[c.walletId] || '#7A8C9E',
color: config.colorFor[c.walletId] || '#4A90E2',
};
});
self.wallets = lodash.sortBy(ret, 'walletName');
self.wallets = lodash.sortBy(ret, 'name');
};
self.setWallets();

View file

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog) {
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService) {
var self = this;
$rootScope.hideMenuBar = false;
@ -23,7 +23,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.isRateAvailable = false;
this.showScanner = false;
this.isMobile = isMobile.any();
this.addr = null;
this.addr = {};
var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) {
self.setForm(data);
@ -38,26 +38,19 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
});
var disableAddrListener = $rootScope.$on('Local/NeedNewAddress', function() {
self.setNewAddress();
self.setAddress(true);
});
var disableFocusListener = $rootScope.$on('Local/NewFocusedWallet', function() {
self.addr = null;
self.addr = {};
self.resetForm();
});
var disableOnlineListener = $rootScope.$on('Local/Online', function() {
// This is needed then the apps go to sleep
self.bindTouchDown();
});
var disableResumeListener = $rootScope.$on('Local/Resume', function() {
// This is needed then the apps go to sleep
self.bindTouchDown();
});
var disableTabListener = $rootScope.$on('Local/TabChanged', function(e, tab) {
// This will slow down switch, do not add things here!
switch (tab) {
@ -77,7 +70,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
disableTabListener();
disableFocusListener();
disableResumeListener();
disableOnlineListener();
$rootScope.hideMenuBar = false;
});
@ -90,11 +82,15 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
var parseError = function(err) {
if (!err) return;
if (err.message) {
if (err.message.indexOf('CORS')>=0) {
// TODO : this is not used anymore?
if (err.message.indexOf('CORS') >= 0) {
err.message = gettext('Could not connect wallet service. Check your Internet connexion and your wallet service configuration.');
}
if (err.message.indexOf('TIMEDOUT')>=0) {
if (err.message.indexOf('TIMEDOUT') >= 0) {
err.message = gettext('Wallet service timed out. Check your Internet connexion and your wallet service configuration.');
}
}
@ -123,17 +119,66 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
});
};
$scope.openWalletsModal = function(wallets) {
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.wallets = wallets;
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
$scope.selectWallet = function(walletId, walletName) {
$scope.gettingAddress = true;
$scope.selectedWalletName = walletName;
$timeout(function() {
$scope.$apply();
});
addressService.getAddress(walletId, false, function(err, addr) {
$scope.gettingAddress = false;
if (!err || addr)
$modalInstance.close(addr);
else {
parseError(err);
self.error = err;
$modalInstance.dismiss('cancel');
}
});
};
};
var modalInstance = $modal.open({
templateUrl: 'views/modals/wallets.html',
windowClass: 'full animated slideInUp',
controller: ModalInstanceCtrl,
});
modalInstance.result.finally(function() {
var m = angular.element(document.getElementsByClassName('reveal-modal'));
m.addClass('slideOutDown');
});
modalInstance.result.then(function(addr) {
if (addr) {
self.setForm(addr);
}
});
};
this.openTxpModal = function(tx, copayers) {
var fc = profileService.focusedClient;
var refreshUntilItChanges = false;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.error = null;
$scope.tx = tx;
$scope.amountStr = tx.amountStr;
$scope.feeStr = tx.feeStr;
$scope.alternativeAmountStr = tx.alternativeAmountStr;
$scope.copayers = copayers
$scope.copayerId = fc.credentials.copayerId;
$scope.loading = null;
$scope.color = fc.backgroundColor;
refreshUntilItChanges = false;
$scope.getShortNetworkName = function() {
return fc.credentials.networkName.substring(0, 4);
@ -146,7 +191,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (err.code && err.code == 'BADREQUEST' &&
(eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) {
$scope.tx.removed = true;
$scope.tx.couldRemove = false;
$scope.tx.canBeRemoved = false;
$scope.tx.pendingForUs = false;
$scope.$apply();
return;
@ -190,7 +235,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
return;
};
self.setOngoingProcess(gettext('Signing transaction'));
self.setOngoingProcess(gettext('Signing payment'));
$scope.loading = true;
$scope.error = null;
$timeout(function() {
@ -200,7 +245,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (err) {
$scope.loading = false;
parseError(err);
$scope.error = err.message || gettext('Could not sign transaction. Please try again.');
$scope.error = err.message || gettext('Could not accept payment. Check you connection and try again');
$scope.$digest();
} else {
//if txp has required signatures then broadcast it
@ -208,14 +253,19 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
if (txpHasRequiredSignatures) {
self.setOngoingProcess(gettext('Broadcasting transaction'));
$scope.loading = true;
fc.broadcastTxProposal(txpsi, function(err, txpsb) {
fc.broadcastTxProposal(txpsi, function(err, txpsb, memo) {
self.setOngoingProcess();
$scope.loading = false;
if (err) {
parseError(err);
$scope.error = gettext('Could not broadcast transaction. Please try again.');
$scope.error = gettext('Could not broadcast payment. Check you connection and try again');
$scope.$digest();
} else {
$log.debug('Transaction signed and broadcasted')
if (memo)
$log.info(memo);
refreshUntilItChanges = true;
$modalInstance.close(txpsb);
}
});
@ -229,7 +279,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
};
$scope.reject = function(txp) {
self.setOngoingProcess(gettext('Rejecting transaction'));
self.setOngoingProcess(gettext('Rejecting payment'));
$scope.loading = true;
$scope.error = null;
$timeout(function() {
@ -238,7 +288,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$scope.loading = false;
if (err) {
parseError(err);
$scope.error = err.message || gettext('Could not reject transaction. Please try again.');
$scope.error = err.message || gettext('Could not reject payment. Check you connection and try again');
$scope.$digest();
} else {
$modalInstance.close(txpr);
@ -249,7 +299,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
$scope.remove = function(txp) {
self.setOngoingProcess(gettext('Deleting transaction'));
self.setOngoingProcess(gettext('Deleting payment'));
$scope.loading = true;
$scope.error = null;
$timeout(function() {
@ -260,7 +310,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
// Hacky: request tries to parse an empty response
if (err && !(err.message && err.message.match(/Unexpected/))) {
parseError(err);
$scope.error = err.message || gettext('Could not delete transaction. Please try again.');
$scope.error = err.message || gettext('Could not delete payment proposal. Check you connection and try again');
$scope.$digest();
return;
}
@ -270,18 +320,23 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
};
$scope.broadcast = function(txp) {
self.setOngoingProcess(gettext('Broadcasting transaction'));
self.setOngoingProcess(gettext('Broadcasting Payment'));
$scope.loading = true;
$scope.error = null;
$timeout(function() {
fc.broadcastTxProposal(txp, function(err, txpb) {
fc.broadcastTxProposal(txp, function(err, txpb, memo) {
self.setOngoingProcess();
$scope.loading = false;
if (err) {
parseError(err);
$scope.error = err.message || gettext('Could not send transaction. Please try again.');
$scope.error = err.message || gettext('Could not broadcast payment. Check you connection and try again');
$scope.$digest();
} else {
if (memo)
$log.info(memo);
refreshUntilItChanges = true;
$modalInstance.close(txpb);
}
});
@ -313,69 +368,52 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess();
if (txp) {
txStatus.notify(txp, function() {
$scope.$emit('Local/TxProposalAction');
$scope.$emit('Local/TxProposalAction', refreshUntilItChanges);
});
} else {
$timeout(function() {
$scope.$emit('Local/TxProposalAction');
$scope.$emit('Local/TxProposalAction', refreshUntilItChanges);
}, 100);
}
});
};
// Receive
this.setNewAddress = function() {
var fc = profileService.focusedClient;
self.generatingAddress = true;
fc.createAddress(function(err, addr) {
self.generatingAddress = false;
if (err) {
if (err.error.match(/locked/gi)) {
$log.debug(err.error);
$timeout(function() {
self.setNewAddress();
}, 5000);
} else {
$log.debug('Creating address ERROR:', err);
$scope.$emit('Local/ClientError', err);
$scope.$digest();
}
return;
}
self.addr = addr.address;
storageService.storeLastAddress(fc.credentials.walletId, addr.address, function() {
self.generatingAddress = false;
$scope.$digest();
});
});
};
this.setAddress = function() {
if (self.addr)
return;
this.setAddress = function(forceNew) {
self.addrError = null;
var fc = profileService.focusedClient;
if (!fc)
return;
// Address already set?
if (!forceNew && self.addr[fc.credentials.walletId]) {
return;
}
self.generatingAddress = true;
$timeout(function() {
storageService.getLastAddress(fc.credentials.walletId, function(err, addr) {
if (addr) {
self.addr = addr;
$scope.$digest();
} else {
self.setNewAddress();
addressService.getAddress(fc.credentials.walletId, forceNew, function(err, addr) {
self.generatingAddress = false;
if (err) {
parseError(err);
self.addrError = err.message || gettext('Could not create address. Check you connection and try again');
}
if (addr)
self.addr[fc.credentials.walletId] = addr;
$scope.$digest();
});
});
};
this.copyAddress = function(addr) {
if (isCordova) {
window.cordova.plugins.clipboard.copy('bitcoin:' + addr);
window.cordova.plugins.clipboard.copy(addr);
window.plugins.toast.showShortCenter('Copied to clipboard');
} else if (nodeWebkit.isDefined()) {
nodeWebkit.writeToClipboard(addr);
}
};
@ -388,6 +426,90 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
}
};
this.openCustomizedAmountModal = function(addr) {
var self = this;
var fc = profileService.focusedClient;
var ModalInstanceCtrl = function($scope, $modalInstance) {
$scope.addr = addr;
$scope.color = fc.backgroundColor;
$scope.unitName = self.unitName;
$scope.alternativeAmount = self.alternativeAmount;
$scope.alternativeName = self.alternativeName;
$scope.alternativeIsoCode = self.alternativeIsoCode;
$scope.isRateAvailable = self.isRateAvailable;
$scope.unitToSatoshi = self.unitToSatoshi;
$scope.unitDecimals = self.unitDecimals;
var satToUnit = 1 / self.unitToSatoshi;
$scope.showAlternative = false;
Object.defineProperty($scope,
"_customAlternative", {
get: function() {
return $scope.customAlternative;
},
set: function(newValue) {
$scope.customAlternative = newValue;
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
$scope.customAmount = parseFloat((rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed($scope.unitDecimals), 10);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty($scope,
"_customAmount", {
get: function() {
return $scope.customAmount;
},
set: function(newValue) {
$scope.customAmount = newValue;
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
$scope.customAlternative = parseFloat((rateService.toFiat(newValue * $scope.unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10);
} else {
$scope.customAlternative = 0;
}
$scope.alternativeAmount = $scope.customAlternative;
},
enumerable: true,
configurable: true
});
$scope.submitForm = function(form) {
var satToBtc = 1 / 100000000;
var amount = form.amount.$modelValue;
var amountSat = parseInt((amount * $scope.unitToSatoshi).toFixed(0));
$timeout(function() {
$scope.customizedAmountUnit = amount + ' ' + $scope.unitName;
$scope.customizedAlternativeUnit = $filter('noFractionNumber')(form.alternative.$modelValue, 2) + ' ' + $scope.alternativeIsoCode;
if ($scope.unitName == 'bits') {
amount = (amountSat * satToBtc).toFixed(8);
}
$scope.customizedAmountBtc = amount;
}, 1);
};
$scope.toggleAlternative = function() {
$scope.showAlternative = !$scope.showAlternative;
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
};
var modalInstance = $modal.open({
templateUrl: 'views/modals/customized-amount.html',
windowClass: 'full animated slideInUp',
controller: ModalInstanceCtrl,
});
modalInstance.result.finally(function() {
var m = angular.element(document.getElementsByClassName('reveal-modal'));
m.addClass('slideOutDown');
});
};
// Send
this.canShowAlternative = function() {
@ -520,9 +642,12 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
var fc = profileService.focusedClient;
$log.warn(err);
parseError(err);
var errMessage = 'The transaction' + (fc.credentials.m > 1 ? ' proposal' : '') +
var errMessage =
fc.credentials.m > 1 ? gettext('Could not create payment proposal') : gettext('Could not send payment');
' could not be created: ' + (err.message ? err.message : err);
//This are abnormal situations, but still err message will not be translated
//(the should) we should switch using err.code and use proper gettext messages
errMessage = errMessage + '. ' + (err.message ? err.message : gettext('Check you connection and try again'));
this.error = errMessage;
@ -554,6 +679,11 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.submitForm = function() {
var fc = profileService.focusedClient;
var unitToSat = this.unitToSatoshi;
if (isCordova && this.isWindowsPhoneApp) {
this.hideAddress = false;
this.hideAmount = false;
}
var form = $scope.sendForm;
if (form.$invalid) {
@ -583,6 +713,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
amount: amount,
message: comment,
payProUrl: paypro ? paypro.url : null,
feePerKb: config.feeValue || 10000,
}, function(err, txp) {
if (err) {
self.setOngoingProcess();
@ -591,12 +722,16 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
}
self.signAndBroadcast(txp, function(err) {
if (err) {
self.setOngoingProcess();
return self.setSendError(err);
}
self.setOngoingProcess();
profileService.lockFC();
self.resetForm();
if (err) {
self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen');
$scope.$emit('Local/TxProposalAction');
$timeout(function() {
$scope.$digest();
}, 1);
}
});
});
}, 100);
@ -608,23 +743,26 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
self.setOngoingProcess(gettext('Signing transaction'));
fc.signTxProposal(txp, function(err, signedTx) {
profileService.lockFC();
self.setOngoingProcess();
if (err) {
self.setOngoingProcess();
$log.debug('Sign error:', err);
err.message = gettext('The payment was created but could not be signed. Please try again from home screen.') + (err.message ? ' ' + err.message : '');
return cb(err);
}
if (signedTx.status == 'accepted') {
self.setOngoingProcess(gettext('Broadcasting transaction'));
fc.broadcastTxProposal(signedTx, function(err, btx) {
fc.broadcastTxProposal(signedTx, function(err, btx, memo) {
self.setOngoingProcess();
if (err) {
$scope.error = gettext('Transaction not broadcasted. Please try again.');
$scope.$digest();
err.message = gettext('The payment was signed but could not be broadcasted. Please try again from home screen.') + (err.message ? ' ' + err.message : '');
return cb(err);
}
if (memo)
$log.info(memo);
txStatus.notify(btx, function() {
$scope.$emit('Local/TxProposalAction');
$scope.$emit('Local/TxProposalAction', true);
return cb();
});
});
@ -821,22 +959,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
return this.alternativeIsoCode;
};
this._addRates = function(txs, cb) {
if (!txs || txs.length == 0) return cb();
var index = lodash.groupBy(txs, 'rateTs');
rateService.getHistoricRates(config.alternativeIsoCode, lodash.keys(index), function(err, res) {
if (err || !res) return cb(err);
lodash.each(res, function(r) {
lodash.each(index[r.ts], function(tx) {
var alternativeAmount = (r.rate != null ? tx.amount * rateService.SAT_TO_BTC * r.rate : null);
tx.alternativeAmount = alternativeAmount ? $filter('noFractionNumber')(alternativeAmount, 2) : null;
});
});
return cb();
});
};
this.openTxModal = function(btx) {
var self = this;
var fc = profileService.focusedClient;
@ -886,6 +1008,46 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
return actions.hasOwnProperty('create');
};
this._doSendAll = function(amount) {
this.setForm(null, amount);
};
this.confirmDialog = function(msg, cb) {
if (isCordova) {
navigator.notification.confirm(
msg,
function(buttonIndex) {
if (buttonIndex == 1) {
$timeout(function() {
return cb(true);
}, 1);
} else {
return cb(false);
}
}
);
} else if (isChromeApp) {
// No feedback, alert/confirm not supported.
return cb(true);
} else {
return cb(confirm(msg));
}
};
this.sendAll = function(amount, feeStr) {
var self = this;
var msg = gettextCatalog.getString("{{fee}} will be discounted for bitcoin networking fees", {
fee: feeStr
});
this.confirmDialog(msg, function(confirmed){
if (confirmed)
self._doSendAll(amount);
});
};
/* Start setup */
this.bindTouchDown();
this.setAddress();
this.setSendFormInputs();

View file

@ -6,6 +6,15 @@ angular.element(document).ready(function() {
var startAngular = function() {
angular.bootstrap(document, ['copayApp']);
};
var handleBitcoinURI = function(url) {
if (!url) return;
setTimeout(function() {
window.location = '#/uri-payment/' + url;
}, 1000);
};
/* Cordova specific Init */
if (window.cordova !== undefined) {
@ -26,20 +35,13 @@ angular.element(document).ready(function() {
}, 100);
}, false);
// We are not emitting here, since when the BWS socket reconnects,
// update will be triggered
document.addEventListener('offline', function() {
window.location = '#/cordova/offline';
}, false);
// Back button event
document.addEventListener('backbutton', function() {
var loc = window.location;
if (loc.toString().match(/index\.html#\/$/)) {
navigator.app.exitApp();
}
else {
window.location = '#/walletHome';
navigator.app.exitApp();
} else {
window.location = '#/cordova/walletHome';
}
}, false);
@ -53,13 +55,6 @@ angular.element(document).ready(function() {
navigator.splashscreen.hide();
}, 2000);
function handleBitcoinURI(url) {
if (!url) return;
setTimeout(function() {
window.location = '#/uri-payment/' + url;
}, 1000);
}
window.plugins.webintent.getUri(handleBitcoinURI);
window.plugins.webintent.onNewIntent(handleBitcoinURI);
window.handleOpenURL = handleBitcoinURI;
@ -67,6 +62,13 @@ angular.element(document).ready(function() {
startAngular();
}, false);
} else {
try {
window.handleOpenURL = handleBitcoinURI;
window.plugins.webintent.getUri(handleBitcoinURI);
window.plugins.webintent.onNewIntent(handleBitcoinURI);
} catch (e) {}
startAngular();
}

Some files were not shown because too many files have changed in this diff Show more