Merge pull request #3700 from gabrielbazan7/feat/pushNotifications

push notifications
This commit is contained in:
Matias Alejo Garcia 2016-01-19 19:03:15 -03:00
commit 331bda1106
9 changed files with 211 additions and 46 deletions

View file

@ -106,6 +106,12 @@ if [ ! -d $PROJECT ]; then
cordova plugin add cordova-plugin-customurlscheme --variable URL_SCHEME=bitcoin cordova plugin add cordova-plugin-customurlscheme --variable URL_SCHEME=bitcoin
checkOK checkOK
cordova plugin add phonegap-plugin-push@1.2.3
checkOK
cordova plugin add https://github.com/EddyVerbruggen/LaunchMyApp-PhoneGap-Plugin.git --variable URL_SCHEME=bitcoin
checkOK
cordova plugin add cordova-plugin-inappbrowser cordova plugin add cordova-plugin-inappbrowser
checkOK checkOK

View file

@ -40,7 +40,7 @@
"url": "https://github.com/bitpay/copay/issues" "url": "https://github.com/bitpay/copay/issues"
}, },
"dependencies": { "dependencies": {
"bitcore-wallet-client": "1.2.0", "bitcore-wallet-client": "1.3.0",
"express": "^4.11.2", "express": "^4.11.2",
"fs": "0.0.2", "fs": "0.0.2",
"grunt": "^0.4.5", "grunt": "^0.4.5",

View file

@ -48,6 +48,10 @@
<switch id="spend-unconfirmed" name="spendUnconfirmed" ng-model="spendUnconfirmed" class="green right"></switch> <switch id="spend-unconfirmed" name="spendUnconfirmed" ng-model="spendUnconfirmed" class="green right"></switch>
<div translate>Use Unconfirmed Funds</div> <div translate>Use Unconfirmed Funds</div>
</li> </li>
<li ng-show="mobile">
<switch id="enable-notifications" name="notifications" ng-model="notifications" class="green right"></switch>
<div translate>Enable notifications</div>
</li>
</ul> </ul>
<h4></h4> <h4></h4>
<ul class="no-bullet m0 "> <ul class="no-bullet m0 ">

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettext, gettextCatalog, amMoment, nodeWebkit, addonManager, feeService, isChromeApp, bwsError, txFormatService, uxLanguage, $state, glideraService, isMobile, addressbookService) { angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, pushNotificationsService, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettext, gettextCatalog, amMoment, nodeWebkit, addonManager, feeService, isChromeApp, bwsError, txFormatService, uxLanguage, $state, glideraService, isMobile, addressbookService) {
var self = this; var self = this;
var SOFT_CONFIRMATION_LIMIT = 12; var SOFT_CONFIRMATION_LIMIT = 12;
self.isCordova = isCordova; self.isCordova = isCordova;
@ -11,6 +11,16 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.updatingTxHistory = {}; self.updatingTxHistory = {};
self.prevState = 'walletHome'; self.prevState = 'walletHome';
document.addEventListener('deviceready', function() {
if (isMobile.Android() || isMobile.iOS()) {
storageService.getDeviceToken(function(err, token) {
$timeout(function() {
if (!token) pushNotificationsService.pushNotificationsInit();
}, 5000);
});
}
});
function strip(number) { function strip(number) {
return (parseFloat(number.toPrecision(12))); return (parseFloat(number.toPrecision(12)));
}; };
@ -21,15 +31,24 @@ angular.module('copayApp.controllers').controller('indexController', function($r
self.menu = [{ self.menu = [{
'title': gettext('Receive'), 'title': gettext('Receive'),
'icon': {false:'icon-receive', true: 'icon-receive-active'}, 'icon': {
false: 'icon-receive',
true: 'icon-receive-active'
},
'link': 'receive' 'link': 'receive'
}, { }, {
'title': gettext('Activity'), 'title': gettext('Activity'),
'icon': {false:'icon-activity',true: 'icon-activity-active'}, 'icon': {
false: 'icon-activity',
true: 'icon-activity-active'
},
'link': 'walletHome' 'link': 'walletHome'
}, { }, {
'title': gettext('Send'), 'title': gettext('Send'),
'icon': {false:'icon-send', true: 'icon-send-active'}, 'icon': {
false: 'icon-send',
true: 'icon-send-active'
},
'link': 'send' 'link': 'send'
}]; }];
@ -300,7 +319,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
return cb(null, opts.walletStatus); return cb(null, opts.walletStatus);
else { else {
self.updateError = false; self.updateError = false;
return fc.getStatus({ twoStep : true }, function(err, ret) { return fc.getStatus({
twoStep: true
}, function(err, ret) {
if (err) { if (err) {
self.updateError = bwsError.msg(err, gettext('Could not update Wallet')); self.updateError = bwsError.msg(err, gettext('Could not update Wallet'));
} else { } else {
@ -1263,6 +1284,18 @@ angular.module('copayApp.controllers').controller('indexController', function($r
go.walletHome(); go.walletHome();
}); });
$rootScope.$on('Local/SubscribeNotifications', function(event) {
pushNotificationsService.enableNotifications();
});
$rootScope.$on('Local/UnsubscribeNotifications', function(event, walletId, cb) {
pushNotificationsService.unsubscribe(walletId, function(err, response) {
if (err) $log.warn('Error: ' + err.code);
$log.debug('Unsubscribed: ' + response);
return cb();
});
});
self.debouncedUpdate = lodash.throttle(function() { self.debouncedUpdate = lodash.throttle(function() {
self.updateAll({ self.updateAll({
quiet: true quiet: true

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('preferencesGlobalController', angular.module('copayApp.controllers').controller('preferencesGlobalController',
function($scope, $rootScope, $log, configService, uxLanguage) { function($scope, $rootScope, $log, configService, isMobile, uxLanguage, pushNotificationsService) {
this.init = function() { this.init = function() {
var config = configService.getSync(); var config = configService.getSync();
@ -14,8 +14,12 @@ angular.module('copayApp.controllers').controller('preferencesGlobalController',
$scope.spendUnconfirmed = config.wallet.spendUnconfirmed; $scope.spendUnconfirmed = config.wallet.spendUnconfirmed;
$scope.glideraEnabled = config.glidera.enabled; $scope.glideraEnabled = config.glidera.enabled;
$scope.glideraTestnet = config.glidera.testnet; $scope.glideraTestnet = config.glidera.testnet;
$scope.notifications = config.notifications ? config.notifications.enabled : true;
}; };
if (isMobile.Android() || isMobile.iOS()) $scope.mobile = true;
else $scope.mobile = false;
var unwatchSpendUnconfirmed = $scope.$watch('spendUnconfirmed', function(newVal, oldVal) { var unwatchSpendUnconfirmed = $scope.$watch('spendUnconfirmed', function(newVal, oldVal) {
if (newVal == oldVal) return; if (newVal == oldVal) return;
var opts = { var opts = {
@ -29,6 +33,22 @@ angular.module('copayApp.controllers').controller('preferencesGlobalController',
}); });
}); });
var unwatchNotification = $scope.$watch('notifications', function(newVal, oldVal) {
if (newVal == oldVal) return;
var opts = {
pushNotifications: {
enabled: newVal
}
};
configService.set(opts, function(err) {
if (opts.pushNotifications.enabled)
pushNotificationsService.enableNotifications();
else
pushNotificationsService.disableNotifications();
if (err) $log.debug(err);
});
});
var unwatchGlideraEnabled = $scope.$watch('glideraEnabled', function(newVal, oldVal) { var unwatchGlideraEnabled = $scope.$watch('glideraEnabled', function(newVal, oldVal) {
if (newVal == oldVal) return; if (newVal == oldVal) return;
var opts = { var opts = {

View file

@ -41,6 +41,21 @@ angular.module('copayApp.services').factory('configService', function(storageSer
rates: { rates: {
url: 'https://insight.bitpay.com:443/api/rates', url: 'https://insight.bitpay.com:443/api/rates',
}, },
pushNotifications: {
enabled: true,
config: {
android: {
senderID: '1036948132229',
},
ios: {
alert: 'true',
badge: 'true',
sound: 'true',
},
windows: {},
}
},
}; };
var configCache = null; var configCache = null;

View file

@ -130,8 +130,7 @@ angular.module('copayApp.services')
root.isDisclaimerAccepted(function(val) { root.isDisclaimerAccepted(function(val) {
if (!val) { if (!val) {
return cb(new Error('NONAGREEDDISCLAIMER: Non agreed disclaimer')); return cb(new Error('NONAGREEDDISCLAIMER: Non agreed disclaimer'));
} } else {
else {
return cb(); return cb();
} }
}); });
@ -305,34 +304,38 @@ angular.module('copayApp.services')
root.deleteWalletFC = function(opts, cb) { root.deleteWalletFC = function(opts, cb) {
var fc = root.focusedClient; var fc = root.focusedClient;
var walletId = fc.credentials.walletId; var walletId = fc.credentials.walletId;
$log.debug('Deleting Wallet:', fc.credentials.walletName);
fc.removeAllListeners(); $rootScope.$emit('Local/UnsubscribeNotifications', walletId, function() {
root.profile.credentials = lodash.reject(root.profile.credentials, {
walletId: walletId
});
delete root.walletClients[walletId]; $log.debug('Deleting Wallet:', fc.credentials.walletName);
root.focusedClient = null;
storageService.clearLastAddress(walletId, function(err) { fc.removeAllListeners();
if (err) $log.warn(err); root.profile.credentials = lodash.reject(root.profile.credentials, {
}); walletId: walletId
});
storageService.removeTxHistory(walletId, function(err) { delete root.walletClients[walletId];
if (err) $log.warn(err); root.focusedClient = null;
});
storageService.clearBackupFlag(walletId, function(err) { storageService.clearLastAddress(walletId, function(err) {
if (err) $log.warn(err); if (err) $log.warn(err);
}); });
$timeout(function() { storageService.removeTxHistory(walletId, function(err) {
root.setWalletClients(); if (err) $log.warn(err);
root.setAndStoreFocus(null, function() { });
storageService.storeProfile(root.profile, function(err) {
if (err) return cb(err); storageService.clearBackupFlag(walletId, function(err) {
return cb(); if (err) $log.warn(err);
});
$timeout(function() {
root.setWalletClients();
root.setAndStoreFocus(null, function() {
storageService.storeProfile(root.profile, function(err) {
if (err) return cb(err);
return cb();
});
}); });
}); });
}); });
@ -368,6 +371,7 @@ angular.module('copayApp.services')
return cb(gettext('Wallet already in Copay' + ": ") + w.walletName); return cb(gettext('Wallet already in Copay' + ": ") + w.walletName);
} }
var config = configService.getSync();
var defaults = configService.getDefaults(); var defaults = configService.getDefaults();
var bwsFor = {}; var bwsFor = {};
bwsFor[walletId] = opts.bwsurl || defaults.bws.url; bwsFor[walletId] = opts.bwsurl || defaults.bws.url;
@ -398,6 +402,8 @@ angular.module('copayApp.services')
handleImport(function() { handleImport(function() {
root.setAndStoreFocus(walletId, function() { root.setAndStoreFocus(walletId, function() {
storageService.storeProfile(root.profile, function(err) { storageService.storeProfile(root.profile, function(err) {
if (config.pushNotifications.enabled)
$rootScope.$emit('Local/SubscribeNotifications');
return cb(err, walletId); return cb(err, walletId);
}); });
}); });
@ -542,13 +548,11 @@ angular.module('copayApp.services')
if (err) $log.error(err); if (err) $log.error(err);
return cb(true); return cb(true);
}); });
} } else {
else {
return cb(); return cb();
} }
}); });
} } else {
else {
return cb(); return cb();
} }
}); });
@ -664,7 +668,8 @@ angular.module('copayApp.services')
name: config.aliasFor[c.walletId] || c.walletName, name: config.aliasFor[c.walletId] || c.walletName,
id: c.walletId, id: c.walletId,
network: c.network, network: c.network,
color: config.colorFor[c.walletId] || '#4A90E2' color: config.colorFor[c.walletId] || '#4A90E2',
copayerId: c.copayerId
}; };
}); });
ret = lodash.filter(ret, function(w) { ret = lodash.filter(ret, function(w) {

View file

@ -0,0 +1,74 @@
'use strict';
angular.module('copayApp.services')
.factory('pushNotificationsService', function($http, $log, isMobile, profileService, storageService, configService, lodash) {
var root = {};
var defaults = configService.getDefaults();
root.pushNotificationsInit = function() {
var push = PushNotification.init(defaults.pushNotifications.config);
push.on('registration', function(data) {
$log.debug('Starting push notification registration');
storageService.setDeviceToken(data.registrationId, function() {
root.enableNotifications();
});
});
push.on('notification', function(data) {
$log.debug('Push notification event: ', data.message);
/* data.message,
data.title,
data.count,
data.sound,
data.image,
data.additionalData
*/
});
push.on('error', function(e) {
$log.warn('Error trying to push notifications: ', e);
});
};
root.enableNotifications = function() {
storageService.getDeviceToken(function(err, token) {
lodash.forEach(profileService.getWallets('testnet'), function(wallet) {
var opts = {};
opts.type = isMobile.iOS() ? "ios" : isMobile.Android() ? "android" : null;
opts.token = token;
root.subscribe(opts, wallet.id, function(err, response) {
if (err) $log.warn('Error: ' + err.code);
$log.debug('Suscribed: ' + JSON.stringify(response));
});
});
});
}
root.disableNotifications = function() {
lodash.forEach(profileService.getWallets('testnet'), function(wallet) {
root.unsubscribe(wallet.id, function(err, response) {
if (err) $log.warn('Error: ' + err.code);
$log.debug('Unsubscribed: ' + response);
});
});
}
root.subscribe = function(opts, walletId, cb) {
var walletClient = profileService.getClient(walletId);
walletClient.pushNotificationsSubscribe(opts, function(err, resp) {
if (err) return cb(err);
return cb(null, resp);
});
}
root.unsubscribe = function(walletId, cb) {
var walletClient = profileService.getClient(walletId);
walletClient.pushNotificationsUnsubscribe(function(err, resp) {
if (err) return cb(err);
return cb(null, resp);
});
}
return root;
});

View file

@ -231,6 +231,14 @@ angular.module('copayApp.services')
storage.get('addressbook-' + network, cb); storage.get('addressbook-' + network, cb);
}; };
root.setDeviceToken = function(token, cb) {
storage.set('token', token, cb);
}
root.getDeviceToken = function(cb) {
storage.get('token', cb);
}
root.removeAddressbook = function(network, cb) { root.removeAddressbook = function(network, cb) {
storage.remove('addressbook-' + network, cb); storage.remove('addressbook-' + network, cb);
}; };