Merge pull request #195 from Bitcoin-com/wallet/task/401

Improvement - 401 - Change "Send Feedback" behavior
This commit is contained in:
Jean-Baptiste Dominguez 2018-07-16 12:10:05 +09:00 committed by GitHub
commit 259060276a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 3781 additions and 4352 deletions

View file

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

View file

@ -1,23 +1,23 @@
Secure bitcoin on your own terms with an open source, multisignature wallet from BitPay.
Copay users can hold funds individually or share finances securely with other users with multisignature wallets, which prevent unauthorized payments by requiring multiple approvals. Here are some ways Copay can be used with others:
To save for vacations or joint purchases with friends
To track family spending and allowances
To manage business, club, or organization funds and expenses
We built the following features into this version of Copay for a bitcoin wallet that doesn't compromise on security or accessibility:
Multiple wallet creation and management in-app
Intuitive multisignature security for personal or shared wallets
Easy spending proposal flow for shared wallets and group payments
Hierarchical deterministic (HD) address generation and wallet backups
Device-based security: all private keys are stored locally, not in the cloud
Support for Bitcoin testnet wallets
Synchronous access across all major mobile and desktop platforms
Payment protocol (BIP70-BIP73) support: easily-identifiable payment requests and verifiably secure bitcoin payments
Support for 150+ currency pricing options and unit denomination in BTC or bits
Email notifications for payments and transfers
Customizable wallet naming and background colors
9 supported languages (EN, CS, FR, DE, IT, ES, JA, PL, RU)
Copay is free and open source software run on non-proprietary servers, so there's no need to rely on any company for continuous support. Anyone can review or contribute to Copay's source code on GitHub (https://github.com/bitpay/copay).
Secure bitcoin on your own terms with an open source, multisignature wallet from BitPay.
Copay users can hold funds individually or share finances securely with other users with multisignature wallets, which prevent unauthorized payments by requiring multiple approvals. Here are some ways Copay can be used with others:
To save for vacations or joint purchases with friends
To track family spending and allowances
To manage business, club, or organization funds and expenses
We built the following features into this version of Copay for a bitcoin wallet that doesn't compromise on security or accessibility:
Multiple wallet creation and management in-app
Intuitive multisignature security for personal or shared wallets
Easy spending proposal flow for shared wallets and group payments
Hierarchical deterministic (HD) address generation and wallet backups
Device-based security: all private keys are stored locally, not in the cloud
Support for Bitcoin testnet wallets
Synchronous access across all major mobile and desktop platforms
Payment protocol (BIP70-BIP73) support: easily-identifiable payment requests and verifiably secure bitcoin payments
Support for 150+ currency pricing options and unit denomination in BTC or bits
Email notifications for payments and transfers
Customizable wallet naming and background colors
9 supported languages (EN, CS, FR, DE, IT, ES, JA, PL, RU)
Copay is free and open source software run on non-proprietary servers, so there's no need to rely on any company for continuous support. Anyone can review or contribute to Copay's source code on GitHub (https://github.com/bitpay/copay).

View file

@ -1 +1 @@

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -1,53 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('rateAppController', function($scope, $state, $stateParams, $window, lodash, externalLinkService, configService, platformInfo, feedbackService, ongoingProcess, popupService, appConfigService) {
$scope.score = parseInt($stateParams.score);
$scope.appName = appConfigService.nameCase;
var isAndroid = platformInfo.isAndroid;
var isIOS = platformInfo.isIOS;
var config = configService.getSync();
$scope.skip = function() {
var dataSrc = {
"Email": lodash.values(config.emailFor)[0] || ' ',
"Feedback": ' ',
"Score": $stateParams.score,
"AppVersion": $window.version,
"Platform": ionic.Platform.platform(),
"DeviceVersion": ionic.Platform.version()
};
feedbackService.send(dataSrc, function(err) {
if (err) {
// try to send, but not essential, since the user didn't add a message
$log.warn('Could not send feedback.');
}
});
$state.go('tabs.rate.complete', {
score: $stateParams.score,
skipped: true
});
};
$scope.sendFeedback = function() {
$state.go('tabs.rate.send', {
score: $scope.score
});
};
$scope.goAppStore = function() {
var defaults = configService.getDefaults();
var url;
if (isAndroid)
url = defaults.rateApp.bitcoincom.android;
if (isIOS)
url = defaults.rateApp.bitcoincom.ios;
externalLinkService.open(url);
$state.go('tabs.rate.complete', {
score: $stateParams.score,
skipped: true,
rated: true
});
};
});

View file

@ -1,60 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('rateCardController', function($scope, $state, $timeout, $log, gettextCatalog, platformInfo, storageService, appConfigService) {
$scope.isCordova = platformInfo.isCordova;
$scope.score = 0;
$scope.appName = appConfigService.nameCase;
$scope.goFeedbackFlow = function() {
$scope.hideCard();
if ($scope.isCordova && $scope.score == 5) {
$state.go('tabs.rate.rateApp', {
score: $scope.score
});
} else {
$state.go('tabs.rate.send', {
score: $scope.score
});
}
};
$scope.setScore = function(score) {
$scope.score = score;
switch ($scope.score) {
case 1:
$scope.button_title = gettextCatalog.getString("I think this app is terrible.");
break;
case 2:
$scope.button_title = gettextCatalog.getString("I don't like it");
break;
case 3:
$scope.button_title = gettextCatalog.getString("Meh - it's alright");
break;
case 4:
$scope.button_title = gettextCatalog.getString("I like the app");
break;
case 5:
$scope.button_title = gettextCatalog.getString("This app is fantastic!");
break;
}
$timeout(function() {
$scope.$apply();
});
};
$scope.hideCard = function() {
$log.debug('Feedback card dismissed.')
storageService.getFeedbackInfo(function(error, info) {
var feedbackInfo = JSON.parse(info);
feedbackInfo.sent = true;
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
$scope.showRateCard.value = false;
$timeout(function() {
$scope.$apply();
}, 100);
});
});
}
});

View file

@ -1,102 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, $window, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess, platformInfo, appConfigService) {
$scope.sendFeedback = function(feedback, goHome) {
var config = configService.getSync();
var dataSrc = {
"Email": lodash.values(config.emailFor)[0] || ' ',
"Feedback": goHome ? ' ' : feedback,
"Score": $stateParams.score || ' ',
"AppVersion": $window.version,
"Platform": ionic.Platform.platform(),
"DeviceVersion": ionic.Platform.version()
};
if (!goHome) ongoingProcess.set('sendingFeedback', true);
feedbackService.send(dataSrc, function(err) {
if (goHome) return;
ongoingProcess.set('sendingFeedback', false);
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Feedback could not be submitted. Please try again later.'));
return;
}
if (!$stateParams.score) {
popupService.showAlert(gettextCatalog.getString('Thank you!'), gettextCatalog.getString('A member of the team will review your feedback as soon as possible.'), function() {
$scope.feedback.value = '';
$ionicHistory.nextViewOptions({
disableAnimate: false,
historyRoot: true
});
$ionicHistory.goBack();
}, gettextCatalog.getString('Finish'));
return;
}
$state.go('tabs.rate.complete', {
score: $stateParams.score
});
});
if (goHome) $state.go('tabs.home');
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
if ($scope.score)
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isCordova = platformInfo.isCordova;
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
$scope.feedback = {};
switch ($scope.score) {
case 1:
$scope.reaction = "Ouch!";
$scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.") + ' ' + gettextCatalog.getString("How could we improve your experience?");
break;
case 2:
$scope.reaction = gettextCatalog.getString("Oh no!");
$scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.") + ' ' + gettextCatalog.getString("How could we improve your experience?");
break;
case 3:
$scope.reaction = "Hmm...";
$scope.comment = gettextCatalog.getString("We'd love to do better.") + ' ' + gettextCatalog.getString("How could we improve your experience?");
break;
case 4:
$scope.reaction = gettextCatalog.getString("Thanks!");
$scope.comment = gettextCatalog.getString("That's exciting to hear. We'd love to earn that fifth star from you how could we improve your experience?");
break;
case 5:
$scope.reaction = gettextCatalog.getString("Thank you!");
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve {{appName}}.", {
appName: appConfigService.nameCase
}) + ' ' + gettextCatalog.getString("Is there anything we could do better?");
break;
default:
$scope.justFeedback = true;
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve {{appName}}. How could we improve your experience?", {
appName: appConfigService.nameCase
});
break;
}
});
$scope.$on("$ionicView.afterEnter", function() {
$scope.showForm = true;
});
$scope.goBack = function() {
$ionicHistory.nextViewOptions({
disableAnimate: false,
historyRoot: true
});
$ionicHistory.goBack();
};
});

View file

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('completeController', function($scope, $stateParams, $timeout, $log, $ionicHistory, $state, $ionicNavBarDelegate, $ionicConfig, platformInfo, configService, storageService, lodash, appConfigService, gettextCatalog) {
angular.module('copayApp.controllers').controller('shareAppController', function($scope, $stateParams, $timeout, $log, $ionicHistory, $state, $ionicNavBarDelegate, $ionicConfig, platformInfo, configService, storageService, lodash, appConfigService, gettextCatalog) {
$scope.isCordova = platformInfo.isCordova;
$scope.title = gettextCatalog.getString("Share {{appName}}", {
appName: appConfigService.nameCase
@ -57,28 +57,8 @@ angular.module('copayApp.controllers').controller('completeController', function
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function() {
if (!$scope.fromSettings)
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
$scope.skipped = (data.stateParams && data.stateParams.skipped) ? true : false;
$scope.rated = (data.stateParams && data.stateParams.rated) ? true : false;
$scope.fromSettings = (data.stateParams && data.stateParams.fromSettings) ? true : false;
if (!$scope.fromSettings) {
$ionicNavBarDelegate.showBackButton(false);
} else {
$ionicNavBarDelegate.showBackButton(true);
}
storageService.getFeedbackInfo(function(error, info) {
var feedbackInfo = lodash.isString(info) ? JSON.parse(info) : null;
feedbackInfo.sent = true;
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {});
});
$ionicNavBarDelegate.showBackButton(true);
if (!$scope.isCordova) return;
$scope.animate = true;
@ -133,13 +113,4 @@ angular.module('copayApp.controllers').controller('completeController', function
}
}, 100);
});
$scope.close = function() {
$ionicHistory.nextViewOptions({
disableAnimate: false,
historyRoot: true
});
if ($scope.score == 5) $ionicHistory.goBack(-3);
else $ionicHistory.goBack(-2);
};
});

View file

@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('tabHomeController',
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) {
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) {
var wallet;
var listeners = [];
var notifications = [];
@ -14,7 +14,6 @@ angular.module('copayApp.controllers').controller('tabHomeController',
$scope.isAndroid = platformInfo.isAndroid;
$scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP;
$scope.isNW = platformInfo.isNW;
$scope.showRateCard = {};
$scope.showServices = false;
$scope.bannerIsLoading = true;
$scope.bannerImageUrl = '';
@ -52,43 +51,6 @@ angular.module('copayApp.controllers').controller('tabHomeController',
}
});
}
storageService.getFeedbackInfo(function(error, info) {
if ($scope.isWindowsPhoneApp) {
$scope.showRateCard.value = false;
return;
}
if (!info) {
initFeedBackInfo();
} else {
var feedbackInfo = JSON.parse(info);
//Check if current version is greater than saved version
var currentVersion = $scope.version;
var savedVersion = feedbackInfo.version;
var isVersionUpdated = feedbackService.isVersionUpdated(currentVersion, savedVersion);
if (!isVersionUpdated) {
initFeedBackInfo();
return;
}
var now = moment().unix();
var timeExceeded = (now - feedbackInfo.time) >= 24 * 7 * 60 * 60;
$scope.showRateCard.value = timeExceeded && !feedbackInfo.sent;
$timeout(function() {
$scope.$apply();
});
}
});
function initFeedBackInfo() {
var feedbackInfo = {};
feedbackInfo.time = moment().unix();
feedbackInfo.version = $scope.version;
feedbackInfo.sent = false;
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
$scope.showRateCard.value = false;
});
};
});
$scope.$on("$ionicView.enter", function(event, data) {

View file

@ -45,6 +45,18 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
});
};
$scope.sendFeedback = function() {
var mailToLink = 'mailto:wallet@bitcoin.com?subject=Feedback%20for%20Bitcoin.com%20Wallet';
if (platformInfo.isNW) {
nw.Shell.openExternal(mailToLink);
} else if (platformInfo.isCordova) {
var mailWindow = window.open(mailToLink, '_system');
mailWindow.close(); // XX SP: bugfix for some browsers in cordova to change the view entirely
} else {
window.location.href = mailToLink;
}
};
$scope.openExternalLink = function() {
var appName = appConfigService.name;
var url = appName == 'copay' ? 'https://github.com/bitcoin-com/wallet/issues' : 'https://www.bitcoin.com/wallet-support';

View file

@ -795,63 +795,15 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
fromOnboarding: null
},
})
/*
*
* Feedback
*
*/
.state('tabs.feedback', {
url: '/feedback',
views: {
'tab-settings@tabs': {
templateUrl: 'views/feedback/send.html',
controller: 'sendController'
}
}
})
.state('tabs.shareApp', {
url: '/shareApp/:score/:skipped/:fromSettings',
url: '/shareApp',
views: {
'tab-settings@tabs': {
controller: 'completeController',
templateUrl: 'views/feedback/complete.html'
controller: 'shareAppController',
templateUrl: 'views/shareApp.html'
}
}
})
.state('tabs.rate', {
url: '/rate',
abstract: true
})
.state('tabs.rate.send', {
url: '/send/:score',
views: {
'tab-home@tabs': {
templateUrl: 'views/feedback/send.html',
controller: 'sendController'
}
}
})
.state('tabs.rate.complete', {
url: '/complete/:score/:skipped',
views: {
'tab-home@tabs': {
controller: 'completeController',
templateUrl: 'views/feedback/complete.html'
}
}
})
.state('tabs.rate.rateApp', {
url: '/rateApp/:score',
views: {
'tab-home@tabs': {
controller: 'rateAppController',
templateUrl: 'views/feedback/rateApp.html'
}
}
})
/*
*
* Buy or Sell Bitcoin

View file

@ -1,59 +0,0 @@
'use strict';
angular.module('copayApp.services').factory('feedbackService', function($http, $log, $httpParamSerializer, configService) {
var root = {};
// var URL = "https://script.google.com/macros/s/1pWGRxVSUX9CxPqNAKZTppWHtDvyVtZv9HteY_TRQbWc/exec";
var URL = "https://wallet-data.bitcoin.com/feedback.php";
root.send = function(dataSrc, cb) {
$http(_post(dataSrc)).then(function() {
$log.info("SUCCESS: Feedback sent");
return cb();
}, function(err) {
$log.info("ERROR: Feedback sent anyway.");
return cb(err);
});
};
var _post = function(dataSrc) {
return {
method: 'POST',
url: URL,
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
data: $httpParamSerializer(dataSrc)
};
};
root.isVersionUpdated = function(currentVersion, savedVersion) {
if (!verifyTagFormat(currentVersion))
return 'Cannot verify the format of version tag: ' + currentVersion;
if (!verifyTagFormat(savedVersion))
return 'Cannot verify the format of the saved version tag: ' + savedVersion;
var current = formatTagNumber(currentVersion);
var saved = formatTagNumber(savedVersion);
if (saved.major > current.major || (saved.major == current.major && saved.minor > current.minor))
return false;
return true;
function verifyTagFormat(tag) {
var regex = /^v?\d+\.\d+\.\d+$/i;
return regex.exec(tag);
};
function formatTagNumber(tag) {
var formattedNumber = tag.replace(/^v/i, '').split('.');
return {
major: +formattedNumber[0],
minor: +formattedNumber[1],
patch: +formattedNumber[2]
};
};
};
return root;
});

View file

@ -217,14 +217,6 @@ angular.module('copayApp.services')
});
};
root.setFeedbackInfo = function(feedbackValues, cb) {
storage.set('feedback', feedbackValues, cb);
};
root.getFeedbackInfo = function(cb) {
storage.get('feedback', cb);
};
root.storeFocusedWalletId = function(id, cb) {
storage.set('focusedWalletId', id || '', cb);
};

View file

@ -1,38 +0,0 @@
#rate-app {
background-color: #ffffff;
text-align: center;
.skip-rating {
color: $v-dark-gray;
position: absolute;
top: 5px;
right: 10px;
padding: 15px;
}
.icon-svg > img {
width: 80px;
height: 80px;
margin-top: 15px;
}
.feedback-title {
font-size: 20px;
font-weight: bold;
color: $v-dark-gray;
margin: 80px 50px 10px;
text-align: center;
}
.share-the-love-illustration {
width: 5rem;
margin: 1rem;
}
.subtitle {
padding: 10px 30px 20px 40px;
color: $v-mid-gray;
}
.rate-buttons {
bottom: 0;
width: 100%;
position: absolute;
background-color: $v-subtle-gray;
padding: 30px 0 15px;
}
}

View file

@ -1,18 +0,0 @@
#rate-card {
.item-heading {
font-weight: 700;
}
.row {
border: none;
}
.item-icon-right {
margin: 0;
}
.feedback-flow-button {
margin-bottom: 20px;
}
.icon-svg > img {
height: 1.8rem;
margin-bottom: 5px;
}
}

View file

@ -1,54 +0,0 @@
#send-feedback {
@extend .deflash-blue;
background-color: #ffffff;
.row {
border: none;
}
.skip {
color: rgba(255, 255, 255, 0.3);
}
.feedback-heading {
padding-top: 20px
}
.feedback-title {
padding-left: 10px;
font-size: 20px;
font-weight: bold;
color: $v-dark-gray;
}
.rating {
text-align: right;
padding-right: 15px;
}
.comment {
padding: 0 20px 20px;
font-size: 1rem;
line-height: 1.5em;
font-weight: 300;
color: $v-dark-gray;
}
.user-feedback {
border-top: 1px solid $v-subtle-gray;
border-bottom: 1px solid $v-subtle-gray;
padding: 20px;
width: 100%;
margin-bottom: 20px;
-webkit-appearance: none;
}
.send-feedback-star {
height: 1rem;
margin-left: 5px;
}
.form-fade-in {
opacity: 0;
animation-name: fadeIn;
animation-duration: .5s;
animation-fill-mode: forwards;
animation-timing-function: ease-in;
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}

View file

@ -1,6 +1,6 @@
#complete {
#share-app {
background-color: #fff;
.complete-layout {
.share-app-layout {
display: flex;
flex-direction: column;
height: 100%;
@ -22,17 +22,6 @@
width: 5rem;
margin: 1rem;
}
.send-feedback-illustration {
height: 16rem;
margin: 1rem;
}
.feedback-title {
font-size: 20px;
font-weight: bold;
color: $v-dark-gray;
margin: 20px 10px;
text-align: center;
}
.subtitle {
padding: 10px 30px 20px;
text-align: center;

View file

@ -22,10 +22,7 @@
@import "wallet-backup-phrase";
@import "zero-state";
@import "onboarding/onboarding";
@import "feedback/rateCard";
@import "feedback/send";
@import "feedback/complete";
@import "feedback/rateApp";
@import "shareApp";
@import "includes/actionSheet";
@import "export";
@import "import";

View file

@ -1,21 +0,0 @@
<ion-view id="rate-app" hide-tabs>
<ion-content scroll="false">
<a class="skip-rating" ng-click="skip()" translate>Not now</a>
<div class="feedback-title" translate>Thank you!</div>
<img src="img/ico-positive-feedback.svg" class="share-the-love-illustration"/>
<div class="subtitle">
<span translate>5-star ratings help us get {{appName}} into more hands, and more users means more resources can be committed to the app!</span>
</div>
<div class="subtitle">
<span class="text-bold" translate>Would you be willing to rate {{appName}} in the app store?</span>
</div>
<div class="rate-buttons">
<button type="submit" class="button button-standard button-primary" ng-click="goAppStore()">
<span translate>Rate on the app store</span>
</button>
<button type="submit" class="button button-standard button-secondary button-clear" ng-click="sendFeedback()">
<span translate>Send us feedback instead</span>
</button>
</div>
</ion-content>
</ion-view>

View file

@ -1,43 +0,0 @@
<div class="card" id="rate-card" ng-controller="rateCardController">
<div class="item item-icon-right item-heading">
<span translate>How do you like {{appName}}?</span>
<a ng-click="hideCard()" ><i class="icon ion-ios-close-empty close-home-tip"></i></a>
</div>
<div class="row item item-sub" ng-class="{'row-margin': isModal}">
<div class="col col-20" ng-click="setScore(1)">
<i class="icon icon-svg">
<img ng-if="1 <= score" src="img/ico-star-filled.svg"/>
<img ng-if="1 > score" src="img/ico-star.svg"/>
</i>
</div>
<div class="col col-20" ng-click="setScore(2)">
<i class="icon icon-svg">
<img ng-if="2 <= score" src="img/ico-star-filled.svg"/>
<img ng-if="2 > score" src="img/ico-star.svg"/>
</i>
</div>
<div class="col col-20" ng-click="setScore(3)">
<i class="icon icon-svg">
<img ng-if="3 <= score" src="img/ico-star-filled.svg"/>
<img ng-if="3 > score" src="img/ico-star.svg"/>
</i>
</div>
<div class="col col-20" ng-click="setScore(4)">
<i class="icon icon-svg">
<img ng-if="4 <= score" src="img/ico-star-filled.svg"/>
<img ng-if="4 > score" src="img/ico-star.svg"/>
</i>
</div>
<div class="col col-20" ng-click="setScore(5)">
<i class="icon icon-svg">
<img ng-if="5 == score" src="img/ico-star-filled.svg"/>
<img ng-if="5 > score" src="img/ico-star.svg"/>
</i>
</div>
</div>
<div class="feedback-flow-button" ng-if="button_title">
<button type="submit" class="button button-standard button-primary" ng-click="goFeedbackFlow()">
<span>{{button_title}}</span>
</button>
</div>
</div>

View file

@ -1,48 +0,0 @@
<ion-view id="send-feedback" hide-tabs>
<ion-nav-bar class="bar-royal">
<ion-nav-title>{{'Send Feedback' | translate}}</ion-nav-title>
<ion-nav-buttons side="primary">
<button ng-show="score" class="button no-border ng-hide" ng-click="sendFeedback(null, true)" translate>
Cancel
</button>
<button ng-show="!score || fromSettings" class="button back-button button-clear ng-hide" ng-click="goBack()">
<i class="icon ion-ios-arrow-thin-left"></i>
</button>
</ion-nav-buttons>
<ion-nav-buttons side="secondary">
<button ng-show="isCordova" ng-disabled="!feedback.value" class="button no-border" type="submit" ng-click="sendFeedback(feedback.value)" translate>
Send
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content class="has-header" scroll="false">
<div class="row item item-sub feedback-heading">
<div class="col col-50">
<div class="feedback-title" ng-if="!justFeedback">
<span>{{reaction}}</span>
</div>
</div>
<div class="col col-50 rating" ng-if="score">
<img class="send-feedback-star" ng-if="1 <= score" src="img/ico-star-filled.svg"/>
<img class="send-feedback-star" ng-if="1 > score" src="img/ico-star.svg"/>
<img class="send-feedback-star" ng-if="2 <= score" src="img/ico-star-filled.svg"/>
<img class="send-feedback-star" ng-if="2 > score" src="img/ico-star.svg"/>
<img class="send-feedback-star" ng-if="3 <= score" src="img/ico-star-filled.svg"/>
<img class="send-feedback-star" ng-if="3 > score" src="img/ico-star.svg"/>
<img class="send-feedback-star" ng-if="4 <= score" src="img/ico-star-filled.svg"/>
<img class="send-feedback-star" ng-if="4 > score" src="img/ico-star.svg"/>
<img class="send-feedback-star" ng-if="5 == score" src="img/ico-star-filled.svg"/>
<img class="send-feedback-star" ng-if="5 > score" src="img/ico-star.svg"/>
</div>
</div>
<div class="comment">
<span>{{comment}}</span>
</div>
<div ng-if="showForm" class="form-fade-in">
<textarea class="user-feedback" ng-model="feedback.value" rows="5" placeholder="{{'Your ideas, feedback, or comments' | translate}}"></textarea>
<button ng-show="!isCordova" ng-disabled="!feedback.value" type="submit" class="button button-standard button-primary" ng-click="sendFeedback(feedback.value)" translate>
Send
</button>
</div>
</ion-content>
</ion-view>

View file

@ -1,32 +1,16 @@
<ion-view id="complete" hide-tabs>
<ion-view id="share-app" hide-tabs>
<ion-nav-bar class="bar-royal">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-title>{{title}}</ion-nav-title>
<ion-nav-buttons side="secondary">
<button ng-show="!fromSettings" class="button no-border" ng-click="close()" translate>
Finish
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content scroll="false">
<div class="complete-layout">
<div class="complete-layout__expand" ng-class="{'fade-in': !animate || socialsharing}">
<div ng-show="fromSettings">
<img src="img/ico-positive-feedback.svg" class="share-the-love-illustration"/>
<div class="subtitle" translate>Share the love by inviting your friends.</div>
</div>
<div ng-show="!fromSettings">
<div class="feedback-title" translate>Thank you!</div>
<div class="subtitle" ng-show="!skipped" translate>A member of the team will review your feedback as soon as possible.</div>
<div ng-if="score <= 3 || !socialsharing">
<div class="subtitle" translate>If you have additional feedback, please let us know by tapping the "Send feedback" option in the Settings tab.</div>
<img src="img/illustration-send-feedback.png" class="send-feedback-illustration"/>
</div>
<div class="subtitle" ng-if="score > 3 && socialsharing" translate>Share the love by inviting your friends.</div>
</div>
<div class="share-app-layout">
<div class="share-app-layout__expand fade-in">
<img src="img/ico-positive-feedback.svg" class="share-the-love-illustration"/>
<div class="subtitle" translate>Share the love by inviting your friends.</div>
</div>
<div class="share-buttons" ng-if="score > 3 && socialsharing" ng-class="{'slide-up': socialsharing }">
<div class="share-buttons slide-up">
<div class="share-buttons__action" ng-show="facebook" ng-click="shareFacebook()">
<i class="icon socialsharing-icon">
<img src="img/social-icons/ico-social-facebook.svg"/>
@ -66,4 +50,4 @@
</div>
</div>
</ion-content>
</ion-view>
</ion-view>

View file

@ -22,8 +22,6 @@
</div>
</div>
<div class="ng-hide" ng-show="showRateCard.value" ng-include="'views/feedback/rateCard.html'"></div>
<div class="list card homeTip" ng-if="homeTip">
<div class="item item-icon-right item-heading">
<div class="title" translate>

View file

@ -22,14 +22,14 @@
<img src="img/icon-link.svg" class="bg just-a-hint"/>
</i>
</a>
<a class="item item-icon-left item-icon-right" ui-sref="tabs.feedback">
<a class="item item-icon-left item-icon-right" ng-click="sendFeedback()">
<i class="icon big-icon-svg">
<img src="img/icon-send-feedback.svg" class="bg"/>
</i>
<span>{{'Send Feedback' | translate}}</span>
<i class="icon bp-arrow-right"></i>
</a>
<a ng-if="isCordova && !isWindowsPhoneApp" class="item item-icon-left item-icon-right" ui-sref="tabs.shareApp({score: 4, skipped: true, fromSettings: true})">
<a ng-if="isCordova && !isWindowsPhoneApp" class="item item-icon-left item-icon-right" ui-sref="tabs.shareApp">
<i class="icon big-icon-svg">
<img src="img/icon-heart.svg" class="bg"/>
</i>