Merge branch 'ref/design' of github.com:bitpay/bitpay-wallet into scanHandling

This commit is contained in:
Marty Alcala 2016-10-19 16:36:32 -04:00
commit 01d5e1d2eb
36 changed files with 336 additions and 149 deletions

1
.gitignore vendored
View File

@ -106,6 +106,7 @@ src/js/appConfig.js
src/js/externalServices.js src/js/externalServices.js
chrome-app/manifest.json chrome-app/manifest.json
www/img/app www/img/app
www/index.html
cordova/android/res/ cordova/android/res/

View File

@ -3,7 +3,7 @@
[![Build Status](https://secure.travis-ci.org/bitpay/copay.svg)](http://travis-ci.org/bitpay/copay) [![Build Status](https://secure.travis-ci.org/bitpay/copay.svg)](http://travis-ci.org/bitpay/copay)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/copay/localized.png)](https://crowdin.com/project/copay) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/copay/localized.png)](https://crowdin.com/project/copay)
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) (BWS) for peer synchronization and network interfacing. 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) (BWS) for peer synchronization and network interfacing.
Binary versions of Copay are available for download at [Copay.io](https://copay.io/#download). Copay Binaries are signed with the key `copay@bitpay.com` See the section [`How to Verify Copay Signatures`](https://github.com/bitpay/copay#how-to-verify-copay-signatures) for details. Binary versions of Copay are available for download at [Copay.io](https://copay.io/#download). Copay Binaries are signed with the key `copay@bitpay.com` See the section [`How to Verify Copay Signatures`](https://github.com/bitpay/copay#how-to-verify-copay-signatures) for details.
@ -29,7 +29,9 @@ For a list of frequently asked questions please visit the [Copay FAQ](https://gi
- Multiple languages supported - Multiple languages supported
- Available for [iOS](https://itunes.apple.com/us/app/copay/id951330296), [Android](https://play.google.com/store/apps/details?id=com.bitpay.copay&hl=en), [Windows Phone](http://www.windowsphone.com/en-us/store/app/copay-wallet/4372479b-a064-4d18-8bd3-74a3bdb81c3a), [Chrome App](https://chrome.google.com/webstore/detail/copay/cnidaodnidkbaplmghlelgikaiejfhja?hl=en), [Linux](https://github.com/bitpay/copay/releases/latest), [Windows](https://github.com/bitpay/copay/releases/latest) and [OS X](https://github.com/bitpay/copay/releases/latest) devices - Available for [iOS](https://itunes.apple.com/us/app/copay/id951330296), [Android](https://play.google.com/store/apps/details?id=com.bitpay.copay&hl=en), [Windows Phone](http://www.windowsphone.com/en-us/store/app/copay-wallet/4372479b-a064-4d18-8bd3-74a3bdb81c3a), [Chrome App](https://chrome.google.com/webstore/detail/copay/cnidaodnidkbaplmghlelgikaiejfhja?hl=en), [Linux](https://github.com/bitpay/copay/releases/latest), [Windows](https://github.com/bitpay/copay/releases/latest) and [OS X](https://github.com/bitpay/copay/releases/latest) devices
## Install For Development ## Testing in a Browser
> **Note:** This method should only be used for development purposes. When running Copay in a normal browser environment, browser extensions and other malicious code might have access to internal data and private keys. For production use, see the latest official [releases](https://github.com/bitpay/copay/releases/).
Clone the repo and open the directory: Clone the repo and open the directory:
@ -47,68 +49,83 @@ npm start
Visit [`localhost:3000`](http://localhost:3000/) to view the app. Visit [`localhost:3000`](http://localhost:3000/) to view the app.
> **Note:** This method should only be used for development purposes. When running Copay in a normal browser environment, browser extensions and other malicious code might have access to internal data and private keys. For production use, see the latest official [releases](https://github.com/bitpay/copay/releases/). A watch task is also available to rebuild components of the app as changes are made. This task can be run in a separate process while the server started by `npm start` is running to quickly test changes.
## Build Copay App Bundles ```
npm run watch
```
## Testing on Real Devices
It's recommended that all final testing be done on a real device both to assess performance and to enable features that are unavailable to the emulator (e.g. a device camera).
### Android ### Android
- Install Android SDK Follow the [Cordova Android Platform Guide](https://cordova.apache.org/docs/en/latest/guide/platforms/android/) to set up your development environment.
- Run `make android`
When your developement enviroment is ready, run the `start:android` npm package script.
```sh
npm run apply:copay
npm run start:android
```
### iOS ### iOS
- Install Xcode 6.1 (or newer) Follow the [Cordova iOS Platform Guide](https://cordova.apache.org/docs/en/latest/guide/platforms/android/) to set up your development environment.
- Run `make ios-prod`
##### Notes for Xcode 7.0 When your developement enviroment is ready, run the `start:ios` npm package script.
###### ATS support ```sh
npm run apply:copay
Before starting Copay from Xcode, add these lines to "Custom iOS Target Properties": npm run start:ios
```
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
``` ```
![Example](http://i.stack.imgur.com/nGw3j.png) ### Desktop (Linux, macOS, and Windows)
The desktop version of Copay currently uses NW.js, an app runtime based on Chromium. To get started, first install NW.js on your system from [the NW.js website](https://nwjs.io/).
App Transport Security (ATS) enforces best practices in the secure connections between an app and its back end. [Read complete documentation](https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9.html). When NW.js is installed, run the `start:desktop` npm package script.
###### Invalid Bundle while submitting application
`iPad Multitasking support requires launch story board in bundle`
To fix this problem, add the following:
```sh
npm run apply:copay
npm run start:desktop
``` ```
<key>UIRequiresFullScreen</key>
<string>YES</string> ## Build Copay App Bundles
Before building the release version for a platform, run the `clean-all` command to delete any untracked files in your current working directory. (Be sure to stash any uncommited changes you've made.) This guarantees consistency across builds for the current state of this repository.
The `final` commands build the production version of the app, and bundle it with the release version of the platform being built.
### Android
```sh
npm run clean-all
npm run apply:copay
npm run final:android
``` ```
###### Build settings, headers search path
Add this line to your Build Settings -> Header Search Paths -> Release
"$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include"
### iOS
```sh
npm run clean-all
npm run apply:copay
npm run final:ios
```
### Windows Phone ### Windows Phone
- Install Visual Studio 2013 (or newer) - Install Visual Studio 2013 (or newer)
- Run `make wp8-prod` - Run `make wp8-prod`
### Desktop versions (Windows, OS X, Linux) ### Desktop (Linux, macOS, and Windows)
Copay uses NW.js (also know as node-webkit) for its desktop version. NW.js is an app runtime based on `Chromium` and `node.js`. ```sh
npm run clean-all
- Install NW.js on your system from [nwjs.io](http://nwjs.io/) npm run apply:copay
- Run `grunt desktop` npm run final:desktop
```
### Google Chrome App ### Google Chrome App
@ -116,10 +133,6 @@ Copay uses NW.js (also know as node-webkit) for its desktop version. NW.js is an
On success, the Chrome extension will be located at: `browser-extensions/chrome/copay-chrome-extension`. To install it go to `chrome://extensions/` in your 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. On success, the Chrome extension will be located at: `browser-extensions/chrome/copay-chrome-extension`. To install it go to `chrome://extensions/` in your 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
The Copay Firefox Extension has been deprecated and is no longer supported.
## About Copay ## About Copay
### General ### General

View File

@ -6,6 +6,7 @@
var templates = { var templates = {
'package.json': '/', 'package.json': '/',
'index.html': 'www/',
'Makefile': 'cordova/', 'Makefile': 'cordova/',
'ProjectMakefile': 'cordova/', 'ProjectMakefile': 'cordova/',
'config-template.xml': '/', 'config-template.xml': '/',

View File

@ -75,6 +75,7 @@
<platform name="ios"> <platform name="ios">
<config-file platform="ios" target="*-Info.plist" parent="UIStatusBarHidden"><true/></config-file> <config-file platform="ios" target="*-Info.plist" parent="UIStatusBarHidden"><true/></config-file>
<config-file platform="ios" target="*-Info.plist" parent="UIViewControllerBasedStatusBarAppearance"><false/></config-file> <config-file platform="ios" target="*-Info.plist" parent="UIViewControllerBasedStatusBarAppearance"><false/></config-file>
<config-file target="*-Info.plist" parent="ITSAppUsesNonExemptEncryption"><false/></config-file>
<icon src="resources/*PACKAGENAME*/ios/icon/icon-60@3x.png" width="180" height="180" /> <icon src="resources/*PACKAGENAME*/ios/icon/icon-60@3x.png" width="180" height="180" />
<icon src="resources/*PACKAGENAME*/ios/icon/icon-60.png" width="60" height="60" /> <icon src="resources/*PACKAGENAME*/ios/icon/icon-60.png" width="60" height="60" />
<icon src="resources/*PACKAGENAME*/ios/icon/icon-60@2x.png" width="120" height="120" /> <icon src="resources/*PACKAGENAME*/ios/icon/icon-60@2x.png" width="120" height="120" />

View File

@ -7,7 +7,7 @@
<meta name="msapplication-tap-highlight" content="no"> <meta name="msapplication-tap-highlight" content="no">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">
<link rel="stylesheet" type="text/css" href="css/copay.css"> <link rel="stylesheet" type="text/css" href="css/copay.css">
<title>{{appConfig.nameCase}} - {{appConfig.description}}</title> <title>*USERVISIBLENAME* - *PURPOSELINE*</title>
<link rel="shortcut icon" href="img/app/favicon.ico"> <link rel="shortcut icon" href="img/app/favicon.ico">
</head> </head>
<body> <body>

View File

@ -23,6 +23,9 @@
"frame": true, "frame": true,
"width": 400, "width": 400,
"height": 650, "height": 650,
"min_width": 400,
"max_width": 800,
"min_height": 650,
"position": "center", "position": "center",
"fullscreen": false "fullscreen": false
}, },
@ -95,6 +98,8 @@
"final:www": "npm run build:www-release", "final:www": "npm run build:www-release",
"final:ios": "npm run final:www && npm run build:ios-release && npm run open:ios", "final:ios": "npm run final:www && npm run build:ios-release && npm run open:ios",
"final:android": "npm run final:www && npm run build:android-release && npm run run:android", "final:android": "npm run final:www && npm run build:android-release && npm run run:android",
"final:desktop": "grunt desktop",
"sign:android": "rm -f platforms/android/build/outputs/apk/android-release-signed-aligned.apk; jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../copay.keystore -signedjar platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-unsigned.apk copay_play && ../android-sdk-macosx/build-tools/21.1.1/zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-signed-aligned.apk",
"run:android": "cordova run android --device", "run:android": "cordova run android --device",
"log:android": "adb logcat | grep chromium", "log:android": "adb logcat | grep chromium",
"apply:copay": "cd app-template && node apply.js copay && cordova prepare", "apply:copay": "cd app-template && node apply.js copay && cordova prepare",

View File

@ -10,7 +10,7 @@
"angular-mocks": "1.4.10", "angular-mocks": "1.4.10",
"angular-gettext": "2.2.1", "angular-gettext": "2.2.1",
"angular-moment": "0.10.1", "angular-moment": "0.10.1",
"angular-qrcode": "monospaced/angular-qrcode#~6.2.1", "angular-qrcode": "bitpay/angular-qrcode#~6.3.0",
"ionic": "1.3.1", "ionic": "1.3.1",
"moment": "2.10.3", "moment": "2.10.3",
"ng-lodash": "0.2.3", "ng-lodash": "0.2.3",

View File

@ -1,18 +1,116 @@
{ {
"name": "distribution-not-selected", "//":"Changes to this file will be overwritten",
"description": "Choose a distribution by running 'npm run apply:copay' or 'npm run apply:bitpay'.", "//":" Modify it in the app-template directory",
"primary-package-json": "See the tempate in app-template/package.json",
"scripts": { "name": "bitpay",
"postinstall": "npm run apply:copay && npm install", "description": "Secure Bitcoin Wallet",
"apply:copay": "cd app-template && node apply.js copay", "author": "BitPay",
"apply:bitpay": "cd app-template && node apply.js bitpay" "version": "0.14.0",
"keywords": [
"bitcoin",
"wallet",
"bitpay",
"copay",
"multisignature",
"bitcore"
],
"main": "www/index.html",
"window": {
"title": "BitPay - Secure Bitcoin Wallet",
"icon": "www/img/icon-128.png",
"toolbar": false,
"show": true,
"visible": true,
"resizable": true,
"frame": true,
"width": 400,
"height": 650,
"position": "center",
"fullscreen": false
}, },
"dependencies": { "webkit": {
"fs-extra": "^0.30.0" "page-cache": false,
"java": false,
"plugin": false
}, },
"dom_storage_quota": 200,
"id": "jid1-x7bV5evAaI1P9Q",
"homepage": "https://bitpay.com",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"url": "git://github.com/bitpay/copay.git", "url": "git://github.com/bitpay/bitpay-wallet.git",
"type": "git" "type": "git"
},
"bugs": {
"url": "https://github.com/bitpay/bitpay-wallet/issues"
},
"dependencies": {
"adm-zip": "^0.4.7",
"angular": "1.4.6",
"angular-mocks": "1.4.10",
"bezier-easing": "^2.0.3",
"bhttp": "^1.2.1",
"bitauth": "^0.3.2",
"bitcore-wallet-client": "4.3.2",
"bower": "^1.7.9",
"chai": "^3.5.0",
"cordova-android": "5.1.1",
"cordova-custom-config": "^3.0.5",
"cordova-plugin-qrscanner": "^2.3.1",
"coveralls": "^2.11.9",
"express": "^4.11.2",
"fs": "0.0.2",
"fs-extra": "^0.30.0",
"grunt-angular-gettext": "^2.2.3",
"grunt-browserify": "^5.0.0",
"grunt-cli": "^1.2.0",
"grunt-contrib-compress": "^1.3.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-uglify": "^2.0.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-exec": "^1.0.0",
"grunt-nw-builder": "^2.0.3",
"grunt-sass": "^1.2.0",
"load-grunt-tasks": "^3.5.0",
"mocha": "^2.4.5",
"phantomjs-prebuilt": "^2.1.7",
"shelljs": "^0.3.0"
},
"scripts": {
"preinstall": "bower install && npm install fs-extra",
"postinstall": "echo && echo \"To finish, choose a distribution by running 'npm run apply:copay' or 'npm run apply:bitpay'.\" && echo",
"start": "npm run build:www && ionic serve --nolivereload --nogulp -s",
"start:ios": "npm run build:www && npm run build:ios && npm run open:ios",
"start:android": "npm run build:www && npm run build:android && npm run run:android",
"start:desktop": "grunt desktop",
"watch": "grunt watch",
"build:www": "grunt",
"build:www-release": "grunt prod",
"build:ios": "cordova prepare ios && cordova build ios --debug",
"build:android": "cordova prepare android && cordova build android --debug",
"build:ios-release": "cordova prepare ios && cordova build ios --release",
"build:android-release": "cordova prepare android && cordova build android --release",
"open:ios": "open platforms/ios/*.xcodeproj",
"open:android": "open -a open -a /Applications/Android\\ Studio.app platforms/android",
"final:www": "npm run build:www-release",
"final:ios": "npm run final:www && npm run build:ios-release && npm run open:ios",
"final:android": "npm run final:www && npm run build:android-release && npm run run:android",
"final:desktop": "grunt desktop",
"sign:android": "rm -f platforms/android/build/outputs/apk/android-release-signed-aligned.apk; jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../copay.keystore -signedjar platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-unsigned.apk copay_play && ../android-sdk-macosx/build-tools/21.1.1/zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-signed-aligned.apk",
"run:android": "cordova run android --device",
"log:android": "adb logcat | grep chromium",
"apply:copay": "cd app-template && node apply.js copay && cordova prepare",
"apply:bitpay": "cd app-template && node apply.js bitpay && cordova prepare",
"test": "./node_modules/.bin/grunt test-coveralls",
"clean": "trash platforms && trash plugins && cordova prepare",
"clean-all": "git clean -dfx && npm install"
},
"devDependencies": {
"cordova": "^6.3.1",
"grunt": "^1.0.1",
"ionic": "^2.1.0",
"trash-cli": "^1.4.0",
"lodash": "^4.3.0"
} }
} }

View File

@ -139,7 +139,6 @@ angular.module('copayApp.controllers').controller('buyGlideraController',
$scope.wallets = profileService.getWallets({ $scope.wallets = profileService.getWallets({
network: $scope.network, network: $scope.network,
n: 1,
onlyComplete: true onlyComplete: true
}); });
}); });

View File

@ -1,14 +1,29 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('notificationsController', function($scope, $state, $timeout, $stateParams, $ionicConfig, profileService, configService) { angular.module('copayApp.controllers').controller('notificationsController', function($scope, $state, $timeout, $stateParams, $ionicConfig, profileService, configService, $interval) {
$ionicConfig.views.swipeBackEnabled(false); $ionicConfig.views.swipeBackEnabled(false);
$scope.walletId = $stateParams.walletId; $scope.walletId = $stateParams.walletId;
$scope.allowNotif = function() { $scope.allowNotif = function() {
$scope.notificationDialogOpen = true;
$timeout(function() { $timeout(function() {
profileService.pushNotificationsInit(); profileService.pushNotificationsInit();
}); });
$scope.notificationPromise = $interval(function() {
PushNotification.hasPermission(function(data) {
if (data.isEnabled) {
$interval.cancel($scope.notificationPromise);
$state.go('onboarding.backupRequest', {
walletId: $scope.walletId
});
}
});
}, 100);
}
$scope.continue = function() {
$interval.cancel($scope.notificationPromise);
$state.go('onboarding.backupRequest', { $state.go('onboarding.backupRequest', {
walletId: $scope.walletId walletId: $scope.walletId
}); });

View File

@ -113,10 +113,13 @@ angular.module('copayApp.directives')
} }
} }
}) })
.directive('contact', ['addressbookService', 'lodash', .directive('contact', ['addressbookService', 'lodash', 'gettextCatalog',
function(addressbookService, lodash) { function(addressbookService, lodash, gettextCatalog) {
return { return {
restrict: 'E', restrict: 'E',
scope: {
label: '='
},
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
var addr = attrs.address; var addr = attrs.address;
addressbookService.get(addr, function(err, ab) { addressbookService.get(addr, function(err, ab) {
@ -124,7 +127,11 @@ angular.module('copayApp.directives')
var name = lodash.isObject(ab) ? ab.name : ab; var name = lodash.isObject(ab) ? ab.name : ab;
element.append(name); element.append(name);
} else { } else {
element.append(addr); if (scope.label && scope.label == 'Sent') {
element.append(gettextCatalog.getString('Sent'));
} else {
element.append(addr);
}
} }
}); });
} }

View File

@ -12,9 +12,10 @@ angular.module('copayApp.directives')
email: '@' email: '@'
}, },
link: function(scope, el, attr) { link: function(scope, el, attr) {
scope.emailHash = md5.createHash(scope.email || ''); if(typeof scope.email === "string"){
scope.emailHash = md5.createHash(scope.email.toLowerCase() || '');
}
}, },
template: '<img class="gravatar" alt="{{ name }}" height="{{ height }}" width="{{ width }}" src="https://secure.gravatar.com/avatar/{{ emailHash }}.jpg?s={{ width }}&d=mm">' template: '<img class="gravatar" alt="{{ name }}" height="{{ height }}" width="{{ width }}" src="https://secure.gravatar.com/avatar/{{ emailHash }}.jpg?s={{ width }}&d=mm">'
} }
}); });

View File

@ -23,10 +23,10 @@ angular.module('copayApp.services').factory('configService', function(storageSer
reconnectDelay: 5000, reconnectDelay: 5000,
idleDurationMin: 4, idleDurationMin: 4,
settings: { settings: {
unitName: 'bits', unitName: 'BTC',
unitToSatoshi: 100, unitToSatoshi: 100,
unitDecimals: 2, unitDecimals: 2,
unitCode: 'bit', unitCode: 'btc',
alternativeName: 'US Dollar', alternativeName: 'US Dollar',
alternativeIsoCode: 'USD', alternativeIsoCode: 'USD',
} }

View File

@ -601,6 +601,16 @@ angular.module('copayApp.services')
$log.debug('Importing Wallet:', opts); $log.debug('Importing Wallet:', opts);
try { try {
var c = JSON.parse(str);
if (c.xPrivKey && c.xPrivKeyEncrypted) {
$log.warn('Found both encrypted and decrypted key. Deleting the encrypted version');
delete c.xPrivKeyEncrypted;
delete c.mnemonicEncrypted;
}
str = JSON.stringify(c);
walletClient.import(str, { walletClient.import(str, {
compressed: opts.compressed, compressed: opts.compressed,
password: opts.password password: opts.password
@ -609,14 +619,6 @@ angular.module('copayApp.services')
return cb(gettext('Could not import. Check input file and spending password')); return cb(gettext('Could not import. Check input file and spending password'));
} }
str = JSON.parse(str);
if (str.xPrivKey && str.xPrivKeyEncrypted) {
$log.warn('Found both encrypted and decrypted key. Deleting the encrypted version');
delete str.xPrivKeyEncrypted;
delete str.mnemonicEncrypted;
}
var addressBook = str.addressBook || {}; var addressBook = str.addressBook || {};
addAndBindWalletClient(walletClient, { addAndBindWalletClient(walletClient, {

View File

@ -52,6 +52,9 @@
position: absolute; position: absolute;
bottom: 254px; bottom: 254px;
top: 66px; top: 66px;
.light {
color: #A4A4A4;
}
} }
} }
@ -84,7 +87,8 @@
.operator-send { .operator-send {
font-weight: bolder; font-weight: bolder;
background-color: #f7f7f7; color: #f8f8f8;
background-color: #1e3186;
font-size: 36px; font-size: 36px;
cursor: pointer; cursor: pointer;

View File

@ -1,6 +1,5 @@
#tab-home { #tab-home {
.icon-create-wallet { .icon-create-wallet {
background-image: url("../img/icon-wallet.svg");
background-color: #4A90E2; // default wallet color background-color: #4A90E2; // default wallet color
} }
.icon-buy-bitcoin { .icon-buy-bitcoin {
@ -16,19 +15,17 @@
.icon-amazon { .icon-amazon {
background-image: url("../img/icon-amazon.svg"); background-image: url("../img/icon-amazon.svg");
} }
.bg {
&.wallet{
padding: .25rem
}
}
.card{ .card{
.item { .item {
color: #444; color: #444;
border-top:none; border-top:none;
padding-bottom: 1.5rem; padding-bottom: 1.5rem;
padding-top:1.5rem; padding-top:1.5rem;
&.wallet{
.big-icon-svg{
& > .bg{
padding: .25rem
}
}
}
} }
.item-sub { .item-sub {
&:first-child:before { &:first-child:before {

View File

@ -1,3 +1,30 @@
.wallet-details {
&__tx-amount {
font-size: 16px;
&--recent {
color: $mid-gray;
font-weight: bold;
}
&--received {
color: #30af6c;
}
&--sent {
color: $dark-gray;
}
}
&__tx-time {
color: $light-gray;
}
&__tx-title {
padding-top: 10px;
color: $dark-gray;
}
&__tx-icon {
float: left;
margin-right: 10px;
}
}
#walletDetails { #walletDetails {
.bar-header { .bar-header {
border: 0; border: 0;
@ -31,23 +58,8 @@
.item.item-footer { .item.item-footer {
font-weight: lighter; font-weight: lighter;
} }
} .tx-search:before {
font-size: 22px !important;
.wallet-details-release {
cursor: pointer;
cursor: hand;
background-color: #E9E9EC;
margin-top: -30px;
margin-bottom: 5px;
padding-top: 30px;
padding-bottom: 20px;
text-align: center;
text-color: #444;
span {
margin-left: 15px;
}
i {
margin-right: 15px;
} }
} }

11
www/img/icon-tx-moved.svg Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.8;fill:#F2F2F2;enable-background:new ;}
.st1{fill:none;stroke:#BEBEBE;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
</style>
<ellipse transform="matrix(0.7071 -0.7071 0.7071 0.7071 -7.0416 17)" class="st0" cx="17" cy="17" rx="16.5" ry="16.5"/>
<path class="st1" d="M22.7,16.9H11.1 M18,21.9l4.9-5l-4.8-4.9"/>
</svg>

After

Width:  |  Height:  |  Size: 707 B

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.8;fill:#EFFEF6;enable-background:new ;}
.st1{fill:none;stroke:#7FB197;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
</style>
<ellipse transform="matrix(0.7071 -0.7071 0.7071 0.7071 -7.0416 17)" class="st0" cx="17" cy="17" rx="16.5" ry="16.5"/>
<path class="st1" d="M17.2,25.6V8.1 M9.6,18.5l7.4,7.4l7.3-7.1"/>
</svg>

After

Width:  |  Height:  |  Size: 708 B

11
www/img/icon-tx-sent.svg Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 34 34" style="enable-background:new 0 0 34 34;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.8;fill:#F2F2F2;enable-background:new ;}
.st1{fill:none;stroke:#BEBEBE;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
</style>
<path class="st0" d="M5.3,28.7c-6.4-6.4-6.4-16.9,0-23.3s16.9-6.4,23.3,0s6.4,16.9,0,23.3S11.8,35.1,5.3,28.7z"/>
<path class="st1" d="M17.2,9.4v16.5 M9.6,15.5l7.4-7.4l7.3,7.1"/>
</svg>

After

Width:  |  Height:  |  Size: 700 B

View File

@ -35,15 +35,14 @@
</div> </div>
<div class="amount"> <div class="amount">
<div class="text-light text-black m15b" ng-class="{'size-28': smallFont, 'size-36': !smallFont}"><span> {{amount || "0.00" }}</div> <div class="text-light text-black m15b" ng-class="{'size-28': smallFont, 'size-36': !smallFont, 'light': !amount}"><span>{{amount || "0.00" }}</div>
<div class="text-light text-black" ng-class="{'size-16': smallFont, 'size-17': !smallFont}" ng-show="!showAlternativeAmount"> <div class="text-light text-black" ng-class="{'size-16': smallFont, 'size-17': !smallFont, 'light': !amountResult}" ng-show="!showAlternativeAmount">
{{globalResult}} <span class="label gray text-white radius">{{amountResult || '0.00'}} {{alternativeIsoCode}}</span> {{globalResult}} <span class="label gray text-white radius">{{amountResult || '0.00'}} {{alternativeIsoCode}}</span>
</div> </div>
<div class="text-light text-black size-17" ng-show="showAlternativeAmount"> <div class="text-light text-black size-17" ng-show="showAlternativeAmount">
{{globalResult}} <span class="label gray text-white radius">{{alternativeResult || '0.00'}} {{unitName}}</span> {{globalResult}} <span class="label gray text-white radius">{{alternativeResult || '0.00'}} {{unitName}}</span>
</div> </div>
</div> </div>
</div> </div>
<div class="keypad"> <div class="keypad">

View File

@ -33,7 +33,7 @@
ng-submit="buy.confirm()" ng-submit="buy.confirm()"
novalidate> novalidate>
<div class="card list"> <div class="list card">
<label class="item item-input item-stacked-label"> <label class="item item-input item-stacked-label">
<span class="input-label">Amount</span> <span class="input-label">Amount</span>
<input type="number" <input type="number"

View File

@ -32,7 +32,7 @@
<form name="buyPriceForm" ng-if="token" <form name="buyPriceForm" ng-if="token"
ng-submit="buy.get2faCode(token)" novalidate> ng-submit="buy.get2faCode(token)" novalidate>
<div class="card list"> <div class="list card">
<label class="item item-input item-stacked-label"> <label class="item item-input item-stacked-label">
<span class="input-label">Amount in {{showAlternative ? 'USD' : 'BTC'}}</span> <span class="input-label">Amount in {{showAlternative ? 'USD' : 'BTC'}}</span>
<input ng-show="!showAlternative" <input ng-show="!showAlternative"
@ -66,7 +66,7 @@
<wallets ng-if="wallets[0]" wallets="wallets"></wallets> <wallets ng-if="wallets[0]" wallets="wallets"></wallets>
<div class="text-center text-gray size-12 m20b" ng-show="!buy.gettingBuyPrice && buy.buyPrice.qty"> <div class="text-center text-gray size-12 m20v" ng-show="!buy.gettingBuyPrice && buy.buyPrice.qty">
Buy Buy
<span ng-show="qty">{{buy.buyPrice.subtotal|currency:'':2}} {{buy.buyPrice.currency}} in Bitcoin</span> <span ng-show="qty">{{buy.buyPrice.subtotal|currency:'':2}} {{buy.buyPrice.currency}} in Bitcoin</span>
<span ng-show="fiat">{{buy.buyPrice.qty}} BTC</span> <span ng-show="fiat">{{buy.buyPrice.qty}} BTC</span>
@ -96,7 +96,7 @@
</p> </p>
<form name="buyForm" <form name="buyForm"
ng-submit="buy.sendRequest(token, permissions, twoFaCode)" novalidate> ng-submit="buy.sendRequest(token, permissions, twoFaCode)" novalidate>
<div class="card list"> <div class="list card">
<label class="item item-input"> <label class="item item-input">
<input type="number" ng-model="twoFaCode" placeholder="2FA Code" required ignore-mouse-wheel> <input type="number" ng-model="twoFaCode" placeholder="2FA Code" required ignore-mouse-wheel>
</label> </label>
@ -106,12 +106,12 @@
Buy Buy
</button> </button>
</form> </form>
<p class="m10t size-12 text-gray"> <p class="m10t size-12 text-gray padding">
Fiat will be immediately withdrawn from your bank account. The bitcoins will be purchased and deposited to your wallet in 2-4 business days. Fiat will be immediately withdrawn from your bank account. The bitcoins will be purchased and deposited to your wallet in 2-4 business days.
</p> </p>
</div> </div>
</div> </div>
<div class="text-center" ng-show="buy.success"> <div class="text-center padding" ng-show="buy.success">
<h1>Purchase initiated</h1> <h1>Purchase initiated</h1>
<p class="text-gray"> <p class="text-gray">
A transfer has been initiated from your bank account. Your bitcoins should arrive to your wallet in 2-4 business days. A transfer has been initiated from your bank account. Your bitcoins should arrive to your wallet in 2-4 business days.

View File

@ -18,7 +18,7 @@
Share this invitation with your copayers Share this invitation with your copayers
</div> </div>
<div class="item text-center" copy-to-clipboard="secret" ng-click="copySecret()"> <div class="item text-center" copy-to-clipboard="secret" ng-click="copySecret()">
<qrcode size="220" error-correction-level="L" data="{{secret}}"></qrcode> <qrcode size="220" error-correction-level="L" data="{{secret}}" color="#334"></qrcode>
<div ng-show="!secret" style="position:relative; top:-226px; height:0px"> <div ng-show="!secret" style="position:relative; top:-226px; height:0px">
<div style="height:220px; width:220px; margin:auto; background: white"> <div style="height:220px; width:220px; margin:auto; background: white">
<ion-spinner class="spinner-dark" icon="lines"></ion-spinner> <ion-spinner class="spinner-dark" icon="lines"></ion-spinner>

View File

@ -52,7 +52,7 @@
</div> </div>
<div ng-show="showOauthForm"> <div ng-show="showOauthForm">
<form name="oauthCodeForm" ng-submit="glidera.submitOauthCode(code)" novalidate> <form name="oauthCodeForm" ng-submit="glidera.submitOauthCode(code)" novalidate>
<div class="card list"> <div class="list">
<label class="item item-input item-stacked-label"> <label class="item item-input item-stacked-label">
<span class="input-label">OAuth Code</span> <span class="input-label">OAuth Code</span>
<input type="text" <input type="text"

View File

@ -1,5 +1,5 @@
<ion-modal-view ng-controller="customAmountController"> <ion-modal-view ng-controller="customAmountController">
<ion-header-bar align-title="center" class="tab-bar" ng-style="{'background-color':color}"> <ion-header-bar align-title="center" class="tab-bar" ng-style="{'background-color':color, 'border-color': color}">
<div class="left-small"> <div class="left-small">
<a ng-click="cancel()" class="p10"> <a ng-click="cancel()" class="p10">
<span class="text-close" translate>Close</span> <span class="text-close" translate>Close</span>
@ -14,7 +14,7 @@
<h4 class="title m0" translate>QR Code</h4> <h4 class="title m0" translate>QR Code</h4>
<ul class="no-bullet size-14 m0"> <ul class="no-bullet size-14 m0">
<li class="line-b p10 oh text-center"> <li class="line-b p10 oh text-center">
<qrcode size="220" data="bitcoin:{{addr + '?amount=' + customizedAmountBtc}}"></qrcode> <qrcode size="220" data="bitcoin:{{addr + '?amount=' + customizedAmountBtc}}" color="#334"></qrcode>
<div class="m10t text-center" ng-show="isCordova"> <div class="m10t text-center" ng-show="isCordova">
<span class="button outline dark-gray tiny round" <span class="button outline dark-gray tiny round"
ng-click="shareAddress('bitcoin:' + addr + '?amount=' + customizedAmountBtc)"> ng-click="shareAddress('bitcoin:' + addr + '?amount=' + customizedAmountBtc)">

View File

@ -1,5 +1,5 @@
<ion-modal-view ng-controller="payproController"> <ion-modal-view ng-controller="payproController">
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color}"> <ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color, 'border-color': color}">
<button class="button button-clear" ng-click="cancel()"> <button class="button button-clear" ng-click="cancel()">
{{'Close' | translate}} {{'Close' | translate}}
</button> </button>

View File

@ -1,5 +1,5 @@
<ion-modal-view> <ion-modal-view>
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color':color}"> <ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color':color, 'border-color': color}">
<button class="button button-clear" ng-click="close()"> <button class="button button-clear" ng-click="close()">
Close Close
</button> </button>

View File

@ -1,5 +1,5 @@
<ion-modal-view ng-controller="txDetailsController" ng-init="init()" id="tx-details"> <ion-modal-view ng-controller="txDetailsController" ng-init="init()" id="tx-details">
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color}"> <ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color, 'border-color': color}">
<button class="button button-clear" ng-click="cancel()"> <button class="button button-clear" ng-click="cancel()">
{{'Close' | translate}} {{'Close' | translate}}
</button> </button>
@ -72,7 +72,7 @@
<div ng-show="btx.hasMultiplesOutputs" class="item item-icon-right item-heading" ng-click="showMultiplesOutputs = !showMultiplesOutputs"> <div ng-show="btx.hasMultiplesOutputs" class="item item-icon-right item-heading" ng-click="showMultiplesOutputs = !showMultiplesOutputs">
{{'Recipients'|translate}} {{'Recipients'|translate}}
[ {{btx.recipientCount}} ] [ {{btx.recipientCount}} ]
<i class="icon bp-arrow-up" ng-show="showMultiplesOutputs"></i> <i class="icon bp-arrow-up" ng-show="showMultiplesOutputs"></i>
<i class="icon bp-arrow-down" ng-show="!showMultiplesOutputs"></i> <i class="icon bp-arrow-down" ng-show="!showMultiplesOutputs"></i>
</div> </div>

View File

@ -4,8 +4,9 @@
<div class="onboarding-description" translate>Would you like to receive push notifications about payments?</div> <div class="onboarding-description" translate>Would you like to receive push notifications about payments?</div>
<div class="onboarding-illustration-notifications"></div> <div class="onboarding-illustration-notifications"></div>
<div id="cta-buttons"> <div id="cta-buttons">
<button class="button button-standard button-primary" ng-click="allowNotif()" translate>Allow notifications</button> <button class="button button-standard button-primary" ng-click="allowNotif()" translate ng-if="!notificationDialogOpen">Allow notifications</button>
<button class="button button-standard button-secondary button-clear" ng-click="disableNotif()" translate>Not now</button> <button class="button button-standard button-secondary button-clear" ng-click="disableNotif()" translate ng-if="!notificationDialogOpen">Not now</button>
<button class="button button-standard button-primary" ng-click="continue()" translate ng-if="notificationDialogOpen">Continue</button>
</div> </div>
</ion-content> </ion-content>
</ion-view> </ion-view>

View File

@ -6,7 +6,7 @@
</ion-nav-bar> </ion-nav-bar>
<ion-content> <ion-content>
<div class="card list"> <div class="list">
<label class="item item-input item-stacked-label no-border"> <label class="item item-input item-stacked-label no-border">
<span class="input-label">Wallet Service URL</span> <span class="input-label">Wallet Service URL</span>
<input type="text" id="bwsurl" type="text" name="bwsurl" ng-model="bwsurl.value"> <input type="text" id="bwsurl" type="text" name="bwsurl" ng-model="bwsurl.value">

View File

@ -31,7 +31,7 @@
<form name="sellPriceForm" ng-if="token" <form name="sellPriceForm" ng-if="token"
ng-submit="sell.get2faCode(token)" novalidate> ng-submit="sell.get2faCode(token)" novalidate>
<div class="card list"> <div class="list card">
<label class="item item-input item-stacked-label"> <label class="item item-input item-stacked-label">
<span class="input-label"><span>Amount in</span> {{showAlternative ? 'USD' : 'BTC'}}</span> <span class="input-label"><span>Amount in</span> {{showAlternative ? 'USD' : 'BTC'}}</span>
<input ng-show="!showAlternative" <input ng-show="!showAlternative"
@ -65,7 +65,7 @@
<wallets ng-if="wallets[0]" wallets="wallets"></wallets> <wallets ng-if="wallets[0]" wallets="wallets"></wallets>
<div class="text-center text-gray size-12 m20b" ng-show="!sell.gettingSellPrice && sell.sellPrice.qty"> <div class="text-center text-gray size-12 m20v" ng-show="!sell.gettingSellPrice && sell.sellPrice.qty">
Sell Sell
<span ng-show="qty">{{sell.sellPrice.subtotal|currency:'':2}} {{sell.sellPrice.currency}} in Bitcoin</span> <span ng-show="qty">{{sell.sellPrice.subtotal|currency:'':2}} {{sell.sellPrice.currency}} in Bitcoin</span>
<span ng-show="fiat">{{sell.sellPrice.qty}} BTC</span> <span ng-show="fiat">{{sell.sellPrice.qty}} BTC</span>
@ -96,7 +96,7 @@
</p> </p>
<form name="sellForm" <form name="sellForm"
ng-submit="sell.createTx(token, permissions, twoFaCode)" novalidate> ng-submit="sell.createTx(token, permissions, twoFaCode)" novalidate>
<div class="card list"> <div class="list card">
<label class="item item-input"> <label class="item item-input">
<input type="number" ng-model="twoFaCode" placeholder="2FA Code" required ignore-mouse-wheel> <input type="number" ng-model="twoFaCode" placeholder="2FA Code" required ignore-mouse-wheel>
</label> </label>
@ -107,12 +107,12 @@
Sell Sell
</button> </button>
</form> </form>
<p class="m10t size-12 text-gray"> <p class="m10t size-12 text-gray padding">
Bitcoins will be immediately sent from your wallet to Glidera. Fiat will be deposited in your bank account in 4-6 business days. Bitcoins will be immediately sent from your wallet to Glidera. Fiat will be deposited in your bank account in 4-6 business days.
</p> </p>
</div> </div>
</div> </div>
<div class="text-center" ng-show="sell.success"> <div class="text-center padding" ng-show="sell.success">
<h1>Sale initiated</h1> <h1>Sale initiated</h1>
<p class="text-gray"> <p class="text-gray">
A transfer has been initiated to your bank account and should arrive in 4-6 business days. A transfer has been initiated to your bank account and should arrive in 4-6 business days.

View File

@ -1,6 +1,6 @@
<div class="list" ng-show="formData.supported"> <div class="list" ng-show="formData.supported">
<div class="text-center m20t"> <div class="text-center m20t">
<qrcode size="220" version="8" error-correction-level="M" data="{{formData.exportWalletInfo}}"></qrcode> <qrcode size="220" version="8" error-correction-level="M" data="{{formData.exportWalletInfo}}" color="#334"></qrcode>
</div> </div>
<div class="text-center size-12 m20v" translate>From the destination device, go to Add wallet &gt; Import wallet and scan this QR code</div> <div class="text-center size-12 m20v" translate>From the destination device, go to Add wallet &gt; Import wallet and scan this QR code</div>
</div> </div>

View File

@ -61,7 +61,7 @@
<div> <div>
<a ng-if="!wallets[0]" ui-sref="tabs.add" class="item item-icon-left item-big-icon-left item-icon-right next-step"> <a ng-if="!wallets[0]" ui-sref="tabs.add" class="item item-icon-left item-big-icon-left item-icon-right next-step">
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
<div class="bg icon-create-wallet"></div> <img src="img/icon-wallet.svg" class="bg wallet icon-create-wallet"/>
</i> </i>
<span translate>Create a bitcoin wallet</span> <span translate>Create a bitcoin wallet</span>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>
@ -70,7 +70,7 @@
class="item item-sub item-icon-left item-big-icon-left item-icon-right wallet" class="item item-sub item-icon-left item-big-icon-left item-icon-right wallet"
ng-click="openWallet(wallet)"> ng-click="openWallet(wallet)">
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg"/> <img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg wallet"/>
</i> </i>
<span> <span>
{{wallet.name || wallet.id}} {{wallet.name || wallet.id}}

View File

@ -53,7 +53,7 @@
</div> </div>
<div class="row qr"> <div class="row qr">
<div class="text-center col center-block" copy-to-clipboard="addr"> <div class="text-center col center-block" copy-to-clipboard="addr">
<qrcode ng-if="addr" size="220" data="bitcoin:{{addr}}"></qrcode> <qrcode ng-if="addr" size="220" data="bitcoin:{{addr}}" color="#334"></qrcode>
<div ng-if="!addr" style="height:225px; width:220px; margin:auto; background: white; padding-top: 25%;"> <div ng-if="!addr" style="height:225px; width:220px; margin:auto; background: white; padding-top: 25%;">
... ...
</div> </div>

View File

@ -4,8 +4,8 @@
<ion-nav-back-button> <ion-nav-back-button>
</ion-nav-back-button> </ion-nav-back-button>
<ion-nav-buttons side="secondary"> <ion-nav-buttons side="secondary">
<button class="button back-button" ng-click="startSearch(); openSearchModal()"> <button class="button back-button" ng-click="startSearch(); openSearchModal()" ng-if="txHistory.length > 4">
<i class="icon ion-ios-search-strong"></i> <i class="icon ion-ios-search-strong tx-search"></i>
</button> </button>
</ion-nav-buttons> </ion-nav-buttons>
</ion-nav-bar> </ion-nav-bar>
@ -91,7 +91,7 @@
</div> </div>
<div class="card list" ng-if="txps[0]"> <div class="list" ng-if="txps[0]">
<div class="item item-heading" translate> <div class="item item-heading" translate>
<span ng-show="requiresMultipleSignatures" translate>Payment Proposals</span> <span ng-show="requiresMultipleSignatures" translate>Payment Proposals</span>
<span ng-show="!requiresMultipleSignatures" translate>Unsent transactions</span> <span ng-show="!requiresMultipleSignatures" translate>Unsent transactions</span>
@ -125,12 +125,11 @@
</div> </div>
</div> </div>
<div class="card list" ng-show="txHistory[0]"> <div class="list" ng-show="txHistory[0]">
<div class="item" ng-repeat="btx in txHistory track by $index" ng-click="openTxModal(btx)"> <div class="item" ng-repeat="btx in txHistory track by $index" ng-click="openTxModal(btx)">
<span class="item-note text-right"> <span class="item-note text-right">
<span class="size-16" ng-class="{'text-bold': btx.recent}"> <span class="wallet-details__tx-amount" ng-class="{'wallet-details__tx-amount--recent': btx.recent, 'wallet-details__tx-amount--received': btx.action == 'received', 'wallet-details__tx-amount--sent': btx.action == 'sent'}">
<span ng-if="btx.action == 'received'">+</span> <span ng-if="btx.action == 'sent'"></span>
<span ng-if="btx.action == 'sent'">-</span>
<span class="size-12" ng-if="btx.action == 'invalid'" translate> <span class="size-12" ng-if="btx.action == 'invalid'" translate>
(possible double spend) (possible double spend)
</span> </span>
@ -139,42 +138,41 @@
</span> </span>
</span> </span>
<p> <p>
<time ng-if="btx.time">{{btx.time * 1000 | amTimeAgo}}</time> <time class="wallet-details__tx-time" ng-if="btx.time">{{btx.time * 1000 | amTimeAgo}}</time>
<span translate class="text-warning" <span translate class="text-warning"
ng-show="!btx.time && (!btx.confirmations || btx.confirmations == 0)"> ng-show="!btx.time && (!btx.confirmations || btx.confirmations == 0)">
Unconfirmed Unconfirmed
</span> </span>
</p> </p>
</span> </span>
<img class="left m10r" src="img/icon-receive-history.svg" alt="sync" width="40" ng-if="btx.action == 'received'"> <img class="wallet-details__tx-icon" src="img/icon-tx-received.svg" alt="sync" width="40" ng-if="btx.action == 'received'">
<img class="left m10r" src="img/icon-sent-history.svg" alt="sync" width="40" ng-if="btx.action == 'sent'"> <img class="wallet-details__tx-icon" src="img/icon-tx-sent.svg" alt="sync" width="40" ng-if="btx.action == 'sent'">
<img class="left m10r" src="img/icon-moved.svg" alt="sync" width="40" ng-if="btx.action == 'moved'"> <img class="wallet-details__tx-icon" src="img/icon-tx-moved.svg" alt="sync" width="40" ng-if="btx.action == 'moved'">
<h2 class="p10t"> <div class="wallet-details__tx-title">
<div ng-if="btx.action == 'received'"> <div ng-if="btx.action == 'received'">
<span class="ellipsis"> <span class="ellipsis">
<h2 ng-if="btx.note.body">{{btx.note.body}}</h2> <div ng-if="btx.note.body">{{btx.note.body}}</div>
<h2 ng-if="!btx.note.body" translate> Received</h2> <div ng-if="!btx.note.body" translate> Received</div>
</span> </span>
</div> </div>
<div ng-if="btx.action == 'sent'"> <div ng-if="btx.action == 'sent'">
<span class="ellipsis"> <span class="ellipsis">
<h2 ng-if="btx.message">{{btx.message}}</h2> <div ng-if="btx.message">{{btx.message}}</div>
<h2 ng-if="!btx.message && btx.note.body">{{btx.note.body}}</h2> <div ng-if="!btx.message && btx.note.body">{{btx.note.body}}</div>
<h2 ng-if="!btx.message && !btx.note.body && wallet.addressbook[btx.addressTo]">{{wallet.addressbook[btx.addressTo]}}</h2> <contact ng-if="!btx.message && !btx.note.body" class="ellipsis" address="{{btx.addressTo}}" label="'Sent'"></contact>
<h2 ng-if="!btx.message && !btx.note.body && !wallet.addressbook[btx.addressTo]" translate> Sent</h2>
</span> </span>
</div> </div>
<div ng-if="btx.action == 'moved'"> <div ng-if="btx.action == 'moved'">
<span class="ellipsis"> <span class="ellipsis">
<h2 ng-if="btx.note.body">{{btx.note.body}}</h2> <div ng-if="btx.note.body">{{btx.note.body}}</div>
<h2 ng-if="!btx.note.body" translate>Moved</h2> <div ng-if="!btx.note.body" translate>Moved</div>
</span> </span>
</div> </div>
<span class="label tu warning radius" ng-if="btx.action == 'invalid'" translate>Invalid</span> <span class="label tu warning radius" ng-if="btx.action == 'invalid'" translate>Invalid</span>
</h2> </div>
</div> </div>
</div> </div>
<ion-infinite-scroll <ion-infinite-scroll