Merge branch 'master' of github.com:bitpay/copay into improveWalletDetails
This commit is contained in:
commit
d02affadd1
29 changed files with 793 additions and 200 deletions
|
|
@ -26,7 +26,10 @@ angular.module('copayApp.controllers').controller('activityController',
|
||||||
|
|
||||||
$scope.openNotificationModal = function(n) {
|
$scope.openNotificationModal = function(n) {
|
||||||
if (n.txid) {
|
if (n.txid) {
|
||||||
openTxModal(n);
|
$state.transitionTo('tabs.wallet.tx-details', {
|
||||||
|
txid: n.txid,
|
||||||
|
walletId: n.walletId
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
var txp = lodash.find($scope.txps, {
|
var txp = lodash.find($scope.txps, {
|
||||||
id: n.txpId
|
id: n.txpId
|
||||||
|
|
@ -46,35 +49,4 @@ angular.module('copayApp.controllers').controller('activityController',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var openTxModal = function(n) {
|
|
||||||
var wallet = profileService.getWallet(n.walletId);
|
|
||||||
|
|
||||||
ongoingProcess.set('loadingTxInfo', true);
|
|
||||||
walletService.getTx(wallet, n.txid, function(err, tx) {
|
|
||||||
ongoingProcess.set('loadingTxInfo', false);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
$log.error(err);
|
|
||||||
return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tx) {
|
|
||||||
$log.warn('No tx found');
|
|
||||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.wallet = wallet;
|
|
||||||
$scope.btx = lodash.cloneDeep(tx);
|
|
||||||
$state.transitionTo('tabs.wallet.tx-details', {
|
|
||||||
txid: $scope.btx.txid,
|
|
||||||
walletId: $scope.walletId
|
|
||||||
});
|
|
||||||
|
|
||||||
walletService.getTxNote(wallet, n.txid, function(err, note) {
|
|
||||||
if (err) $log.warn('Could not fetch transaction note: ' + err);
|
|
||||||
$scope.btx.note = note;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
34
src/js/controllers/feedback/rateAppStore.js
Normal file
34
src/js/controllers/feedback/rateAppStore.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('rateAppStoreController', function($scope, $state, $stateParams, externalLinkService, configService, gettextCatalog, platformInfo) {
|
||||||
|
$scope.score = parseInt($stateParams.score);
|
||||||
|
var isAndroid = platformInfo.isAndroid;
|
||||||
|
var isIOS = platformInfo.isIOS;
|
||||||
|
var isWP = platformInfo.isWP;
|
||||||
|
var config = configService.getSync();
|
||||||
|
|
||||||
|
$scope.skip = function() {
|
||||||
|
$state.go('feedback.thanks', {
|
||||||
|
score: $scope.score,
|
||||||
|
skipped: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.sendFeedback = function() {
|
||||||
|
$state.go('feedback.sendFeedback', {
|
||||||
|
score: $scope.score
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.goAppStore = function() {
|
||||||
|
var url;
|
||||||
|
if (isAndroid) url = config.rateApp.android;
|
||||||
|
if (isIOS) url = config.rateApp.ios;
|
||||||
|
// if (isWP) url = config.rateApp.ios; TODO
|
||||||
|
var title = gettextCatalog.getString('Rate the app');
|
||||||
|
var message = gettextCatalog.getString('You must go to the official website of the app to rate it');
|
||||||
|
var okText = gettextCatalog.getString('Go');
|
||||||
|
var cancelText = gettextCatalog.getString('Cancel');
|
||||||
|
externalLinkService.open(url, true, title, message, okText, cancelText);
|
||||||
|
};
|
||||||
|
});
|
||||||
61
src/js/controllers/feedback/rateCard.js
Normal file
61
src/js/controllers/feedback/rateCard.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('rateCardController', function($scope, $state, $timeout, gettextCatalog, platformInfo, storageService) {
|
||||||
|
|
||||||
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
|
|
||||||
|
$scope.goFeedbackFlow = function() {
|
||||||
|
if ($scope.isModal) {
|
||||||
|
$scope.rateModal.hide();
|
||||||
|
$scope.rateModal.remove();
|
||||||
|
}
|
||||||
|
if ($scope.isCordova && $scope.score == 5) {
|
||||||
|
$state.go('feedback.rateAppStore', {
|
||||||
|
score: $scope.score
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$state.go('feedback.sendFeedback', {
|
||||||
|
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() {
|
||||||
|
if ($scope.isModal) {
|
||||||
|
$scope.rateModal.hide();
|
||||||
|
$scope.rateModal.remove();
|
||||||
|
} else {
|
||||||
|
storageService.setRateCardFlag('true', function() {
|
||||||
|
$scope.hideRateCard.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
52
src/js/controllers/feedback/sendFeedback.js
Normal file
52
src/js/controllers/feedback/sendFeedback.js
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('sendFeedbackController', function($scope, $state, $log, $stateParams, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) {
|
||||||
|
$scope.score = parseInt($stateParams.score);
|
||||||
|
switch ($scope.score) {
|
||||||
|
case 1:
|
||||||
|
$scope.reaction = gettextCatalog.getString("Ouch!");
|
||||||
|
$scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$scope.reaction = gettextCatalog.getString("Oh no!");
|
||||||
|
$scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$scope.reaction = gettextCatalog.getString("Thanks!");
|
||||||
|
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay wallet.");
|
||||||
|
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.");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
$scope.reaction = gettextCatalog.getString("Feedback!");
|
||||||
|
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay wallet.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.sendFeedback = function(feedback, skip) {
|
||||||
|
|
||||||
|
var config = configService.getSync();
|
||||||
|
|
||||||
|
var dataSrc = {
|
||||||
|
"Email": lodash.values(config.emailFor)[0] || ' ',
|
||||||
|
"Feedback": skip ? ' ' : feedback,
|
||||||
|
"Score": $stateParams.score
|
||||||
|
};
|
||||||
|
|
||||||
|
ongoingProcess.set('sendingFeedback', true);
|
||||||
|
feedbackService.send(dataSrc, function(err) {
|
||||||
|
ongoingProcess.set('sendingFeedback', false);
|
||||||
|
if (err) {
|
||||||
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send feedback'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$state.go('feedback.thanks', {
|
||||||
|
score: $stateParams.score,
|
||||||
|
skipped: skip
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
76
src/js/controllers/feedback/thanks.js
Normal file
76
src/js/controllers/feedback/thanks.js
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('thanksController', function($scope, $stateParams, $timeout, $log, platformInfo, configService, storageService) {
|
||||||
|
$scope.score = parseInt($stateParams.score);
|
||||||
|
$scope.skipped = $stateParams.skipped == 'false' ? false : true;
|
||||||
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
|
var config = configService.getSync();
|
||||||
|
|
||||||
|
$scope.shareFacebook = function() {
|
||||||
|
window.plugins.socialsharing.shareViaFacebook(config.download.url, null, null, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.shareTwitter = function() {
|
||||||
|
window.plugins.socialsharing.shareVia($scope.shareTwitterVia, config.download.url, null, null, null, null, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.shareGooglePlus = function() {
|
||||||
|
window.plugins.socialsharing.shareVia($scope.shareGooglePlusVia, config.download.url, null, null, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.shareEmail = function() {
|
||||||
|
window.plugins.socialsharing.shareViaEmail(config.download.url, null, null, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.shareWhatsapp = function() {
|
||||||
|
window.plugins.socialsharing.shareViaWhatsApp(config.download.url, null, null, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.shareMessage = function() {
|
||||||
|
window.plugins.socialsharing.shareViaSMS(config.download.url, null, null, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
storageService.setRateCardFlag('true', function() {});
|
||||||
|
if (!$scope.isCordova) return;
|
||||||
|
|
||||||
|
window.plugins.socialsharing.available(function(isAvailable) {
|
||||||
|
// the boolean is only false on iOS < 6
|
||||||
|
$scope.socialsharing = isAvailable;
|
||||||
|
if (isAvailable) {
|
||||||
|
window.plugins.socialsharing.canShareVia('com.apple.social.facebook', 'msg', null, null, null, function(e) {
|
||||||
|
$scope.facebook = true;
|
||||||
|
}, function(e) {
|
||||||
|
$log.debug('facebook error: ' + e);
|
||||||
|
$scope.facebook = false;
|
||||||
|
});
|
||||||
|
window.plugins.socialsharing.canShareVia('com.twitter.android', 'msg', null, null, null, function(e) {
|
||||||
|
$scope.shareTwitterVia = 'com.twitter.android';
|
||||||
|
$scope.twitter = true;
|
||||||
|
}, function(e) {
|
||||||
|
$log.debug('twitter error: ' + e);
|
||||||
|
$scope.twitter = false;
|
||||||
|
});
|
||||||
|
window.plugins.socialsharing.canShareVia('com.google.android.apps.plus', 'msg', null, null, null, function(e) {
|
||||||
|
$scope.shareGooglePlusVia = 'com.google.android.apps.plus';
|
||||||
|
$scope.googleplus = true;
|
||||||
|
}, function(e) {
|
||||||
|
$log.debug('googlePlus error: ' + e);
|
||||||
|
$scope.googleplus = false;
|
||||||
|
});
|
||||||
|
window.plugins.socialsharing.canShareViaEmail(function(e) {
|
||||||
|
$scope.email = true;
|
||||||
|
}, function(e) {
|
||||||
|
$log.debug('email error: ' + e);
|
||||||
|
$scope.email = false;
|
||||||
|
});
|
||||||
|
window.plugins.socialsharing.canShareVia('whatsapp', 'msg', null, null, null, function(e) {
|
||||||
|
$scope.whatsapp = true;
|
||||||
|
}, function(e) {
|
||||||
|
$log.debug('whatsapp error: ' + e);
|
||||||
|
$scope.whatsapp = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('welcomeController', function($scope, $state, $timeout, $ionicConfig, $log, profileService, startupService) {
|
angular.module('copayApp.controllers').controller('welcomeController', function($scope, $state, $timeout, $ionicConfig, $log, profileService, startupService, storageService) {
|
||||||
|
|
||||||
$ionicConfig.views.swipeBackEnabled(false);
|
$ionicConfig.views.swipeBackEnabled(false);
|
||||||
|
|
||||||
|
|
@ -19,7 +19,13 @@ angular.module('copayApp.controllers').controller('welcomeController', function(
|
||||||
$log.debug('Creating profile');
|
$log.debug('Creating profile');
|
||||||
profileService.createProfile(function(err) {
|
profileService.createProfile(function(err) {
|
||||||
if (err) $log.warn(err);
|
if (err) $log.warn(err);
|
||||||
|
setProfileCreationTime();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function setProfileCreationTime() {
|
||||||
|
var now = moment().unix() * 1000 + 24 * 60 * 60 * 1000;
|
||||||
|
storageService.setProfileCreationTime(now, function() {});
|
||||||
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,27 +13,100 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
$scope.isCordova = platformInfo.isCordova;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
$scope.isAndroid = platformInfo.isAndroid;
|
$scope.isAndroid = platformInfo.isAndroid;
|
||||||
$scope.isNW = platformInfo.isNW;
|
$scope.isNW = platformInfo.isNW;
|
||||||
|
$scope.hideRateCard = {};
|
||||||
|
|
||||||
$scope.$on("$ionicView.afterEnter", function() {
|
$scope.$on("$ionicView.afterEnter", function() {
|
||||||
startupService.ready();
|
startupService.ready();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!$scope.homeTip) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
storageService.getHomeTipAccepted(function(error, value) {
|
if (!$scope.homeTip) {
|
||||||
$scope.homeTip = (value == 'accepted') ? false : true;
|
storageService.getHomeTipAccepted(function(error, value) {
|
||||||
});
|
$scope.homeTip = (value == 'accepted') ? false : true;
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if ($scope.isNW) {
|
if ($scope.isNW) {
|
||||||
latestReleaseService.checkLatestRelease(function(err, newRelease) {
|
latestReleaseService.checkLatestRelease(function(err, newRelease) {
|
||||||
if (err) {
|
if (err) {
|
||||||
$log.warn(err);
|
$log.warn(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newRelease) $scope.newRelease = true;
|
if (newRelease) $scope.newRelease = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
storageService.getProfileCreationTime(function(error, time) {
|
||||||
|
var now = moment().unix() * 1000;
|
||||||
|
storageService.getRateCardFlag(function(error, value) {
|
||||||
|
$scope.hideRateCard.value = (value == 'true' || (time - now) > 0) ? true : false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
|
updateAllWallets();
|
||||||
|
|
||||||
|
addressbookService.list(function(err, ab) {
|
||||||
|
if (err) $log.error(err);
|
||||||
|
$scope.addressbook = ab || {};
|
||||||
|
});
|
||||||
|
|
||||||
|
listeners = [
|
||||||
|
$rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
||||||
|
var wallet = profileService.getWallet(walletId);
|
||||||
|
updateWallet(wallet);
|
||||||
|
if ($scope.recentTransactionsEnabled) getNotifications();
|
||||||
|
}),
|
||||||
|
$rootScope.$on('Local/TxAction', function(e, walletId) {
|
||||||
|
$log.debug('Got action for wallet ' + walletId);
|
||||||
|
var wallet = profileService.getWallet(walletId);
|
||||||
|
updateWallet(wallet);
|
||||||
|
if ($scope.recentTransactionsEnabled) getNotifications();
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
configService.whenAvailable(function() {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if ($scope.recentTransactionsEnabled) getNotifications();
|
||||||
|
|
||||||
|
if ($scope.bitpayCardEnabled) bitpayCardCache();
|
||||||
|
$timeout(function() {
|
||||||
|
$ionicScrollDelegate.resize();
|
||||||
|
$scope.$apply();
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.leave", function(event, data) {
|
||||||
|
lodash.each(listeners, function(x) {
|
||||||
|
x();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.leave", function(event, data) {
|
||||||
|
lodash.each(listeners, function(x) {
|
||||||
|
x();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||||
|
|
@ -43,7 +116,10 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
wallet = profileService.getWallet(n.walletId);
|
wallet = profileService.getWallet(n.walletId);
|
||||||
|
|
||||||
if (n.txid) {
|
if (n.txid) {
|
||||||
openTxModal(n);
|
$state.transitionTo('tabs.wallet.tx-details', {
|
||||||
|
txid: n.txid,
|
||||||
|
walletId: n.walletId
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
var txp = lodash.find($scope.txps, {
|
var txp = lodash.find($scope.txps, {
|
||||||
id: n.txpId
|
id: n.txpId
|
||||||
|
|
@ -65,37 +141,6 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var openTxModal = function(n) {
|
|
||||||
wallet = profileService.getWallet(n.walletId);
|
|
||||||
|
|
||||||
ongoingProcess.set('loadingTxInfo', true);
|
|
||||||
walletService.getTx(wallet, n.txid, function(err, tx) {
|
|
||||||
ongoingProcess.set('loadingTxInfo', false);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
$log.error(err);
|
|
||||||
return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tx) {
|
|
||||||
$log.warn('No tx found');
|
|
||||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.wallet = wallet;
|
|
||||||
$scope.btx = lodash.cloneDeep(tx);
|
|
||||||
$state.transitionTo('tabs.wallet.tx-details', {
|
|
||||||
txid: $scope.btx.txid,
|
|
||||||
walletId: $scope.walletId
|
|
||||||
});
|
|
||||||
|
|
||||||
walletService.getTxNote(wallet, n.txid, function(err, note) {
|
|
||||||
if (err) $log.warn('Could not fetch transaction note: ' + err);
|
|
||||||
$scope.btx.note = note;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.openWallet = function(wallet) {
|
$scope.openWallet = function(wallet) {
|
||||||
if (!wallet.isComplete()) {
|
if (!wallet.isComplete()) {
|
||||||
return $state.go('tabs.copayers', {
|
return $state.go('tabs.copayers', {
|
||||||
|
|
@ -117,6 +162,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
$scope.txpsN = n;
|
$scope.txpsN = n;
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$ionicScrollDelegate.resize();
|
$ionicScrollDelegate.resize();
|
||||||
|
$scope.$apply();
|
||||||
}, 100);
|
}, 100);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
@ -141,25 +187,6 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!$scope.recentTransactionsEnabled) return;
|
|
||||||
$scope.fetchingNotifications = true;
|
|
||||||
profileService.getNotifications({
|
|
||||||
limit: 3
|
|
||||||
}, function(err, n) {
|
|
||||||
if (err) {
|
|
||||||
$log.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$scope.fetchingNotifications = false;
|
|
||||||
$scope.notifications = n;
|
|
||||||
|
|
||||||
$timeout(function() {
|
|
||||||
$ionicScrollDelegate.resize();
|
|
||||||
$scope.$apply();
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var updateWallet = function(wallet) {
|
var updateWallet = function(wallet) {
|
||||||
|
|
@ -171,20 +198,22 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
}
|
}
|
||||||
wallet.status = status;
|
wallet.status = status;
|
||||||
updateTxps();
|
updateTxps();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (!$scope.recentTransactionsEnabled) return;
|
var getNotifications = function() {
|
||||||
|
profileService.getNotifications({
|
||||||
$scope.fetchingNotifications = true;
|
limit: 3
|
||||||
profileService.getNotifications({
|
}, function(err, n) {
|
||||||
limit: 3
|
if (err) {
|
||||||
}, function(err, notifications) {
|
$log.error(err);
|
||||||
$scope.fetchingNotifications = false;
|
return;
|
||||||
if (err) {
|
}
|
||||||
$log.error(err);
|
$scope.notifications = n;
|
||||||
return;
|
$timeout(function() {
|
||||||
}
|
$ionicScrollDelegate.resize();
|
||||||
$scope.notifications = notifications;
|
$scope.$apply();
|
||||||
});
|
}, 100);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -241,57 +270,4 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
}, 300);
|
}, 300);
|
||||||
updateAllWallets();
|
updateAllWallets();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data) {
|
|
||||||
updateAllWallets();
|
|
||||||
|
|
||||||
addressbookService.list(function(err, ab) {
|
|
||||||
if (err) $log.error(err);
|
|
||||||
$scope.addressbook = ab || {};
|
|
||||||
});
|
|
||||||
|
|
||||||
listeners = [
|
|
||||||
$rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
|
||||||
var wallet = profileService.getWallet(walletId);
|
|
||||||
updateWallet(wallet);
|
|
||||||
}),
|
|
||||||
$rootScope.$on('Local/TxAction', function(e, walletId) {
|
|
||||||
$log.debug('Got action for wallet ' + walletId);
|
|
||||||
var wallet = profileService.getWallet(walletId);
|
|
||||||
updateWallet(wallet);
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
configService.whenAvailable(function() {
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if ($scope.bitpayCardEnabled) bitpayCardCache();
|
|
||||||
$timeout(function() {
|
|
||||||
$ionicScrollDelegate.resize();
|
|
||||||
$scope.$apply();
|
|
||||||
}, 10);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.leave", function(event, data) {
|
|
||||||
lodash.each(listeners, function(x) {
|
|
||||||
x();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, $window, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService) {
|
angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, $window, $ionicModal, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService) {
|
||||||
|
|
||||||
var updateConfig = function() {
|
var updateConfig = function() {
|
||||||
|
|
||||||
|
|
@ -32,4 +32,15 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
|
||||||
updateConfig();
|
updateConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.openRateModal = function() {
|
||||||
|
$scope.isModal = true;
|
||||||
|
$ionicModal.fromTemplateUrl('views/feedback/rateCard.html', {
|
||||||
|
scope: $scope,
|
||||||
|
backdropClickToClose: false,
|
||||||
|
hardwareBackButtonClose: false
|
||||||
|
}).then(function(modal) {
|
||||||
|
$scope.rateModal = modal;
|
||||||
|
$scope.rateModal.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('txDetailsController', function($log, $timeout, $ionicHistory, $scope, $stateParams, walletService, lodash, gettextCatalog, profileService, configService, externalLinkService, popupService) {
|
angular.module('copayApp.controllers').controller('txDetailsController', function($log, $ionicHistory, $scope, walletService, lodash, gettextCatalog, profileService, configService, externalLinkService, popupService, ongoingProcess) {
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
$scope.title = gettextCatalog.getString('Transaction');
|
$scope.title = gettextCatalog.getString('Transaction');
|
||||||
|
|
@ -9,11 +9,13 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
$scope.copayerId = $scope.wallet.credentials.copayerId;
|
$scope.copayerId = $scope.wallet.credentials.copayerId;
|
||||||
$scope.isShared = $scope.wallet.credentials.n > 1;
|
$scope.isShared = $scope.wallet.credentials.n > 1;
|
||||||
|
|
||||||
walletService.getTx($scope.wallet, $stateParams.txid, function(err, tx) {
|
ongoingProcess.set('loadingTxInfo', true);
|
||||||
|
walletService.getTx($scope.wallet, data.stateParams.txid, function(err, tx) {
|
||||||
|
ongoingProcess.set('loadingTxInfo', false);
|
||||||
if (err) {
|
if (err) {
|
||||||
$log.warn('Could not get tx');
|
$log.warn('Could not get tx');
|
||||||
$ionicHistory.goBack();
|
$ionicHistory.goBack();
|
||||||
return;
|
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found'));
|
||||||
}
|
}
|
||||||
$scope.btx = tx;
|
$scope.btx = tx;
|
||||||
if ($scope.btx.action != 'invalid') {
|
if ($scope.btx.action != 'invalid') {
|
||||||
|
|
@ -130,6 +132,27 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
return n.substring(0, 4);
|
return n.substring(0, 4);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.getFiatRate = function() {
|
||||||
|
if ($scope.rateDate) return;
|
||||||
|
var alternativeIsoCode = $scope.wallet.status.alternativeIsoCode;
|
||||||
|
$scope.loadingRate = true;
|
||||||
|
$scope.wallet.getFiatRate({
|
||||||
|
code: alternativeIsoCode,
|
||||||
|
ts: $scope.btx.time * 1000
|
||||||
|
}, function(err, res) {
|
||||||
|
$scope.loadingRate = false;
|
||||||
|
if (err) {
|
||||||
|
$log.debug('Could not get historic rate');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (res && res.rate) {
|
||||||
|
$scope.rateDate = res.fetchedOn;
|
||||||
|
$scope.rateStr = res.rate + ' ' + alternativeIsoCode;
|
||||||
|
$scope.$apply();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.cancel = function() {
|
$scope.cancel = function() {
|
||||||
$scope.txDetailsModal.hide();
|
$scope.txDetailsModal.hide();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -720,13 +720,50 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Buy or Sell Bitcoin
|
* Feedback
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.state('feedback', {
|
||||||
|
url: '/feedback',
|
||||||
|
abstract: true,
|
||||||
|
template: '<ion-nav-view name="feedback"></ion-nav-view>'
|
||||||
|
})
|
||||||
|
.state('feedback.sendFeedback', {
|
||||||
|
url: '/sendFeedback/:score',
|
||||||
|
views: {
|
||||||
|
'feedback': {
|
||||||
|
controller: 'sendFeedbackController',
|
||||||
|
templateUrl: 'views/feedback/sendFeedback.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.state('feedback.thanks', {
|
||||||
|
url: '/thanks/:score/:skipped',
|
||||||
|
views: {
|
||||||
|
'feedback': {
|
||||||
|
controller: 'thanksController',
|
||||||
|
templateUrl: 'views/feedback/thanks.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.state('feedback.rateAppStore', {
|
||||||
|
url: '/rateAppStore/:score',
|
||||||
|
views: {
|
||||||
|
'feedback': {
|
||||||
|
controller: 'rateAppStoreController',
|
||||||
|
templateUrl: 'views/feedback/rateAppStore.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Buy or Sell Bitcoin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
.state('tabs.buyandsell', {
|
.state('tabs.buyandsell', {
|
||||||
url: '/buyandsell',
|
url: '/buyandsell',
|
||||||
views: {
|
views: {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,16 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
||||||
url: 'https://bws.bitpay.com/bws/api',
|
url: 'https://bws.bitpay.com/bws/api',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
download: {
|
||||||
|
url: 'https://bitpay.com/wallet',
|
||||||
|
},
|
||||||
|
|
||||||
|
rateApp: {
|
||||||
|
ios: 'https://itunes.apple.com/app/bitpay-secure-bitcoin-wallet/id1149581638',
|
||||||
|
android: 'https://play.google.com/store/apps/details?id=com.bitpay.wallet',
|
||||||
|
wp: ''
|
||||||
|
},
|
||||||
|
|
||||||
// wallet default config
|
// wallet default config
|
||||||
wallet: {
|
wallet: {
|
||||||
requiredCopayers: 2,
|
requiredCopayers: 2,
|
||||||
|
|
|
||||||
28
src/js/services/feedbackService.js
Normal file
28
src/js/services/feedbackService.js
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
'use strict';
|
||||||
|
angular.module('copayApp.services').factory('feedbackService', function($http, $log, $httpParamSerializer, configService) {
|
||||||
|
var root = {};
|
||||||
|
var URL = "https://script.google.com/macros/s/AKfycbybtvNSQKUfgzgXcj3jYLlvCKrcBoktjiJ1V8_cwd2yVkpUBGe3/exec";
|
||||||
|
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return root;
|
||||||
|
});
|
||||||
|
|
@ -33,6 +33,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
'validatingWallet': gettext('Validating wallet integrity...'),
|
'validatingWallet': gettext('Validating wallet integrity...'),
|
||||||
'validatingWords': gettext('Validating recovery phrase...'),
|
'validatingWords': gettext('Validating recovery phrase...'),
|
||||||
'loadingTxInfo': gettext('Loading transaction info...'),
|
'loadingTxInfo': gettext('Loading transaction info...'),
|
||||||
|
'sendingFeedback': gettext('Sending feedback...'),
|
||||||
};
|
};
|
||||||
|
|
||||||
root.clear = function() {
|
root.clear = function() {
|
||||||
|
|
@ -64,7 +65,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
|
|
||||||
var showName = $filter('translate')(processNames[name] || name);
|
var showName = $filter('translate')(processNames[name] || name);
|
||||||
|
|
||||||
if(customHandler) {
|
if (customHandler) {
|
||||||
customHandler(processName, showName, isOn);
|
customHandler(processName, showName, isOn);
|
||||||
} else if (root.onGoingProcessName) {
|
} else if (root.onGoingProcessName) {
|
||||||
if (isCordova) {
|
if (isCordova) {
|
||||||
|
|
|
||||||
|
|
@ -795,7 +795,7 @@ angular.module('copayApp.services')
|
||||||
root.getNotifications = function(opts, cb) {
|
root.getNotifications = function(opts, cb) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
var TIME_STAMP = 60 * 60 * 24 * 7;
|
var TIME_STAMP = 60 * 60 * 6;
|
||||||
var MAX = 100;
|
var MAX = 100;
|
||||||
|
|
||||||
var typeFilter = {
|
var typeFilter = {
|
||||||
|
|
@ -861,26 +861,25 @@ angular.module('copayApp.services')
|
||||||
|
|
||||||
var finale = shown; // GROUPING DISABLED!
|
var finale = shown; // GROUPING DISABLED!
|
||||||
|
|
||||||
// var finale = [],
|
var finale = [],
|
||||||
// prev;
|
prev;
|
||||||
//
|
|
||||||
//
|
|
||||||
// // Item grouping... DISABLED.
|
// Item grouping... DISABLED.
|
||||||
//
|
|
||||||
// // REMOVE (if we want 1-to-1 notification) ????
|
// REMOVE (if we want 1-to-1 notification) ????
|
||||||
// lodash.each(shown, function(x) {
|
lodash.each(shown, function(x) {
|
||||||
// if (prev && prev.walletId === x.walletId && prev.txpId && prev.txpId === x.txpId && prev.creatorId && prev.creatorId === x.creatorId) {
|
if (prev && prev.walletId === x.walletId && prev.txpId && prev.txpId === x.txpId && prev.creatorId && prev.creatorId === x.creatorId) {
|
||||||
// prev.types.push(x.type);
|
prev.types.push(x.type);
|
||||||
// prev.data = lodash.assign(prev.data, x.data);
|
prev.data = lodash.assign(prev.data, x.data);
|
||||||
// prev.txid = prev.txid || x.txid;
|
prev.txid = prev.txid || x.txid;
|
||||||
// prev.amountStr = prev.amountStr || x.amountStr;
|
prev.amountStr = prev.amountStr || x.amountStr;
|
||||||
// prev.creatorName = prev.creatorName || x.creatorName;
|
prev.creatorName = prev.creatorName || x.creatorName;
|
||||||
// } else {
|
} else {
|
||||||
// finale.push(x);
|
finale.push(x);
|
||||||
// prev = x;
|
prev = x;
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
//
|
|
||||||
|
|
||||||
var u = bwcService.getUtils();
|
var u = bwcService.getUtils();
|
||||||
lodash.each(finale, function(x) {
|
lodash.each(finale, function(x) {
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,14 @@ angular.module('copayApp.services')
|
||||||
storage.remove('profile', cb);
|
storage.remove('profile', cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.setProfileCreationTime = function(time, cb) {
|
||||||
|
storage.set('profileCreationTime', time, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
root.getProfileCreationTime = function(cb) {
|
||||||
|
storage.get('profileCreationTime', cb);
|
||||||
|
};
|
||||||
|
|
||||||
root.storeFocusedWalletId = function(id, cb) {
|
root.storeFocusedWalletId = function(id, cb) {
|
||||||
storage.set('focusedWalletId', id || '', cb);
|
storage.set('focusedWalletId', id || '', cb);
|
||||||
};
|
};
|
||||||
|
|
@ -203,6 +211,14 @@ angular.module('copayApp.services')
|
||||||
storage.set('homeTip', val, cb);
|
storage.set('homeTip', val, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.getRateCardFlag = function(cb) {
|
||||||
|
storage.get('rateCardFlag', cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
root.setRateCardFlag = function(val, cb) {
|
||||||
|
storage.set('rateCardFlag', val, cb);
|
||||||
|
};
|
||||||
|
|
||||||
root.setHideBalanceFlag = function(walletId, val, cb) {
|
root.setHideBalanceFlag = function(walletId, val, cb) {
|
||||||
storage.set('hideBalance-' + walletId, val, cb);
|
storage.set('hideBalance-' + walletId, val, cb);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
27
src/sass/views/feedback/rateAppStore.scss
Normal file
27
src/sass/views/feedback/rateAppStore.scss
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#rate-app-store {
|
||||||
|
background-color: #ffffff;
|
||||||
|
.skip {
|
||||||
|
margin: 10px;
|
||||||
|
color: #667;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $dark-gray;
|
||||||
|
margin: 40px 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
padding: 10px 30px 20px 40px;
|
||||||
|
}
|
||||||
|
.buttons {
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
background-color: $subtle-gray;
|
||||||
|
.button {
|
||||||
|
margin-top: 40px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/sass/views/feedback/rateCard.scss
Normal file
22
src/sass/views/feedback/rateCard.scss
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#rate-card {
|
||||||
|
.stars {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: none;
|
||||||
|
.button {
|
||||||
|
background-color: #fff;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
height:10px;
|
||||||
|
width:10px;
|
||||||
|
}
|
||||||
|
.gold {
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
.subtle-gray {
|
||||||
|
color: $subtle-gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.feedback-flow-button {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/sass/views/feedback/sendFeedBack.scss
Normal file
39
src/sass/views/feedback/sendFeedBack.scss
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#send-feedback {
|
||||||
|
background-color: #ffffff;
|
||||||
|
.skip {
|
||||||
|
margin: 20px 20px 10px;
|
||||||
|
color: #667;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $dark-gray;
|
||||||
|
}
|
||||||
|
.star {
|
||||||
|
a {
|
||||||
|
font-size: 25px;
|
||||||
|
padding: 20px;
|
||||||
|
.gold {
|
||||||
|
color: #ffd700;
|
||||||
|
}
|
||||||
|
.subtle-gray {
|
||||||
|
color: $subtle-gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.comment {
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5em;
|
||||||
|
font-weight: 300;
|
||||||
|
color: $dark-gray;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
padding: 20px;
|
||||||
|
border-top: 1px solid $subtle-gray;
|
||||||
|
padding: 20px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/sass/views/feedback/thanks.scss
Normal file
44
src/sass/views/feedback/thanks.scss
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#thanks-feedback {
|
||||||
|
background-color: #ffffff;
|
||||||
|
.item-heading {
|
||||||
|
border-style: none;
|
||||||
|
margin-top: 10px;
|
||||||
|
a {
|
||||||
|
color: $dark-gray;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: $dark-gray;
|
||||||
|
margin: 20px 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
padding: 10px 30px 20px 40px;
|
||||||
|
.image {
|
||||||
|
text-align: center;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.share-buttons {
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
background-color: $subtle-gray;
|
||||||
|
.row {
|
||||||
|
margin: 20px 0px 20px;
|
||||||
|
span {
|
||||||
|
margin-top: 15px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -125,6 +125,6 @@
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@
|
||||||
@import "wallet-backup-phrase";
|
@import "wallet-backup-phrase";
|
||||||
@import "zero-state";
|
@import "zero-state";
|
||||||
@import "onboarding/onboarding";
|
@import "onboarding/onboarding";
|
||||||
|
@import "feedback/rateCard";
|
||||||
|
@import "feedback/sendFeedback";
|
||||||
|
@import "feedback/thanks";
|
||||||
|
@import "feedback/rateAppStore";
|
||||||
@import "includes/actionSheet";
|
@import "includes/actionSheet";
|
||||||
@import "export";
|
@import "export";
|
||||||
@import "import";
|
@import "import";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<ion-view>
|
<ion-view>
|
||||||
<ion-nav-bar class="bar-royal">
|
<ion-nav-bar class="bar-royal">
|
||||||
<ion-nav-title>
|
<ion-nav-title>
|
||||||
{{'Recent Activity'|translate}}
|
{{'Recent Transactions'|translate}}
|
||||||
</ion-nav-title>
|
</ion-nav-title>
|
||||||
<ion-nav-back-button>
|
<ion-nav-back-button>
|
||||||
</ion-nav-back-button>
|
</ion-nav-back-button>
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<div ng-if="fetchingNotifications" class="updatingHistory">
|
<div ng-if="fetchingNotifications" class="updatingHistory">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<ion-spinner class="spinner-dark" icon="lines"></ion-spinner>
|
<ion-spinner class="spinner-dark" icon="lines"></ion-spinner>
|
||||||
<div translate>Updating activity. Please stand by</div>
|
<div translate>Updating... Please stand by</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item" ng-show="!notifications[0]">
|
<div class="item" ng-show="!notifications[0]">
|
||||||
<span translate>No recent activity</span>
|
<span translate>No recent transactions</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
27
www/views/feedback/rateAppStore.html
Normal file
27
www/views/feedback/rateAppStore.html
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<ion-view id="rate-app-store">
|
||||||
|
<ion-content scroll="false">
|
||||||
|
<a class="right skip" ng-click="skip()">Skip</a>
|
||||||
|
<div class="title">
|
||||||
|
<span translate>Thank you!</span>
|
||||||
|
<div>
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="subtitle">
|
||||||
|
<span translate>5-star ratings help us get BitPay Wallet into more hands, and more users means more resoucers can be committed to the app!</span>
|
||||||
|
</div>
|
||||||
|
<div class="subtitle">
|
||||||
|
<span class="text-bold" translate>Would you be willing to rate BitPay Wallet in the app store?</span>
|
||||||
|
</div>
|
||||||
|
<div class="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-primary button-clear" ng-click="sendFeedback()">
|
||||||
|
<span translate>Send us feedback instead</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-view>
|
||||||
18
www/views/feedback/rateCard.html
Normal file
18
www/views/feedback/rateCard.html
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<div id="rate-card" ng-class="{'popup-modal': isModal}" ng-controller="rateCardController">
|
||||||
|
<div class="item item-icon-right item-heading">
|
||||||
|
<span translate>How do you like BitPay Wallet?</span>
|
||||||
|
<a ng-click="hideCard()" ><i class="icon ion-ios-close-empty close-home-tip"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="stars item item-sub">
|
||||||
|
<button class="button icon ion-android-star" ng-click="setScore(1)" ng-class="{'gold': 1 <= score, 'subtle-gray': 1 > score}"></button>
|
||||||
|
<button class="button icon ion-android-star" ng-click="setScore(2)" ng-class="{'gold': 2 <= score, 'subtle-gray': 2 > score}"></button>
|
||||||
|
<button class="button icon ion-android-star" ng-click="setScore(3)" ng-class="{'gold': 3 <= score, 'subtle-gray': 3 > score}"></button>
|
||||||
|
<button class="button icon ion-android-star" ng-click="setScore(4)" ng-class="{'gold': 4 <= score, 'subtle-gray': 4 > score}"></button>
|
||||||
|
<button class="button icon ion-android-star" ng-click="setScore(5)" ng-class="{'gold': 5 == score, 'subtle-gray': 5 > score}"></button>
|
||||||
|
</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>
|
||||||
26
www/views/feedback/sendFeedback.html
Normal file
26
www/views/feedback/sendFeedback.html
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<ion-view id="send-feedback">
|
||||||
|
<a class="right skip" ng-click="sendFeedback(null,true)" href translate>Skip</a>
|
||||||
|
<ion-content class="has-header" scroll="false">
|
||||||
|
<div class="title">
|
||||||
|
<span>{{reaction}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="star">
|
||||||
|
<a><i ng-class="{'gold': 1 <= score, 'subtle-gray': 1 > score}" class="icon ion-android-star"></i></a>
|
||||||
|
<a><i ng-class="{'gold': 2 <= score, 'subtle-gray': 2 > score}" class="icon ion-android-star"></i></a>
|
||||||
|
<a><i ng-class="{'gold': 3 <= score, 'subtle-gray': 3 > score}" class="icon ion-android-star"></i></a>
|
||||||
|
<a><i ng-class="{'gold': 4 <= score, 'subtle-gray': 4 > score}" class="icon ion-android-star"></i></a>
|
||||||
|
<a><i ng-class="{'gold': 5 == score, 'subtle-gray': 5 > score}" class="icon ion-android-star"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="comment">
|
||||||
|
<span translate>{{comment}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<textarea ng-model="feedback" placeholder="Is there anything we could do to improve your experience?" row="40"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="padding">
|
||||||
|
<button ng-disabled="!feedback" type="submit" class="button button-full button-primary" ng-click="sendFeedback(feedback, false)" translate>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-view>
|
||||||
79
www/views/feedback/thanks.html
Normal file
79
www/views/feedback/thanks.html
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
<ion-view id="thanks-feedback">
|
||||||
|
<ion-content scroll="false">
|
||||||
|
<div class="item item-icon-right item-heading">
|
||||||
|
<a ui-sref="tabs.home()"><i class="icon ion-ios-close-empty close-home-tip"></i></a>
|
||||||
|
</div>
|
||||||
|
<div ng-show="skipped && isCordova">
|
||||||
|
<div class="title" translate>Invite friends to BitPay Wallet!</div>
|
||||||
|
<div>
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<span translate>Share the love by inviting your friends.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-show="!skipped || !isCordova">
|
||||||
|
<div class="title" translate>Thank you!</div>
|
||||||
|
<div class="subtitle">
|
||||||
|
<span translate>A member of the team will review your feedback as soon as possible.</span>
|
||||||
|
</div>
|
||||||
|
<div class="subtitle" ng-if="score <= 3 || !isCordova">
|
||||||
|
<span translate>If you have additional feedback, please let us know by tapping the "Send feedback" option in the Settings tab.</span>
|
||||||
|
<div class="image">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center" ng-if="score > 3 && isCordova">
|
||||||
|
<span translate>Share the love by inviting your friends.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="share-buttons" ng-if="isCordova && score > 3">
|
||||||
|
<div class="ng-hide" ng-show="socialsharing" ng-if="score >= 4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="ng-hide" ng-show="facebook" ng-click="shareFacebook()">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
<span>Facebook</span>
|
||||||
|
</div>
|
||||||
|
<div class="ng-hide" ng-show="twitter" ng-click="shareTwitter()">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
<span>Twitter</span>
|
||||||
|
</div>
|
||||||
|
<div class="ng-hide" ng-show="googleplus" ng-click="shareGooglePlus()">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
<span>Google+</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="ng-hide" ng-show="email" ng-click="shareEmail()">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
<span>Email</span>
|
||||||
|
</div>
|
||||||
|
<div class="ng-hide" ng-show="whatsapp" ng-click="shareWhatsapp()">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
<span>Whatsapp</span>
|
||||||
|
</div>
|
||||||
|
<div ng-click="shareMessage()">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/address-book-add.svg"/>
|
||||||
|
</i>
|
||||||
|
<span>Message</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-view>
|
||||||
|
|
@ -10,9 +10,12 @@
|
||||||
spinner="ios-small"
|
spinner="ios-small"
|
||||||
on-refresh="onRefresh()">
|
on-refresh="onRefresh()">
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<div class="release" ng-show="newRelease" ng-click="openExternalLink('https://github.com/bitpay/copay/releases/latest', true, 'Update Available', 'An update to this app is available. For your security, please update to the latest version.', 'View Update', 'Go Back')">
|
<div class="release ng-hide" ng-show="newRelease" ng-click="openExternalLink('https://github.com/bitpay/copay/releases/latest', true, 'Update Available', 'An update to this app is available. For your security, please update to the latest version.', 'View Update', 'Go Back')">
|
||||||
<span translate>An update to this app is available</span><span><i class="icon bp-arrow-right"></i></span>
|
<span translate>An update to this app is available</span><span><i class="icon bp-arrow-right"></i></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="list card ng-hide" ng-show="!hideRateCard.value">
|
||||||
|
<span ng-include="'views/feedback/rateCard.html'"></span>
|
||||||
|
</div>
|
||||||
<div class="list card homeTip" ng-if="homeTip">
|
<div class="list card homeTip" ng-if="homeTip">
|
||||||
<div class="item item-icon-right item-heading">
|
<div class="item item-icon-right item-heading">
|
||||||
<a ng-click="hideHomeTip()"><i class="icon ion-ios-close-empty close-home-tip"></i></a>
|
<a ng-click="hideHomeTip()"><i class="icon ion-ios-close-empty close-home-tip"></i></a>
|
||||||
|
|
@ -47,10 +50,6 @@
|
||||||
<span translate>Recent Transactions</span>
|
<span translate>Recent Transactions</span>
|
||||||
<i class="icon bp-arrow-right"></i>
|
<i class="icon bp-arrow-right"></i>
|
||||||
</a>
|
</a>
|
||||||
<span ng-if="fetchingNotifications" class="item text-center">
|
|
||||||
<ion-spinner icon="lines"></ion-spinner>
|
|
||||||
<div translate>Updating activity...</div>
|
|
||||||
</span>
|
|
||||||
<a class="item item-sub activity" ng-repeat="notification in notifications" ng-click="openNotificationModal(notification)">
|
<a class="item item-sub activity" ng-repeat="notification in notifications" ng-click="openNotificationModal(notification)">
|
||||||
<span ng-include="'views/includes/walletActivity.html'"></span>
|
<span ng-include="'views/includes/walletActivity.html'"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<img src="img/icon-link.svg" class="bg just-a-hint"/>
|
<img src="img/icon-link.svg" class="bg just-a-hint"/>
|
||||||
</i>
|
</i>
|
||||||
</a>
|
</a>
|
||||||
<a class="ng-hide item item-icon-left item-icon-right" ng-hide="true">
|
<a class="item item-icon-left item-icon-right" ng-click="openRateModal()">
|
||||||
<i class="icon big-icon-svg">
|
<i class="icon big-icon-svg">
|
||||||
<img src="img/icon-send-feedback.svg" class="bg"/>
|
<img src="img/icon-send-feedback.svg" class="bg"/>
|
||||||
</i>
|
</i>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="amount-label">
|
<div class="amount-label">
|
||||||
<div class="amount">{{displayAmount}} <span class="unit">{{displayUnit}}</span></div>
|
<div class="amount">{{displayAmount}} <span class="unit">{{displayUnit}}</span></div>
|
||||||
<div class="alternative">{{btx.alternativeAmountStr}}</div>
|
<div class="alternative" ng-click="getFiatRate(); showRate = !showRate">
|
||||||
|
<span ng-show="!showRate">{{btx.alternativeAmountStr}}</span>
|
||||||
|
<span ng-show="showRate">
|
||||||
|
<span ng-show="!loadingRate">{{rateStr}} ({{rateDate | amDateFormat:'MM/DD/YYYY HH:mm a'}})</span>
|
||||||
|
<span ng-show="loadingRate">...</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue