diff --git a/.travis.yml b/.travis.yml index 51762742b..4ad45dd71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,12 @@ +sudo: required +dist: trusty language: node_js node_js: - - '4.0' + - '6' before_install: - - npm install -g bower - - npm install -g grunt-cli - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start install: - - bower install - - npm install -after_success: - - npm run exec:coveralls + - npm run apply:bitpay +# after_success: +# - npm run exec:coveralls diff --git a/README.md b/README.md index ee4d4007f..1bc0b0ea8 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -Copay +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) -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 a secure bitcoin wallet platform for both desktop and mobile devices. 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. diff --git a/app-template/build-macos.sh b/app-template/build-macos.sh index f214b1fb4..5f09bd0b2 100755 --- a/app-template/build-macos.sh +++ b/app-template/build-macos.sh @@ -116,6 +116,9 @@ mkdir /Volumes/"${VOL_NAME}"/.background cp "${DMG_BACKGROUND_IMG}" /Volumes/"${VOL_NAME}"/.background/ echo "Adding volume icon to disk image" +# we install this here to avoid trying to install it on linux or windows, where +# it fails to install +npm install fileicon # use fileicon node_module cp "${DMG_VOLUME_ICON}" /Volumes/"${VOL_NAME}"/.VolumeIcon.icns `npm bin`/fileicon set /Volumes/"${VOL_NAME}"/ /Volumes/"${VOL_NAME}"/.VolumeIcon.icns diff --git a/app-template/package-template.json b/app-template/package-template.json index 5ff4ab91e..a1d87faf0 100644 --- a/app-template/package-template.json +++ b/app-template/package-template.json @@ -45,6 +45,10 @@ "bugs": { "url": "*GITHUBREPOBUGS*" }, + "engines": { + "node": "6", + "npm": "3" + }, "dependencies": { "adm-zip": "^0.4.7", "angular": "1.4.6", @@ -103,7 +107,7 @@ "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", "apply:copay": "npm i && cd app-template && node apply.js copay && cordova prepare", "apply:bitpay": "npm i && cd app-template && node apply.js bitpay && cordova prepare", - "test": "./node_modules/.bin/grunt test-coveralls", + "test": "echo \"no package tests configured\"", "clean": "trash platforms && trash plugins && cordova prepare", "unstage-package": "git reset package.json", "clean-all": "git clean -dfx" @@ -114,7 +118,6 @@ "ionic": "^2.1.0", "trash-cli": "^1.4.0", "lodash": "^4.3.0", - "fileicon": "^0.1.8", "pre-commit": "^1.1.3" }, "pre-commit": "unstage-package" diff --git a/resources/bitpay/ios/app-store/feature-graphic-1024.png b/resources/bitpay/android/app-store/feature-graphic-1024.png similarity index 100% rename from resources/bitpay/ios/app-store/feature-graphic-1024.png rename to resources/bitpay/android/app-store/feature-graphic-1024.png diff --git a/resources/bitpay/android/app-store/icon-512x512.png b/resources/bitpay/android/app-store/icon-512x512.png new file mode 100644 index 000000000..92b75419a Binary files /dev/null and b/resources/bitpay/android/app-store/icon-512x512.png differ diff --git a/resources/bitpay/windows/icon.ico b/resources/bitpay/windows/icon.ico new file mode 100644 index 000000000..4629745bd Binary files /dev/null and b/resources/bitpay/windows/icon.ico differ diff --git a/resources/copay/android/app-store/icon-512x512.png b/resources/copay/android/app-store/icon-512x512.png new file mode 100644 index 000000000..cba4cf27a Binary files /dev/null and b/resources/copay/android/app-store/icon-512x512.png differ diff --git a/resources/copay/windows/icon.ico b/resources/copay/windows/icon.ico new file mode 100644 index 000000000..b810ca475 Binary files /dev/null and b/resources/copay/windows/icon.ico differ diff --git a/resources/generate.sh b/resources/generate.sh index 51e7c1dad..0acf4b436 100644 --- a/resources/generate.sh +++ b/resources/generate.sh @@ -2,9 +2,11 @@ # export all slices marked for export to the proper directory echo "Exporting all assets from src.sketch..." +# sketchtool is installed by install.sh sketchtool export layers src.sketch function postprocess { + # $1 = distribution name echo "Beginning postprocessing for $1..." echo "Postprocessing assets for macOS..." @@ -15,6 +17,14 @@ function postprocess { tiffutil -cathidpicheck $1/mac/dmg-background.png $1/mac/dmg-background@2x.png -out $1/mac/dmg-background.tiff echo "Removing raw background pngs..." rm $1/mac/dmg-background.png $1/mac/dmg-background@2x.png + + echo "Postprocessing assets for Windows..." + + echo "Combining windows/ico pngs into a single ICO file..." + # convert ships with imagemagick + convert $1/windows/ico/ico_16x16.png $1/windows/ico/ico_24x24.png $1/windows/ico/ico_32x32.png $1/windows/ico/ico_48x48.png $1/windows/ico/ico_64x64.png $1/windows/ico/ico_128x128.png $1/windows/ico/ico_256x256.png $1/windows/icon.ico + echo "Removing raw windows/ico pngs..." + rm -r $1/windows/ico/* && rmdir $1/windows/ico } function iconset { diff --git a/resources/install.sh b/resources/install.sh index 15d7b5938..37c444946 100644 --- a/resources/install.sh +++ b/resources/install.sh @@ -1,2 +1,8 @@ +echo "Installing sketchtool... (this requires Sketch.app)" # This installs sketchtool: https://www.sketchapp.com/tool/ sh /Applications/Sketch.app/Contents/Resources/sketchtool/install.sh + +echo "Installing imagemagick... (This requires Homebrew)" +# This requires Homebrew: http://brew.sh/ +brew install imagemagick +# imagemagick provides the `convert` utility, used to generate ICO files diff --git a/resources/readme.md b/resources/readme.md index dde1971dc..9d6d0f9f4 100644 --- a/resources/readme.md +++ b/resources/readme.md @@ -4,9 +4,9 @@ This directory contains a `src.sketch` file from which all other assets are expo ## Requirements -You'll need [Sketch](https://www.sketchapp.com/) to make any changes to this directory. +You'll need [Sketch](https://www.sketchapp.com/) to make any changes to this directory. You'll also need to have [Homebrew](http://brew.sh/) installed to regenerate all assets. -Sketch is only available for macOS, and several processes in `generate.sh` require utilities that ship with the OS, so this process must be performed on macOS. +Sketch and Homebrew are only available for macOS, and several processes in `generate.sh` require utilities that ship with macOS, so this process requires macOS. ## Install sketchtool diff --git a/resources/src.sketch b/resources/src.sketch index 212d9de82..c5af3aa96 100644 Binary files a/resources/src.sketch and b/resources/src.sketch differ diff --git a/src/js/controllers/activity.js b/src/js/controllers/activity.js index dbf2f5ada..29721ca3b 100644 --- a/src/js/controllers/activity.js +++ b/src/js/controllers/activity.js @@ -39,7 +39,7 @@ angular.module('copayApp.controllers').controller('activityController', ongoingProcess.set('loadingTxInfo', false); if (err) { $log.warn('No txp found'); - return popupService.showAlert(null, gettextCatalog.getString('Transaction not found')); + return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found')); } txpModalService.open(_txp); }); @@ -61,7 +61,7 @@ angular.module('copayApp.controllers').controller('activityController', if (!tx) { $log.warn('No tx found'); - return popupService.showAlert(null, gettextCatalog.getString('Transaction not found')); + return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found')); } $scope.wallet = wallet; diff --git a/src/js/controllers/addressbook.js b/src/js/controllers/addressbook.js index 4c3ffba35..00931bc83 100644 --- a/src/js/controllers/addressbook.js +++ b/src/js/controllers/addressbook.js @@ -47,7 +47,7 @@ angular.module('copayApp.controllers').controller('addressbookListController', f $timeout(function() { addressbookService.remove(addr, function(err, ab) { if (err) { - popupService.showAlert(err); + popupService.showAlert(gettextCatalog.getString('Error'), err); return; } initAddressbook(); @@ -56,7 +56,7 @@ angular.module('copayApp.controllers').controller('addressbookListController', f }, 100); }; - $scope.$on("$ionicView.beforeEnter", function(event, data){ + $scope.$on("$ionicView.beforeEnter", function(event, data) { initAddressbook(); }); diff --git a/src/js/controllers/addressbookAdd.js b/src/js/controllers/addressbookAdd.js index a33050197..a1bc7fd7a 100644 --- a/src/js/controllers/addressbookAdd.js +++ b/src/js/controllers/addressbookAdd.js @@ -27,7 +27,7 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu $timeout(function() { addressbookService.add(addressbook, function(err, ab) { if (err) { - popupService.showAlert(err); + popupService.showAlert(gettextCatalog.getString('Error'), err); return; } if ($scope.fromSendTab) $scope.goHome(); diff --git a/src/js/controllers/amazon.js b/src/js/controllers/amazon.js index 453cced4e..6bc4a4108 100644 --- a/src/js/controllers/amazon.js +++ b/src/js/controllers/amazon.js @@ -12,7 +12,7 @@ angular.module('copayApp.controllers').controller('amazonController', var initAmazon = function() { amazonService.getPendingGiftCards(function(err, gcds) { if (err) { - popupService.showAlert(err); + popupService.showAlert(gettextCatalog.getString('Error'), err); return; } $scope.giftCards = lodash.isEmpty(gcds) ? null : gcds; @@ -31,7 +31,7 @@ angular.module('copayApp.controllers').controller('amazonController', $log.debug("creating gift card"); amazonService.createGiftCard(dataFromStorage, function(err, giftCard) { if (err) { - popupService.showAlert(bwcError.msg(err)); + popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err)); return; } if (giftCard.status != 'PENDING') { @@ -51,7 +51,7 @@ angular.module('copayApp.controllers').controller('amazonController', $log.debug("Saving new gift card"); amazonService.getPendingGiftCards(function(err, gcds) { if (err) { - popupService.showAlert(err); + popupService.showAlert(gettextCatalog.getString('Error'), err); return; } $scope.giftCards = gcds; diff --git a/src/js/controllers/backup.js b/src/js/controllers/backup.js index 324372323..f40af13d8 100644 --- a/src/js/controllers/backup.js +++ b/src/js/controllers/backup.js @@ -131,7 +131,6 @@ angular.module('copayApp.controllers').controller('backupController', } profileService.setBackupFlag(wallet.credentials.walletId); - profileService.setBackupNeededModalFlag(wallet.credentials.walletId); return cb(); }, 1); }; diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 3e37210ea..dd84deaf9 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -4,12 +4,14 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi var self = this; var runningBalance; - $scope.dateRange = { value: 'last30Days'}; + $scope.dateRange = { + value: 'last30Days' + }; $scope.network = bitpayCardService.getEnvironment(); var updateHistoryFromCache = function(cb) { bitpayCardService.getBitpayDebitCardsHistory($scope.cardId, function(err, data) { - if (err || lodash.isEmpty(data)) return cb(); + if (err ||  lodash.isEmpty(data)) return cb(); $scope.historyCached = true; self.bitpayCardTransactionHistory = data.transactions; self.bitpayCardCurrentBalance = data.balance; @@ -19,8 +21,8 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi var setDateRange = function(preset) { var startDate, endDate; - preset = preset || 'last30Days'; - switch(preset) { + preset = preset ||  'last30Days'; + switch (preset) { case 'last30Days': startDate = moment().subtract(30, 'days').toISOString(); endDate = moment().toISOString(); @@ -138,7 +140,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi disableAnimate: true }); $state.go('tabs.home'); - popupService.showAlert(null, msg); + popupService.showAlert(gettextCatalog.getString('Error'), msg); } else { updateHistoryFromCache(function() { self.update(); @@ -147,4 +149,3 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi }); }); - diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index 73ef571ac..63e5b7904 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -24,11 +24,13 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f obj.otp = otp; bitpayCardService.bitAuthPair(obj, function(err, data) { if (err) { - popupService.showAlert(null, err); + popupService.showAlert(gettextCatalog.getString('Error'), err); return; } var title = gettextCatalog.getString('Add BitPay Card Account?'); - var msg = gettextCatalog.getString('Would you like to add this account ({{email}}) to your wallet?', {email: obj.email}); + var msg = gettextCatalog.getString('Would you like to add this account ({{email}}) to your wallet?', { + email: obj.email + }); var ok = gettextCatalog.getString('Add Account'); var cancel = gettextCatalog.getString('Go back'); popupService.showConfirm(title, msg, ok, cancel, function(res) { @@ -43,7 +45,9 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f }); $state.go('tabs.home').then(function() { if (data.cards[0]) { - $state.transitionTo('tabs.bitpayCard', {id: data.cards[0].id}); + $state.transitionTo('tabs.bitpayCard', { + id: data.cards[0].id + }); } }); }); diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 9d8165758..941a02aa3 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -84,6 +84,9 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.insuffientFunds = true; $log.warn('No wallet available to make the payment'); + $timeout(function() { + $scope.$apply(); + }); } } }); @@ -99,7 +102,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( $timeout(function() { $scope.$apply(); - }, 100); + }); }; $scope.$on('accepted', function(event) { @@ -286,6 +289,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( }; $scope.approve = function(onSendStatusChange) { + if ($scope.paypro && $scope.paymentExpired.value) { popupService.showAlert(null, gettextCatalog.getString('The payment request has expired')); $scope.sendStatus = ''; diff --git a/src/js/controllers/import.js b/src/js/controllers/import.js index 056d55ed5..af9dd6e31 100644 --- a/src/js/controllers/import.js +++ b/src/js/controllers/import.js @@ -60,7 +60,7 @@ angular.module('copayApp.controllers').controller('importController', }; if (info.type == 1 && info.hasPassphrase) - popupService.showAlert(gettextCatalog.getString('Password required. Make sure to enter your password in advanced options')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Password required. Make sure to enter your password in advanced options')); $scope.formData.derivationPath = info.derivationPath; $scope.formData.testnetEnabled = info.network == 'testnet' ? true : false; @@ -236,7 +236,7 @@ angular.module('copayApp.controllers').controller('importController', var words = $scope.formData.words || null; if (!words) { - popupService.showAlert(gettextCatalog.getString('Please enter the recovery phrase')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Please enter the recovery phrase')); } else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) { return _importExtendedPrivateKey(words, opts); } else if (words.indexOf('xpub') == 0 || words.indexOf('tpuv') == 0) { @@ -245,7 +245,7 @@ angular.module('copayApp.controllers').controller('importController', var wordList = words.split(/[\u3000\s]+/); if ((wordList.length % 3) != 0) { - popupService.showAlert(gettextCatalog.getString('Wrong number of recovery words:') + wordList.length); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Wrong number of recovery words: ') + wordList.length); return; } } @@ -280,7 +280,7 @@ angular.module('copayApp.controllers').controller('importController', $scope.importHW = function(form) { if (form.$invalid || $scope.formData.ccount < 0) { - popupService.showAlert(gettextCatalog.getString('There is an error in the form')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('There is an error in the form')); return; } @@ -290,7 +290,7 @@ angular.module('copayApp.controllers').controller('importController', if ($scope.seedSource.id == 'trezor') { if (account < 1) { - popupService.showAlert(gettextCatalog.getString('Invalid account number')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); return; } account = account - 1; diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 200de8b76..656949602 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('tabHomeController', - function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window, bitpayCardService, startupService, addressbookService) { + function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window, bitpayCardService, startupService, addressbookService) { var wallet; var listeners = []; var notifications = []; @@ -12,6 +12,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.homeTip = $stateParams.fromOnboarding; $scope.isCordova = platformInfo.isCordova; $scope.isAndroid = platformInfo.isAndroid; + $scope.isNW = platformInfo.isNW; $scope.$on("$ionicView.afterEnter", function() { startupService.ready(); @@ -23,6 +24,21 @@ angular.module('copayApp.controllers').controller('tabHomeController', }); } + if ($scope.isNW) { + latestReleaseService.checkLatestRelease(function(err, newRelease) { + if (err) { + $log.warn(err); + return; + } + + if (newRelease) $scope.newRelease = true; + }); + } + + $scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) { + externalLinkService.open(url, optIn, title, message, okText, cancelText); + }; + $scope.openNotificationModal = function(n) { wallet = profileService.getWallet(n.walletId); @@ -41,7 +57,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', ongoingProcess.set('loadingTxInfo', false); if (err) { $log.warn('No txp found'); - return popupService.showAlert(null, gettextCatalog.getString('Transaction not found')); + return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found')); } txpModalService.open(_txp); }); @@ -63,7 +79,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', if (!tx) { $log.warn('No tx found'); - return popupService.showAlert(null, gettextCatalog.getString('Transaction not found')); + return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found')); } $scope.wallet = wallet; @@ -181,13 +197,13 @@ angular.module('copayApp.controllers').controller('tabHomeController', }); }; - var nextStep = function() { - lodash.each(['AmazonGiftCards', 'BitpayCard', 'BuyAndSell'], function(service) { + var nextStep = function(cb) { + var i = 0; + var services = ['AmazonGiftCards', 'BitpayCard', 'BuyAndSell']; + lodash.each(services, function(service) { storageService.getNextStep(service, function(err, value) { $scope.externalServices[service] = value ? true : false; - $timeout(function() { - $ionicScrollDelegate.resize(); - }, 10); + if (++i == services.length) return cb(); }); }); }; @@ -227,7 +243,6 @@ angular.module('copayApp.controllers').controller('tabHomeController', }; $scope.$on("$ionicView.enter", function(event, data) { - nextStep(); updateAllWallets(); addressbookService.list(function(err, ab) { @@ -248,22 +263,28 @@ angular.module('copayApp.controllers').controller('tabHomeController', ]; configService.whenAvailable(function() { - var config = configService.getSync(); - var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; + nextStep(function() { + var config = configService.getSync(); + var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; - $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp; - $scope.coinbaseEnabled = config.coinbase.enabled && !isWindowsPhoneApp; - $scope.amazonEnabled = config.amazon.enabled; - $scope.bitpayCardEnabled = config.bitpayCard.enabled; + $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp; + $scope.coinbaseEnabled = config.coinbase.enabled && !isWindowsPhoneApp; + $scope.amazonEnabled = config.amazon.enabled; + $scope.bitpayCardEnabled = config.bitpayCard.enabled; - var buyAndSellEnabled = !$scope.externalServices.BuyAndSell && ($scope.glideraEnabled || $scope.coinbaseEnabled); - var amazonEnabled = !$scope.externalServices.AmazonGiftCards && $scope.amazonEnabled; - var bitpayCardEnabled = !$scope.externalServices.BitpayCard && $scope.bitpayCardEnabled; + var buyAndSellEnabled = !$scope.externalServices.BuyAndSell && ($scope.glideraEnabled || $scope.coinbaseEnabled); + var amazonEnabled = !$scope.externalServices.AmazonGiftCards && $scope.amazonEnabled; + var bitpayCardEnabled = !$scope.externalServices.BitpayCard && $scope.bitpayCardEnabled; - $scope.nextStepEnabled = buyAndSellEnabled || amazonEnabled || bitpayCardEnabled; - $scope.recentTransactionsEnabled = config.recentTransactions.enabled; + $scope.nextStepEnabled = buyAndSellEnabled || amazonEnabled || bitpayCardEnabled; + $scope.recentTransactionsEnabled = config.recentTransactions.enabled; - if ($scope.bitpayCardEnabled) bitpayCardCache(); + if ($scope.bitpayCardEnabled) bitpayCardCache(); + $timeout(function() { + $ionicScrollDelegate.resize(); + $scope.$apply(); + }, 10); + }); }); }); diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 733297650..11095db14 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -4,7 +4,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi $scope.isCordova = platformInfo.isCordova; $scope.isNW = platformInfo.isNW; - var showModalTimeout; $scope.shareAddress = function(addr) { if ($scope.generatingAddress) return; @@ -21,11 +20,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi $scope.generatingAddress = false; if (err) popupService.showAlert(gettextCatalog.getString('Error'), err); $scope.addr = addr; - if ($scope.wallet.showBackupNeededModal) { - showModalTimeout = $timeout(function() { - $scope.openBackupNeededModal(); - }, 2000); - } $timeout(function() { $scope.$apply(); }, 10); @@ -59,7 +53,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi $scope.close = function() { $scope.BackupNeededModal.hide(); $scope.BackupNeededModal.remove(); - profileService.setBackupNeededModalFlag($scope.wallet.credentials.walletId); }; $scope.doBackup = function() { @@ -84,16 +77,13 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi return; } $scope.wallet = wallet; + $scope.generatingAddress = false; $log.debug('Wallet changed: ' + wallet.name); $timeout(function() { - $scope.setAddress(); + $scope.setAddress(false); }, 100); }); - $scope.$on("$ionicView.leave", function(event, data) { - $timeout.cancel(showModalTimeout); - }); - $scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.wallets = profileService.getWallets(); }); diff --git a/src/js/controllers/tab-send.js b/src/js/controllers/tab-send.js index afea741e1..9506d6b4d 100644 --- a/src/js/controllers/tab-send.js +++ b/src/js/controllers/tab-send.js @@ -149,6 +149,9 @@ angular.module('copayApp.controllers').controller('tabSendController', function( } }); }); + if ($scope.hasFunds != true) { + $ionicScrollDelegate.freezeScroll(true); + } }; $scope.$on("$ionicView.beforeEnter", function(event, data) { diff --git a/src/js/controllers/tabsController.js b/src/js/controllers/tabsController.js index f3397286b..1b07555d5 100644 --- a/src/js/controllers/tabsController.js +++ b/src/js/controllers/tabsController.js @@ -4,7 +4,7 @@ angular.module('copayApp.controllers').controller('tabsController', function($ro $scope.onScan = function(data) { if (!incomingData.redir(data)) { - popupService.showAlert(null, gettextCatalog.getString('Invalid data')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid data')); } }; @@ -22,7 +22,7 @@ angular.module('copayApp.controllers').controller('tabsController', function($ro }, 1); }; - $scope.$on("$ionicView.beforeEnter", function(event, data){ + $scope.$on("$ionicView.beforeEnter", function(event, data) { $rootScope.hideTabs = ''; }); diff --git a/src/js/services/latestReleaseService.js b/src/js/services/latestReleaseService.js index bb9520223..87aace87f 100644 --- a/src/js/services/latestReleaseService.js +++ b/src/js/services/latestReleaseService.js @@ -23,7 +23,7 @@ angular.module('copayApp.services') if (latest.major < current.major || (latest.major == current.major && latest.minor <= current.minor)) return cb(null, false); - $log.debug('A new version of Copay is available: ' + latestVersion); + $log.debug('A new version is available: ' + latestVersion); return cb(null, true); }); diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index c40b3b1bb..4c65a3f48 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -38,22 +38,6 @@ angular.module('copayApp.services') }); } - root.setBackupNeededModalFlag = function(walletId) { - storageService.setBackupNeededModalFlag(walletId, true, function(err) { - if (err) $log.error(err); - $log.debug('Backup warning modal flag stored'); - root.wallet[walletId].showBackupNeededModal = false; - }); - }; - - function _showBackupNeededModal(wallet, cb) { - storageService.getBackupNeededModalFlag(wallet.credentials.walletId, function(err, val) { - if (err) $log.error(err); - if (val) return cb(false); - return cb(true); - }); - }; - root.setBackupFlag = function(walletId) { storageService.setBackupFlag(walletId, function(err) { if (err) $log.error(err); @@ -117,11 +101,6 @@ angular.module('copayApp.services') wallet.balanceHidden = val; }); - _showBackupNeededModal(wallet, function(val) { - if (wallet.needsBackup) wallet.showBackupNeededModal = val; - else wallet.showBackupNeededModal = false; - }); - wallet.removeAllListeners(); wallet.on('report', function(n) { diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 60f01a3c8..4184f8454 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -373,15 +373,6 @@ angular.module('copayApp.services') }); }; - - root.setBackupNeededModalFlag = function(walletId, val, cb) { - storage.set('showBackupNeededModal-' + walletId, val, cb); - }; - - root.getBackupNeededModalFlag = function(walletId, cb) { - storage.get('showBackupNeededModal-' + walletId, cb); - }; - root.setAmazonGiftCards = function(network, gcs, cb) { storage.set('amazonGiftCards-' + network, gcs, cb); }; diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index dae6d3ccc..65b644ebb 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -83,11 +83,11 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim wallet.notAuthorized = true; $state.go('tabs.home'); } else if (err instanceof errors.NOT_FOUND) { - popupService.showAlert(gettextCatalog.getString('Could not access Wallet Service: Not found')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not access Wallet Service: Not found')); } else { var msg = "" $rootScope.$emit('Local/ClientError', (err.error ? err.error : err)); - popupService.showAlert(bwcError.msg(err, gettextCatalog.getString('Error at Wallet Service'))); + popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, gettextCatalog.getString('Error at Wallet Service'))); } }; root.handleError = lodash.debounce(_handleError, 1000); diff --git a/src/sass/views/includes/modals/modals.scss b/src/sass/views/includes/modals/modals.scss index 8553f11e1..742148e01 100644 --- a/src/sass/views/includes/modals/modals.scss +++ b/src/sass/views/includes/modals/modals.scss @@ -69,5 +69,9 @@ } } +.modal-backdrop.active { + background: rgba(0, 0, 0, .8); + } + @import "backup-needed-modal"; @import "screenshot-warning-model"; diff --git a/src/sass/views/integrations/glidera.scss b/src/sass/views/integrations/glidera.scss index a9869cc87..fea75b498 100644 --- a/src/sass/views/integrations/glidera.scss +++ b/src/sass/views/integrations/glidera.scss @@ -19,4 +19,9 @@ text-align: left; margin: 1rem; } + .item-img-buy, + .item-img-sell { + vertical-align: middle; + margin-right: 10px; + } } diff --git a/src/sass/views/tab-home.scss b/src/sass/views/tab-home.scss index 3053f6eb6..2d5368a8d 100644 --- a/src/sass/views/tab-home.scss +++ b/src/sass/views/tab-home.scss @@ -103,4 +103,19 @@ } } } + .release { + cursor: pointer; + cursor: hand; + background-color: #E9E9EC; + padding-top: 30px; + padding-bottom: 20px; + text-align: center; + color: #444; + i { + margin-top: 1px; + font-size: 20px; + margin-left: 10px; + position: absolute; + } + } } diff --git a/src/sass/views/tab-send.scss b/src/sass/views/tab-send.scss index ccff2790f..fa0ea55ff 100644 --- a/src/sass/views/tab-send.scss +++ b/src/sass/views/tab-send.scss @@ -71,4 +71,5 @@ } } } + .scroll{height: 100%;} } diff --git a/src/sass/views/tab-settings.scss b/src/sass/views/tab-settings.scss index f78b87286..d82a890b1 100644 --- a/src/sass/views/tab-settings.scss +++ b/src/sass/views/tab-settings.scss @@ -3,7 +3,7 @@ color: $dark-gray; border-color: rgba(221, 221, 221, 0.3); } - &-explaination, &-button-group { + &-explanation, &-button-group { padding: 0 1rem; margin: 1rem 0; } diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss index e54502fb7..37438bc1d 100644 --- a/src/sass/views/walletDetails.scss +++ b/src/sass/views/walletDetails.scss @@ -61,6 +61,12 @@ .tx-search:before { font-size: 22px !important; } + .description { + background-color: #f2f2f2; + text-align: center; + font-size: 13px; + color: $mid-gray; + } } .wallet-details-wallet-info { diff --git a/www/views/advancedSettings.html b/www/views/advancedSettings.html index 505ea7dc6..11a90fd4b 100644 --- a/www/views/advancedSettings.html +++ b/www/views/advancedSettings.html @@ -38,7 +38,7 @@
Experimental Features
-
+
These features aren't quite ready for primetime. They may change, stop working, or disappear at any time.
diff --git a/www/views/confirm.html b/www/views/confirm.html index 062850972..94bea675c 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -7,7 +7,7 @@ - +
@@ -46,10 +46,13 @@ Multiple recipients -->
+
+ No wallets available +
Insufficient funds
- + From
@@ -59,14 +62,14 @@
- + Add Memo {{description}} -
+
Fee: {{feeLevel}} {{fee || '...'}} diff --git a/www/views/glidera.html b/www/views/glidera.html index 83f6ad717..f77e3a5f4 100644 --- a/www/views/glidera.html +++ b/www/views/glidera.html @@ -4,8 +4,8 @@ Glidera - @@ -28,7 +28,7 @@

You can buy and sell Bitcoin with a US bank account directly in this app.

- +

Connect your Glidera account to get started.

- -
diff --git a/www/views/includes/txp.html b/www/views/includes/txp.html index c37274878..107c0046c 100644 --- a/www/views/includes/txp.html +++ b/www/views/includes/txp.html @@ -4,8 +4,8 @@ {{tx.amountStr}}
- - {{addressbook[tx.toAddress].name}} + + {{addressbook[tx.toAddress].name || addressbook[tx.toAddress]}} {{tx.message}} diff --git a/www/views/modals/tx-details.html b/www/views/modals/tx-details.html index 39f802c9c..82f560c8c 100644 --- a/www/views/modals/tx-details.html +++ b/www/views/modals/tx-details.html @@ -41,6 +41,12 @@
{{wallet.name}}
+
+ Created by + + {{btx.creatorName}} + +
Memo @@ -54,7 +60,6 @@ {{btx.feeStr}}
-
Timeline
@@ -72,7 +77,7 @@
- +
diff --git a/www/views/modals/txp-details.html b/www/views/modals/txp-details.html index 254caeaa4..769985946 100644 --- a/www/views/modals/txp-details.html +++ b/www/views/modals/txp-details.html @@ -85,8 +85,8 @@ {{tx.creatorName}} -
- {{'Memo'|translate}} +
+ {{'Memo'|translate}} {{tx.message}} @@ -141,7 +141,7 @@
- +
diff --git a/www/views/paperWallet.html b/www/views/paperWallet.html index 43c9754fc..2d9a5a6f2 100644 --- a/www/views/paperWallet.html +++ b/www/views/paperWallet.html @@ -7,7 +7,7 @@
-
+
Backup Needed
Before receiving funds, you must backup your wallet. If this device is lost, it is impossible to access your funds without a backup. diff --git a/www/views/preferencesAlias.html b/www/views/preferencesAlias.html index c34f241c6..6513f0de9 100644 --- a/www/views/preferencesAlias.html +++ b/www/views/preferencesAlias.html @@ -7,7 +7,7 @@ -
+
What do you call this wallet?
When this wallet was created, it was called “{{walletName}}”. You can change the name displayed on this device below.
diff --git a/www/views/preferencesEmail.html b/www/views/preferencesEmail.html index fc7ba9a85..4b97bdd6f 100644 --- a/www/views/preferencesEmail.html +++ b/www/views/preferencesEmail.html @@ -7,7 +7,7 @@ -
+
You'll receive email notifications about payments sent and received from {{wallet.name}}.
diff --git a/www/views/preferencesFee.html b/www/views/preferencesFee.html index 123cec824..a4e453b2e 100644 --- a/www/views/preferencesFee.html +++ b/www/views/preferencesFee.html @@ -7,7 +7,7 @@ -
+
Bitcoin transactions 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. Current fees are determined based on network load and the selected policy.
diff --git a/www/views/preferencesHistory.html b/www/views/preferencesHistory.html index 0b7603c04..25d08b2d3 100644 --- a/www/views/preferencesHistory.html +++ b/www/views/preferencesHistory.html @@ -5,7 +5,7 @@ -
+
Export to file @@ -18,8 +18,14 @@ {{err | translate}}
+
- Clear cache + Clear cache +
+
+ The transaction history and every new incoming transaction are cached in the app. This feature clean this up and synchronizes again from the server +
+
diff --git a/www/views/preferencesInformation.html b/www/views/preferencesInformation.html index 6db452ea6..5871585c5 100644 --- a/www/views/preferencesInformation.html +++ b/www/views/preferencesInformation.html @@ -90,7 +90,7 @@
Latest Wallet Addresses
-
+
Only “main” addresses are shown below. This excludes “change” address.
@@ -99,7 +99,7 @@ {{a.address}} {{a.path}} · {{a.createdOn *1000 | amDateFormat:'MMMM Do YYYY, h:mm a' }}
-
+
Please note: due to resource constraints, this list of addresses is not verified locally. A compromised BWS node could return addresses which are not controlled by this wallet.
diff --git a/www/views/tab-home.html b/www/views/tab-home.html index c0e008a50..865afc0bc 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -10,6 +10,9 @@ spinner="ios-small" on-refresh="onRefresh()"> +
+ An update to this app is available +
diff --git a/www/views/tab-receive.html b/www/views/tab-receive.html index ecff16e8b..6f77a406c 100644 --- a/www/views/tab-receive.html +++ b/www/views/tab-receive.html @@ -46,7 +46,7 @@
-
+
Wallet not backed up
diff --git a/www/views/tab-send.html b/www/views/tab-send.html index 60a594212..b959aee5f 100644 --- a/www/views/tab-send.html +++ b/www/views/tab-send.html @@ -2,73 +2,75 @@ {{'Send' | translate}} - -
- - - -
Start sending bitcoin
-
To get started, buy bitcoin or share your address. You can receive bitcoin from any wallet or service.
-
To get started, you'll need to create a bitcoin wallet and get some bitcoin.
-
- - - -
-
-
- -
Recipient
- -
-
- Contacts - - - -
-
- - - - - Add a Contact - - - - - - - {{item.name}} - - -
- Show more + +
+
+ + + +
Start sending bitcoin
+
To get started, buy bitcoin or share your address. You can receive bitcoin from any wallet or service.
+
To get started, you'll need to create a bitcoin wallet and get some bitcoin.
+
+ + +
+
+
Recipient
+ +
+
+ Contacts + + + +
+ +
-
-
-
- Transfer to Wallet +
diff --git a/www/views/walletDetails.html b/www/views/walletDetails.html index 315f43901..8c56d4be6 100644 --- a/www/views/walletDetails.html +++ b/www/views/walletDetails.html @@ -99,7 +99,7 @@
-