diff --git a/Gruntfile.js b/Gruntfile.js index 342cc85e7..eb4bb2eb0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -163,7 +163,7 @@ module.exports = function(grunt) { }, bitanalytics: { src: [ - 'bitanalytics/bitanalytics-0.1.0.js' + 'bitanalytics/bitanalytics.js' ], dest: 'www/lib/bitanalytics.js' }, diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 1c7f5a30a..2f8e3db04 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -72,7 +72,7 @@ - + diff --git a/bitanalytics/bitanalytics-0.1.0.js b/bitanalytics/bitanalytics.js similarity index 97% rename from bitanalytics/bitanalytics-0.1.0.js rename to bitanalytics/bitanalytics.js index db149e481..c8c0d8870 100644 --- a/bitanalytics/bitanalytics-0.1.0.js +++ b/bitanalytics/bitanalytics.js @@ -6276,7 +6276,7 @@ var ClickAction = /** @class */ (function (_super) { }(action_1.default)); exports.default = ClickAction; -},{"../action":4,"../log-event":15,"../log-event-handlers":14}],6:[function(require,module,exports){ +},{"../action":4,"../log-event":16,"../log-event-handlers":15}],6:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; @@ -6315,7 +6315,7 @@ var BitAnalytics = /** @class */ (function () { exports.default = BitAnalytics; BitAnalytics.main(); -},{"./action-factory":2,"./action-handlers":3,"./channels/adjust-channel":9,"./channels/mixpanel-channel":12,"./log-event":15,"./log-event-handlers":14}],7:[function(require,module,exports){ +},{"./action-factory":2,"./action-handlers":3,"./channels/adjust-channel":9,"./channels/mixpanel-channel":12,"./log-event":16,"./log-event-handlers":15}],7:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; @@ -6560,11 +6560,10 @@ var FirebaseChannel = /** @class */ (function (_super) { var keys = Object.keys(params); var keysLength = keys.length; var sanitized = {}; - for (var i = 0; i < keysLength; i++) { - var key = keys[i]; + keys.map(function (key) { var cleanKey = key.replace('-', '_').replace(/[\W]+/g, ''); sanitized[cleanKey] = params[key]; - } + }); return sanitized; }; return FirebaseChannel; @@ -6588,13 +6587,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); var channel_1 = __importDefault(require("../channel")); +var ga_1 = __importDefault(require("../external-libs/ga")); var GoogleAnalyticsChannel = /** @class */ (function (_super) { __extends(GoogleAnalyticsChannel, _super); function GoogleAnalyticsChannel(name, config) { var _this = _super.call(this, name) || this; - _this.dataLayer = null; _this.gaInstance = null; - _this.trackingId = ''; _this.eventLabels = ['id']; if (!config.trackingId) { throw new Error('[BitAnalytics] Google Analytics config is missing tracking ID.'); @@ -6602,8 +6600,12 @@ var GoogleAnalyticsChannel = /** @class */ (function (_super) { if (config.eventLabels) { _this.eventLabels = config.eventLabels; } - _this.trackingId = config.trackingId; - _this.setUpGa(); + _this.gaInstance = new ga_1.default({ + trackID: config.trackingId, + appVersion: config.appVersion, + appName: config.appName || 'App' + }); + _this.isReady = true; return _this; } /** @@ -6612,49 +6614,26 @@ var GoogleAnalyticsChannel = /** @class */ (function (_super) { * */ GoogleAnalyticsChannel.prototype.postEvent = function (name, params) { - // Default Google Analytics Events - // https://developers.google.com/analytics/devguides/collection/gtagjs/events - // Useful to convert to these, or start with these? if (this.isReady) { - params.event_category = name; + var category = name; + var action = name; + var label = name; + var value = params['value'] || ''; for (var _i = 0, _a = this.eventLabels; _i < _a.length; _i++) { var eventLabel = _a[_i]; if (params[eventLabel]) { - params.event_label = params[eventLabel]; + label = params[eventLabel]; break; } } - this.gtag('event', name, params); + this.gaInstance.event(category, action, label, value); } }; - /** - * - * Private methods - * - */ - /** - * Mimics function in the tracking snippet - */ - GoogleAnalyticsChannel.prototype.gtag = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - console.log(arguments); - window.dataLayer.push(arguments); - }; - GoogleAnalyticsChannel.prototype.setUpGa = function () { - // From what GA recommends to insert into page - window.dataLayer = window.dataLayer || []; - this.gtag('js', new Date()); - this.gtag('config', this.trackingId); - this.isReady = true; - }; return GoogleAnalyticsChannel; }(channel_1.default)); exports.default = GoogleAnalyticsChannel; -},{"../channel":8}],12:[function(require,module,exports){ +},{"../channel":8,"../external-libs/ga":14}],12:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || @@ -6746,6 +6725,207 @@ exports.default = MixpanelChannel; },{}],14:[function(require,module,exports){ "use strict"; +/* + * name: nwjs-analytics -Node-Webkit Google Analytics integration + * version: 1.0.2 + * github: https://github.com/Daaru00/nwjs-analytics + */ +function GA(opt) { + this.apiVersion = opt.apiVersion || '1'; + this.trackID = opt.trackID || 'UA-XXXXXXXX-X'; + this.clientID = opt.clientID || null; + this.userID = opt.userID || null; + this.appName = opt.appName || 'App'; + this.appVersion = opt.appVersion || '1.0.0'; + this.debug = opt.debug || false; + this.performanceTracking = opt.performanceTracking || true; + this.errorTracking = opt.errorTracking || true; + this.userLanguage = opt.userLanguage || "en"; + this.currency = opt.currency || "EUR"; + this.lastScreenName = opt.lastScreenName || ''; +} +GA.prototype.sendRequest = function (data, callback) { + var ga = this; + if (!this.clientID || this.clientID == null) + this.clientID = this.generateClientID(); + if (!this.userID || this.userID == null) + this.userID = this.generateClientID(); + var postData = "v=" + this.apiVersion + + "&an=" + this.appName + + "&av=" + this.appVersion + + "&tid=" + this.trackID + + "&cid=" + this.clientID + + "&sr=" + this.getScreenResolution() + + "&vp=" + this.getViewportSize(); + Object.keys(data).forEach(function (key) { + var val = data[key]; + if (typeof val != "undefined") + postData += "&" + key + "=" + val; + }); + var http = new XMLHttpRequest(); + var url = "https://www.google-analytics.com"; + if (!this.debug) + url += "/collect"; + else + url += "/debug/collect"; + http.open("GET", url + "?" + postData, true); + http.onreadystatechange = function () { + if (ga.debug) + console.log(http.response); + if (http.readyState == 4 && http.status == 200) { + if (callback) + callback(true); + } + else { + if (callback) + callback(false); + } + }; + http.send(); +}; +GA.prototype.generateClientID = function () { + var id = ""; + var possibilities = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (var i = 0; i < 5; i++) + id += possibilities.charAt(Math.floor(Math.random() * possibilities.length)); + return id; +}; +GA.prototype.getScreenResolution = function () { + return screen.width + "x" + screen.height; +}; +GA.prototype.getColorDept = function () { + return screen.colorDepth + "-bits"; +}; +GA.prototype.getUserAgent = function () { + return navigator.userAgent; +}; +GA.prototype.getViewportSize = function () { + return window.screen.availWidth + "x" + window.screen.availHeight; +}; +/* + * Measurement Protocol + * [https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide] + */ +GA.prototype.screenView = function (screename) { + var data = { + 't': 'screenview', + 'cd': screename + }; + this.sendRequest(data); + this.lastScreenName = screename; +}; +GA.prototype.event = function (category, action, label, value) { + var data = { + 't': 'event', + 'ec': category, + 'ea': action, + }; + if (label) { + data['el'] = label; + } + if (value) { + data['ev'] = value; + } + if (this.lastScreenName) { + data['cd'] = this.lastScreenName; + } + this.sendRequest(data); +}; +GA.prototype.exception = function (msg, fatal) { + var data = { + 't': 'exception', + 'exd': msg, + 'exf': fatal || 0 + }; + this.sendRequest(data); +}; +GA.prototype.timing = function (category, variable, time, label) { + var data = { + 't': 'timing', + 'utc': category, + 'utv': variable, + 'utt': time, + 'utl': label, + }; + this.sendRequest(data); +}, + GA.prototype.ecommerce = { + transactionID: false, + generateTransactionID: function () { + var id = ""; + var possibilities = "0123456789"; + for (var i = 0; i < 5; i++) + id += possibilities.charAt(Math.floor(Math.random() * possibilities.length)); + return id; + }, + transaction: function (total, items) { + var t_id = ""; + if (!this.ecommerce.transactionID) + t_id = this.ecommerce.generateTransactionID(); + else + t_id = this.ecommerce.transactionID; + var data = { + 't': 'transaction', + 'ti': t_id, + 'tr': total, + 'cu': this.currency, + }; + this.sendRequest(data); + items.forEach(function (item) { + var data = { + 't': 'item', + 'ti': t_id, + 'in': item.name, + 'ip': item.price, + 'iq': item.qty, + 'ic': item.id, + 'cu': this.currency + }; + this.sendRequest(data); + }); + } + }, + GA.prototype.custom = function (data) { + this.sendRequest(data); + }; +module.exports = GA; +/* + * Performance Tracking + */ +/*window.addEventListener("load", function() { + + if(ga.performanceTracking) { + setTimeout(function() { + var timing = window.performance.timing; + var userTime = timing.loadEventEnd - timing.navigationStart; + ga.timing("performance", "pageload", userTime); + }, 0); + } + +}, false);*/ +/* + * Error Reporting + */ +/*window.onerror = function (msg, url, lineNo, columnNo, error) { + var message = [ + 'Message: ' + msg, + 'Line: ' + lineNo, + 'Column: ' + columnNo, + 'Error object: ' + JSON.stringify(error) + ].join(' - '); + + if(ga.errorTracking) + { + setTimeout(function() { + ga.exception(message.toString()); + }, 0); + } + + return false; +};*/ + +},{}],15:[function(require,module,exports){ +"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -6865,7 +7045,7 @@ var LogEventHandlers = /** @class */ (function () { }()); exports.default = LogEventHandlers; -},{"./channel-factory":7}],15:[function(require,module,exports){ +},{"./channel-factory":7}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var LogEvent = /** @class */ (function () { diff --git a/i18n/po/template.pot b/i18n/po/template.pot index 358145a1c..d8281988f 100644 --- a/i18n/po/template.pot +++ b/i18n/po/template.pot @@ -201,6 +201,16 @@ msgstr "" msgid "Price Display" msgstr "" +#: src/js/controllers/tab-settings.js:19 +#: www/views/preferencesPriceDisplay.html:12 +msgid "Fiat" +msgstr "" + +#: src/js/controllers/tab-settings.js:19 +#: www/views/preferencesPriceDisplay.html:15 +msgid "Cryptocurrency" +msgstr "" + #: src/js/controllers/buyAmazon.js:98 msgid "Amazon.com is not available at this moment. Please try back later." msgstr "" @@ -432,6 +442,7 @@ msgid "Buy & Sell Bitcoin" msgstr "" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "" @@ -656,6 +667,7 @@ msgstr "" #: src/js/controllers/copayers.js:79 #: src/js/controllers/export.js:193 +#: src/js/controllers/confirm.js:41 #: www/views/includes/copyToClipboard.html:4 msgid "Copied to clipboard" msgstr "" @@ -2162,6 +2174,10 @@ msgstr "" msgid "Payment Sent" msgstr "" +#: www/views/includes/slideToAcceptSuccess.html:12 +msgid "Share this transaction" +msgstr "" + #: www/views/modals/txp-details.html:32 msgid "Payment accepted, but not yet broadcasted" msgstr "" @@ -3725,6 +3741,54 @@ msgstr "" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "" + #: src/js/controllers/amount.js:49 msgid "Address doesn\'t contain currency information, please make sure you are sending the correct currency." msgstr "" diff --git a/src/js/controllers/addressbookAdd.js b/src/js/controllers/addressbookAdd.js index 9529d943e..ff284b234 100644 --- a/src/js/controllers/addressbookAdd.js +++ b/src/js/controllers/addressbookAdd.js @@ -21,6 +21,9 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu $timeout(function() { var form = addressbookForm; if (data && form) { + if (data.result) { + data = data.result; + } data = data.replace(/^bitcoin(cash)?:/, ''); form.address.$setViewValue(data); form.address.$isValid = true; @@ -36,9 +39,9 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu addressbook.address = translated.legacy; } - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("contact_created", [{ "coin": $scope.addressbookEntry.coin diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 07256c0b2..c98064fcc 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -1,11 +1,12 @@ 'use strict'; -angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, $ionicLoading, addressbookService, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bitcoinCashJsService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService, soundService) { +angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, $ionicLoading, ionicToast, addressbookService, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bitcoinCashJsService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService, soundService, clipboardService) { var countDown = null; var FEE_TOO_HIGH_LIMIT_PER = 15; var tx = {}; + var lastTxId = ""; // Config Related values var config = configService.getSync(); @@ -25,6 +26,17 @@ angular.module('copayApp.controllers').controller('confirmController', function( }, 10); } + $scope.shareTransaction = function() { + var explorerTxUrl = 'https://explorer.bitcoin.com/'+tx.coin+'/tx/'+lastTxId; + if (platformInfo.isCordova) { + var text = 'Take a look at this Bitcoin transaction here: '+explorerTxUrl; + window.plugins.socialsharing.share(text, null, null, null); + } else { + ionicToast.show(gettextCatalog.getString('Copied to clipboard'), 'bottom', false, 3000); + clipboardService.copyToClipboard(explorerTxUrl); + } + }; + $scope.showWalletSelector = function() { $scope.walletSelector = true; refresh(); @@ -652,6 +664,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( txConfirmNotification.subscribe(wallet, { txid: txp.txid }); + lastTxId = txp.txid; } }, onSendStatusChange); }; @@ -683,9 +696,9 @@ angular.module('copayApp.controllers').controller('confirmController', function( soundService.play('misc/payment_sent.mp3'); } - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("transfer_success", [{ "coin": $scope.wallet.coin, diff --git a/src/js/controllers/customAmount.js b/src/js/controllers/customAmount.js index d74ebca30..5d22d40fb 100644 --- a/src/js/controllers/customAmount.js +++ b/src/js/controllers/customAmount.js @@ -65,6 +65,14 @@ angular.module('copayApp.controllers').controller('customAmountController', func var currency = parsedAmount.currency; $scope.amountUnitStr = parsedAmount.amountUnitStr; + configService.whenAvailable(function (config) { + $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; + + $timeout(function () { + $scope.$apply(); + }); + }); + if (currency != 'BTC' && currency != 'BCH') { // Convert to BTC or BCH var config = configService.getSync().wallet.settings; diff --git a/src/js/controllers/preferencesNotifications.js b/src/js/controllers/preferencesNotifications.js index edfb983b5..a9a833ff7 100644 --- a/src/js/controllers/preferencesNotifications.js +++ b/src/js/controllers/preferencesNotifications.js @@ -76,9 +76,9 @@ angular.module('copayApp.controllers').controller('preferencesNotificationsContr emailService.updateEmail(opts); - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("settings_email_notification_toggle", [{ "toggle": $scope.emailNotifications.value diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index a04820ebd..07b01b974 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -224,6 +224,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', cb(); } } + $scope.walletsWithFunds = profileService.getWallets({hasFunds: true}); }); }); }; diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 3c48818b6..190f1b752 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -144,9 +144,9 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi } $scope.paymentReceivedCoin = $scope.wallet.coin; - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("transfer_success", [{ "coin": $scope.wallet.coin, @@ -232,10 +232,14 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi if (!$scope.wallets[0]) return; - // select first wallet if no wallet selected previously - var selectedWallet = checkSelectedWallet($scope.wallet, $scope.wallets); + var selectedWallet = null; + if (data.stateParams.walletId) { // from walletDetails + selectedWallet = checkSelectedWallet(profileService.getWallet(data.stateParams.walletId), $scope.wallets); + } else { + // select first wallet if no wallet selected previously + selectedWallet = checkSelectedWallet($scope.wallet, $scope.wallets); + } $scope.onWalletSelect(selectedWallet); - $scope.showShareButton = platformInfo.isCordova ? (platformInfo.isIOS ? 'iOS' : 'Android') : null; listeners = [ diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index 4d0636d53..494d63cc5 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -16,7 +16,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct isoCode: config.wallet.settings.alternativeIsoCode }; - $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; + $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay === 'crypto' ? gettextCatalog.getString('Cryptocurrency') : gettextCatalog.getString('Fiat'); // TODO move this to a generic service bitpayAccountService.getAccounts(function(err, data) { diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js index 24237f6c9..d3308ff1e 100644 --- a/src/js/controllers/walletDetails.js +++ b/src/js/controllers/walletDetails.js @@ -12,9 +12,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.isAndroid = platformInfo.isAndroid; $scope.isIOS = platformInfo.isIOS; - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("wallet_details_open", [], [channel]); window.BitAnalytics.LogEventHandlers.postEvent(log); @@ -342,9 +342,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun top = TOP_BALANCE_BUTTON; } - var amountTop = ((amountScale - 0.7) / 0.7) * top; - if (amountTop < -10) { - amountTop = -10; + var amountTop = ((amountScale - 0.80) / 0.80) * top; + if (amountTop < -2) { + amountTop = -2; } if (amountTop > top) { amountTop = top; @@ -353,6 +353,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun var t = amountTop; $scope.altAmountOpacity = (amountHeight - 100) / 80; + $scope.buttonsOpacity = (amountHeight - 140) / 70; $window.requestAnimationFrame(function() { $scope.amountHeight = amountHeight + 'px'; $scope.contentMargin = contentMargin + 'px'; @@ -469,4 +470,30 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun function rgbToHex(r, g, b) { return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); } + $scope.goToSend = function() { + $state.go('tabs.home', { + walletId: $scope.wallet.id + }).then(function () { + $ionicHistory.clearHistory(); + $state.go('tabs.send'); + }); + }; + $scope.goToReceive = function() { + $state.go('tabs.home', { + walletId: $scope.wallet.id + }).then(function () { + $ionicHistory.clearHistory(); + $state.go('tabs.receive', { + walletId: $scope.wallet.id + }); + }); + }; + $scope.goToBuy = function() { + $state.go('tabs.home', { + walletId: $scope.wallet.id + }).then(function () { + $ionicHistory.clearHistory(); + $state.go('tabs.buyandsell'); + }); + }; }); diff --git a/src/js/directives/slideToAcceptSuccess.js b/src/js/directives/slideToAcceptSuccess.js index fbd588bfe..ec6321b95 100644 --- a/src/js/directives/slideToAcceptSuccess.js +++ b/src/js/directives/slideToAcceptSuccess.js @@ -9,12 +9,12 @@ angular.module('copayApp.directives') scope: { isShown: '=slideSuccessShow', onConfirm: '&slideSuccessOnConfirm', - hideOnConfirm: '=slideSuccessHideOnConfirm' + hideOnConfirm: '=slideSuccessHideOnConfirm', + onShare: '=slideSuccessOnShare', }, link: function(scope, element, attrs) { - - scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; - + scope.isCordova = platformInfo.isCordova; + scope.hasShareFunction = typeof scope.onShare === 'function'; var elm = element[0]; elm.style.display = 'none'; scope.$watch('isShown', function() { @@ -32,6 +32,9 @@ angular.module('copayApp.directives') elm.style.display = 'none'; } }; + scope.onShareButtonClick = function() { + scope.onShare(); + } } }; }); diff --git a/src/js/routes.js b/src/js/routes.js index 8a8adc964..dea46a2cf 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -236,7 +236,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }) .state('tabs.receive', { - url: '/receive', + url: '/receive/:walletId', views: { 'tab-receive': { controller: 'tabReceiveController', @@ -1231,9 +1231,9 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }); - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } // Send a log to test diff --git a/src/js/services/bitcoincomService.js b/src/js/services/bitcoincomService.js index 051123111..68fd51a8a 100644 --- a/src/js/services/bitcoincomService.js +++ b/src/js/services/bitcoincomService.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.services').factory('bitcoincomService', function(platformInfo, nextStepsService) { +angular.module('copayApp.services').factory('bitcoincomService', function(gettextCatalog, nextStepsService, platformInfo) { var root = {}; var credentials = {}; @@ -19,42 +19,42 @@ angular.module('copayApp.services').factory('bitcoincomService', function(platfo var cashGamesItem = { name: 'games', - title: 'Bitcoin Cash Games', + title: gettextCatalog.getString('Bitcoin Cash Games'), icon: 'icon-games', href: 'https://cashgames.bitcoin.com' }; var newsItem = { name: 'news', - title: 'News', + title: gettextCatalog.getString('News'), icon: 'icon-news', href: 'https://news.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=News' }; var poolItem = { name: 'pool', - title: 'Mining Pool', + title: gettextCatalog.getString('Mining Pool'), icon: 'icon-mining', href: 'https://pool.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=Pool' }; var toolsItem = { name: 'tools', - title: 'Tools', + title: gettextCatalog.getString('Tools'), icon: 'icon-tools', href: 'https://tools.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=Tools' }; var priceChartItem = { name: 'pricechart', - title: 'Bitcoin Price Charts', + title: gettextCatalog.getString('Bitcoin Price Charts'), icon: 'icon-chart', sref: 'tabs.pricechart', }; var faucetItem = { name: 'faucet', - title: 'Free Bitcoin Cash', + title: gettextCatalog.getString('Free Bitcoin Cash'), icon: 'icon-faucet', href: 'https://free.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=Faucet' }; diff --git a/src/js/services/buyAndSellService.js b/src/js/services/buyAndSellService.js index 65a9a93c7..e35403131 100644 --- a/src/js/services/buyAndSellService.js +++ b/src/js/services/buyAndSellService.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('buyAndSellService', function($log, servicesService, lodash, $ionicScrollDelegate, $timeout) { +angular.module('copayApp.services').factory('buyAndSellService', function(gettextCatalog, $log, servicesService, lodash, $ionicScrollDelegate, $timeout) { var root = {}; var services = []; var linkedServices = []; @@ -23,7 +23,7 @@ angular.module('copayApp.services').factory('buyAndSellService', function($log, if (linkedServices.length == 0) { servicesService.register({ - title: 'Buy Bitcoin', + title: gettextCatalog.getString('Buy Bitcoin'), name: 'buyandsell', icon: 'icon-buy-bitcoin2', sref: 'tabs.buyandsell', diff --git a/src/js/services/clipboardService.js b/src/js/services/clipboardService.js index ebd30c28c..075cb749a 100644 --- a/src/js/services/clipboardService.js +++ b/src/js/services/clipboardService.js @@ -11,10 +11,15 @@ angular.module('copayApp.services').factory('clipboardService', function ($http, cordova.plugins.clipboard.copy(data); } else if (platformInfo.isNW) { nodeWebkitService.writeToClipboard(data); + } else if (navigator && navigator.clipboard) { + $log.debug("Use navigator clipboard.") + navigator.clipboard.writeText(data).catch(err => { + $log.debug("Clipboard writing is not supported in your browser.."); + }); } else if (clipboard.supported) { clipboard.copyText(data); } else { - // No supported + // Not supported return; } }; diff --git a/src/js/services/communityService.js b/src/js/services/communityService.js index 24cc99474..93a4afe5e 100644 --- a/src/js/services/communityService.js +++ b/src/js/services/communityService.js @@ -1,5 +1,5 @@ 'use strict' -angular.module('copayApp.services').factory('communityService', function(configService, $log, lodash) { +angular.module('copayApp.services').factory('communityService', function(configService, gettextCatalog, $log, lodash) { var root = {}; var services = []; @@ -37,14 +37,14 @@ angular.module('copayApp.services').factory('communityService', function(configS var bchRedditItem = { name: 'bchreddit', - title: 'Bitcoin Cash Reddit', + title: gettextCatalog.getString('Bitcoin Cash Reddit'), icon: 'icon-reddit-white', href: 'http://reddit.com/r/btc' }; var bitcoincomTwitterItem = { name: 'bitcoincomTwitter', - title: 'Bitcoin.com Twitter', + title: gettextCatalog.getString('Bitcoin.com Twitter'), icon: 'icon-twitter-white', href: 'https://twitter.com/BTCTN' }; diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index c86d263f2..113289104 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -427,9 +427,9 @@ angular.module('copayApp.services') }, function(err, secret) { if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb); - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("wallet_created", [{ "coin": opts.coin diff --git a/src/js/services/shapeshiftService.js b/src/js/services/shapeshiftService.js index 4a77d8db0..5396f4fa5 100644 --- a/src/js/services/shapeshiftService.js +++ b/src/js/services/shapeshiftService.js @@ -1,4 +1,5 @@ 'use strict'; + angular.module('copayApp.services').factory('shapeshiftService', function ($http, $interval, $log, lodash, moment, ongoingProcess, shapeshiftApiService, storageService, configService, incomingData, platformInfo, servicesService) { var root = {}; root.ShiftState = 'Shift'; @@ -135,17 +136,4 @@ angular.module('copayApp.services').factory('shapeshiftService', function ($http } }); }; - - var servicesItem = { - name: 'shapeshift', - title: 'Shapeshift', - icon: 'icon-shapeshift', - sref: 'tabs.shapeshift', - }; - - var register = function () { - servicesService.register(servicesItem); - }; - register(); - return root; }); diff --git a/src/js/services/txFormatService.js b/src/js/services/txFormatService.js index ebcb3886a..1932ebd2a 100644 --- a/src/js/services/txFormatService.js +++ b/src/js/services/txFormatService.js @@ -201,7 +201,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter, var alternativeIsoCode = config.alternativeIsoCode; // If fiat currency - if (currency != 'BCH' && currency != 'BTC' && currency != 'sat') { + if (currency && currency.toUpperCase() != 'BCH' && currency.toUpperCase() != 'BTC' && currency != 'sat') { amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency; amountSat = rateService.fromFiat(amount, currency, coin).toFixed(0); } else if (currency == 'sat') { diff --git a/src/sass/buttons.scss b/src/sass/buttons.scss index a8512ae64..ab066b734 100644 --- a/src/sass/buttons.scss +++ b/src/sass/buttons.scss @@ -72,5 +72,17 @@ &.activated { color: #FFF; } + &-outline { + @include button-style(transparent, #FFFFFF, #FAFAFA, #FFF, #FFFFFF); + @include button-outline(#FFFFFF); + background: none; + box-shadow: none; + } + } + &-grey-outline { + @include button-style(transparent, #727272, #FAFAFA, #727272, #727272); + @include button-outline(#727272); + background: none; + box-shadow: none; } } \ No newline at end of file diff --git a/src/sass/qr.scss b/src/sass/qr.scss index 62fd12eb7..5df26e37b 100644 --- a/src/sass/qr.scss +++ b/src/sass/qr.scss @@ -5,8 +5,8 @@ qrcode { content: ""; background-size: 100% 100%; display: block; - left: 88px; - margin-top: 88px; + left: calc(50% - 22px); + margin-top: calc(50% - 22px); width: 44px; height: 44px; position:absolute; diff --git a/src/sass/shame.scss b/src/sass/shame.scss index 07ac2dedf..5a17c5f1f 100644 --- a/src/sass/shame.scss +++ b/src/sass/shame.scss @@ -233,6 +233,10 @@ input[type=number] { font-size: 24px; } +.size-25 { + font-size: 25px; +} + .size-28 { font-size: 28px; } diff --git a/src/sass/views/custom-amount.scss b/src/sass/views/custom-amount.scss index b9bf65459..17973101d 100644 --- a/src/sass/views/custom-amount.scss +++ b/src/sass/views/custom-amount.scss @@ -26,16 +26,10 @@ height: 100%; .qr-code { text-align: center; - margin-top: 24vh; - margin-bottom: 7vh; - @media(max-height: 800px) { - margin-top: 18vh; - } - @media(max-height: 700px) { - margin-top: 14vh; - } - @media(max-height: 600px) { - margin-top: 8vh; + margin-top: 6px; + qrcode canvas { + height: 30vh; + max-height: 220px; } } .info { @@ -91,5 +85,34 @@ .address-types { text-align: center; } + + .amount { + margin-top: 20vh; + margin-bottom: 4vh; + @media(max-height: 800px) { + margin-top: 12vh; + margin-bottom: 6vh; + } + @media(max-height: 700px) { + margin-top: 10vh; + margin-bottom: 4vh; + } + @media(max-height: 600px) { + margin-top: 6vh; + margin-bottom: 2vh; + + } + width: 100%; + text-align: center; + //padding-top: 30px; + display: block; + align-items: center; + justify-content: center; + + &-alternative { + line-height: 36px; + } + } + } } diff --git a/src/sass/views/includes/slideToAcceptSuccess.scss b/src/sass/views/includes/slideToAcceptSuccess.scss index 68312c7a4..f64dd6154 100644 --- a/src/sass/views/includes/slideToAcceptSuccess.scss +++ b/src/sass/views/includes/slideToAcceptSuccess.scss @@ -12,12 +12,6 @@ slide-to-accept-success { .slide-success { $duration: 400ms; - &__windows-background { - background: $v-success-bg-color; - height: 100%; - width: 100%; - position: fixed; - } &__background { $start-radius: 5; $scale-factor: 20; @@ -40,9 +34,11 @@ slide-to-accept-success { &__content { position: relative; z-index: 1; - margin-top: -20vh; + margin-top: -10vh; > img { + width: 45vw; + max-width: 166px; margin-bottom: 1.8rem; -webkit-transform: translateY(5rem); transform: translateY(5rem); @@ -59,7 +55,7 @@ slide-to-accept-success { &__header { color: #FFFFFF; - font-size: 26px; + font-size: 29px; -webkit-transform: translateY(5rem); transform: translateY(5rem); opacity: 0; @@ -72,6 +68,26 @@ slide-to-accept-success { opacity: 1; } } + &__share { + transition: transform $duration ease, opacity $duration ease; + transition-delay: 600ms; + opacity: 0; + margin-top: 15vh; + span { + color: #FFF; + font-size: 22px; + height: 28px; + } + img { + height: 28px; + width: auto; + vertical-align: bottom; + margin-right: 4px; + } + &.reveal { + opacity: 0.79; + } + } } &__footer { @@ -98,11 +114,11 @@ slide-to-accept-success { &__btn { display: block; color: #FFFFFF; - font-size: 18px; + font-size: 22px; font-weight: 600; letter-spacing: 2.86px; - padding: 1rem 0 1.1rem; - border-top: 1px solid rgba(255, 255, 255, .45); + padding: 2rem 0 2.1rem; + border-top: 1px solid rgba(255, 255, 255, 0.25); cursor: pointer; } } diff --git a/src/sass/views/tab-home.scss b/src/sass/views/tab-home.scss index 66a2f1d58..708ff4fad 100644 --- a/src/sass/views/tab-home.scss +++ b/src/sass/views/tab-home.scss @@ -69,6 +69,25 @@ } } } + .buttons { + margin: 6px auto -12px; + max-width: 600px; + >.col { + padding: 5px 10px; + margin-bottom: 0; + } + .button { + border: 2px solid; + border-radius: 47px; + padding: 0 15px 0 15px; + text-align: center; + width: 100%; + font-size: 19px; + font-weight: bolder; + min-height: auto; + line-height: 36px; + } + } .wallet-coin-logo { vertical-align: middle; margin-right: 5px; diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss index 9e651f871..6b760bbc4 100644 --- a/src/sass/views/walletDetails.scss +++ b/src/sass/views/walletDetails.scss @@ -135,11 +135,12 @@ &.status-bar { margin-top: 20px; + margin-top: env(safe-area-inset-top); } } .bar-header { border: 0; - background: none; + background: rgb(238, 182, 64); .title, .button { color: #fff; } @@ -153,7 +154,7 @@ ion-content { &.collapsible { - margin-top: 210px; + margin-top: 230px; } padding-top: 0; @@ -190,12 +191,34 @@ transform: translateY(100px); } } + + .send-receive-buttons { + max-width: 600px; + position: absolute; + bottom: 20px; + + >.col { + padding: 5px 10px; + margin-bottom: 0; + } + .button { + border: 2px solid; + border-radius: 47px; + padding: 0 15px 0 15px; + text-align: center; + width: 100%; + font-size: 19px; + font-weight: bolder; + min-height: auto; + line-height: 36px; + } + } } .amount { width: 100%; text-align: center; color: #fff; - height: 210px; + height: 230px; padding-top: 40px; display: block; align-items: center; diff --git a/www/img/icon-sent-successful.svg b/www/img/icon-sent-successful.svg new file mode 100644 index 000000000..070357ddf --- /dev/null +++ b/www/img/icon-sent-successful.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/www/img/icon-share-white.svg b/www/img/icon-share-white.svg new file mode 100644 index 000000000..eeb3e7b6b --- /dev/null +++ b/www/img/icon-share-white.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/www/views/confirm.html b/www/views/confirm.html index 1def16389..0ad56e6c4 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -120,6 +120,7 @@ Payment Sent Proposal Created diff --git a/www/views/customAmount.html b/www/views/customAmount.html index a4f2d57c9..b361a6da9 100644 --- a/www/views/customAmount.html +++ b/www/views/customAmount.html @@ -30,8 +30,22 @@
Return To Address

+
+
+ {{amountUnitStr}} +
+ {{altAmountStr | uppercase}} +
+
+
+ {{altAmountStr | uppercase}} +
+ {{amountUnitStr}} +
+
+
- +
@@ -57,12 +71,6 @@ {{address}}
-
- Amount - - {{amountUnitStr}} - {{altAmountStr}} - -
diff --git a/www/views/includes/slideToAcceptSuccess.html b/www/views/includes/slideToAcceptSuccess.html index 923eab25c..9995001ae 100644 --- a/www/views/includes/slideToAcceptSuccess.html +++ b/www/views/includes/slideToAcceptSuccess.html @@ -1,13 +1,16 @@
+ ng-class="{'fill-screen': fillScreen}">
- +
Payment Sent
+
+
+
+
+ Receive +
+
+
+
+ Buy Bitcoin +
+
+ Send +
+
+
+
diff --git a/www/views/tab-send.html b/www/views/tab-send.html index 7bf4d47be..20198c7f0 100644 --- a/www/views/tab-send.html +++ b/www/views/tab-send.html @@ -15,7 +15,7 @@
-
+
+
+
+ Receive +
+
+
+
+ Buy Bitcoin +
+
+ Send +
+
+
+