fix status
This commit is contained in:
parent
8bcb332276
commit
2897aa3e4c
9 changed files with 21 additions and 155 deletions
|
|
@ -1,295 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').
|
||||
factory('notification', function($timeout, platformInfo) {
|
||||
|
||||
var isCordova = platformInfo.isCordova;
|
||||
var notifications = [];
|
||||
|
||||
/*
|
||||
ls.getItem('notifications', function(err, data) {
|
||||
if (data) {
|
||||
notifications = JSON.parse(data);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
var queue = [];
|
||||
var settings = {
|
||||
info: {
|
||||
duration: 6000,
|
||||
enabled: true
|
||||
},
|
||||
funds: {
|
||||
duration: 7000,
|
||||
enabled: true
|
||||
},
|
||||
version: {
|
||||
duration: 60000,
|
||||
enabled: true
|
||||
},
|
||||
warning: {
|
||||
duration: 7000,
|
||||
enabled: true
|
||||
},
|
||||
error: {
|
||||
duration: 7000,
|
||||
enabled: true
|
||||
},
|
||||
success: {
|
||||
duration: 5000,
|
||||
enabled: true
|
||||
},
|
||||
progress: {
|
||||
duration: 0,
|
||||
enabled: true
|
||||
},
|
||||
custom: {
|
||||
duration: 35000,
|
||||
enabled: true
|
||||
},
|
||||
details: true,
|
||||
localStorage: false,
|
||||
html5Mode: false,
|
||||
html5DefaultIcon: 'img/favicon.ico'
|
||||
};
|
||||
|
||||
function html5Notify(icon, title, content, ondisplay, onclose) {
|
||||
if (window.webkitNotifications && window.webkitNotifications.checkPermission() === 0) {
|
||||
if (!icon) {
|
||||
icon = 'img/favicon.ico';
|
||||
}
|
||||
var noti = window.webkitNotifications.createNotification(icon, title, content);
|
||||
if (typeof ondisplay === 'function') {
|
||||
noti.ondisplay = ondisplay;
|
||||
}
|
||||
if (typeof onclose === 'function') {
|
||||
noti.onclose = onclose;
|
||||
}
|
||||
noti.show();
|
||||
} else {
|
||||
settings.html5Mode = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
|
||||
/* ========== SETTINGS RELATED METHODS =============*/
|
||||
|
||||
disableHtml5Mode: function() {
|
||||
settings.html5Mode = false;
|
||||
},
|
||||
|
||||
disableType: function(notificationType) {
|
||||
settings[notificationType].enabled = false;
|
||||
},
|
||||
|
||||
enableHtml5Mode: function() {
|
||||
// settings.html5Mode = true;
|
||||
settings.html5Mode = this.requestHtml5ModePermissions();
|
||||
},
|
||||
|
||||
enableType: function(notificationType) {
|
||||
settings[notificationType].enabled = true;
|
||||
},
|
||||
|
||||
getSettings: function() {
|
||||
return settings;
|
||||
},
|
||||
|
||||
toggleType: function(notificationType) {
|
||||
settings[notificationType].enabled = !settings[notificationType].enabled;
|
||||
},
|
||||
|
||||
toggleHtml5Mode: function() {
|
||||
settings.html5Mode = !settings.html5Mode;
|
||||
},
|
||||
|
||||
requestHtml5ModePermissions: function() {
|
||||
if (window.webkitNotifications) {
|
||||
if (window.webkitNotifications.checkPermission() === 0) {
|
||||
return true;
|
||||
} else {
|
||||
window.webkitNotifications.requestPermission(function() {
|
||||
if (window.webkitNotifications.checkPermission() === 0) {
|
||||
settings.html5Mode = true;
|
||||
} else {
|
||||
settings.html5Mode = false;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/* ============ QUERYING RELATED METHODS ============*/
|
||||
|
||||
getAll: function() {
|
||||
// Returns all notifications that are currently stored
|
||||
return notifications;
|
||||
},
|
||||
|
||||
getQueue: function() {
|
||||
return queue;
|
||||
},
|
||||
|
||||
/* ============== NOTIFICATION METHODS ==============*/
|
||||
|
||||
info: function(title, content, userData) {
|
||||
return this.awesomeNotify('info', 'fi-info', title, content, userData);
|
||||
},
|
||||
|
||||
funds: function(title, content, userData) {
|
||||
return this.awesomeNotify('funds', 'icon-receive', title, content, userData);
|
||||
},
|
||||
|
||||
version: function(title, content, severe) {
|
||||
return this.awesomeNotify('version', severe ? 'fi-alert' : 'fi-flag', title, content);
|
||||
},
|
||||
|
||||
error: function(title, content, userData) {
|
||||
return this.awesomeNotify('error', 'fi-x', title, content, userData);
|
||||
},
|
||||
|
||||
success: function(title, content, userData) {
|
||||
return this.awesomeNotify('success', 'fi-check', title, content, userData);
|
||||
},
|
||||
|
||||
warning: function(title, content, userData) {
|
||||
return this.awesomeNotify('warning', 'fi-alert', title, content, userData);
|
||||
},
|
||||
|
||||
new: function(title, content, userData) {
|
||||
return this.awesomeNotify('warning', 'fi-plus', title, content, userData);
|
||||
},
|
||||
|
||||
sent: function(title, content, userData) {
|
||||
return this.awesomeNotify('warning', 'icon-paperplane', title, content, userData);
|
||||
},
|
||||
|
||||
awesomeNotify: function(type, icon, title, content, userData) {
|
||||
/**
|
||||
* Supposed to wrap the makeNotification method for drawing icons using font-awesome
|
||||
* rather than an image.
|
||||
*
|
||||
* Need to find out how I'm going to make the API take either an image
|
||||
* resource, or a font-awesome icon and then display either of them.
|
||||
* Also should probably provide some bits of color, could do the coloring
|
||||
* through classes.
|
||||
*/
|
||||
// image = '<i class="icon-' + image + '"></i>';
|
||||
return this.makeNotification(type, false, icon, title, content, userData);
|
||||
},
|
||||
|
||||
notify: function(image, title, content, userData) {
|
||||
// Wraps the makeNotification method for displaying notifications with images
|
||||
// rather than icons
|
||||
return this.makeNotification('custom', image, true, title, content, userData);
|
||||
},
|
||||
|
||||
makeNotification: function(type, image, icon, title, content, userData) {
|
||||
var notification = {
|
||||
'type': type,
|
||||
'image': image,
|
||||
'icon': icon,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'timestamp': +new Date(),
|
||||
'userData': userData
|
||||
};
|
||||
|
||||
notifications.push(notification);
|
||||
|
||||
if (settings.html5Mode) {
|
||||
html5Notify(image, title, content, function() {
|
||||
// inner on display function
|
||||
}, function() {
|
||||
// inner on close function
|
||||
});
|
||||
}
|
||||
|
||||
//this is done because html5Notify() changes the variable settings.html5Mode
|
||||
if (!settings.html5Mode) {
|
||||
queue.push(notification);
|
||||
$timeout(function removeFromQueueTimeout() {
|
||||
queue.splice(queue.indexOf(notification), 1);
|
||||
}, settings[type].duration);
|
||||
}
|
||||
|
||||
// Mobile notification
|
||||
if (window && window.navigator && window.navigator.vibrate) {
|
||||
window.navigator.vibrate([200, 100, 200]);
|
||||
};
|
||||
|
||||
if (document.hidden && (type == 'info' || type == 'funds') && !isCordova) {
|
||||
new window.Notification(title, {
|
||||
body: content,
|
||||
icon: 'img/notification.png'
|
||||
});
|
||||
}
|
||||
|
||||
this.save();
|
||||
return notification;
|
||||
},
|
||||
|
||||
|
||||
/* ============ PERSISTENCE METHODS ============ */
|
||||
|
||||
save: function() {
|
||||
// Save all the notifications into localStorage
|
||||
if (settings.localStorage) {
|
||||
localStorage.setItem('notifications', JSON.stringify(notifications));
|
||||
}
|
||||
},
|
||||
|
||||
restore: function() {
|
||||
// Load all notifications from localStorage
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
notifications = [];
|
||||
this.save();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
).directive('notifications', function(notification, $compile) {
|
||||
/**
|
||||
*
|
||||
* It should also parse the arguments passed to it that specify
|
||||
* its position on the screen like "bottom right" and apply those
|
||||
* positions as a class to the container element
|
||||
*
|
||||
* Finally, the directive should have its own controller for
|
||||
* handling all of the notifications from the notification service
|
||||
*/
|
||||
function link(scope, element, attrs) {
|
||||
var position = attrs.notifications;
|
||||
position = position.split(' ');
|
||||
element.addClass('dr-notification-container');
|
||||
for (var i = 0; i < position.length; i++) {
|
||||
element.addClass(position[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {},
|
||||
templateUrl: 'views/includes/notifications.html',
|
||||
link: link,
|
||||
controller: ['$scope',
|
||||
function NotificationsCtrl($scope) {
|
||||
$scope.queue = notification.getQueue();
|
||||
|
||||
$scope.removeNotification = function(noti) {
|
||||
$scope.queue.splice($scope.queue.indexOf(noti), 1);
|
||||
};
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
});
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('notificationService', function profileServiceFactory($filter, notification, lodash, configService, gettext) {
|
||||
|
||||
var root = {};
|
||||
|
||||
var groupingTime = 5000;
|
||||
var lastNotificationOnWallet = {};
|
||||
|
||||
root.getLast = function(walletId) {
|
||||
var last = lastNotificationOnWallet[walletId];
|
||||
if (!last) return null;
|
||||
|
||||
return Date.now() - last.ts < groupingTime ? last : null;
|
||||
};
|
||||
|
||||
root.storeLast = function(notificationData, walletId) {
|
||||
|
||||
if (notificationData.type == 'NewAddress')
|
||||
return;
|
||||
|
||||
lastNotificationOnWallet[walletId] = {
|
||||
creatorId: notificationData.creatorId,
|
||||
type: notificationData.type,
|
||||
ts: Date.now(),
|
||||
};
|
||||
};
|
||||
|
||||
root.shouldSkip = function(notificationData, last) {
|
||||
if (!last) return false;
|
||||
|
||||
// rules...
|
||||
if (last.type === 'NewTxProposal' &&
|
||||
notificationData.type === 'TxProposalAcceptedBy')
|
||||
return true;
|
||||
|
||||
if (last.type === 'TxProposalFinallyAccepted' &&
|
||||
notificationData.type === 'NewOutgoingTx')
|
||||
return true;
|
||||
|
||||
if (last.type === 'TxProposalRejectedBy' &&
|
||||
notificationData.type === 'TxProposalFinallyRejected')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
root.newBWCNotification = function(notificationData, walletId, walletName) {
|
||||
var last = root.getLast(walletId);
|
||||
root.storeLast(notificationData, walletId);
|
||||
|
||||
if (root.shouldSkip(notificationData, last))
|
||||
return;
|
||||
|
||||
var config = configService.getSync();
|
||||
config.colorFor = config.colorFor || {};
|
||||
var color = config.colorFor[walletId] || '#4A90E2';
|
||||
var name = config.aliasFor[walletId] || walletName;
|
||||
|
||||
switch (notificationData.type) {
|
||||
case 'NewTxProposal':
|
||||
notification.new(gettext('New Payment Proposal'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
case 'TxProposalAcceptedBy':
|
||||
notification.success(gettext('Payment Proposal Signed by Copayer'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
case 'TxProposalRejectedBy':
|
||||
notification.error(gettext('Payment Proposal Rejected by Copayer'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
case 'TxProposalFinallyRejected':
|
||||
notification.error(gettext('Payment Proposal Rejected'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
case 'NewOutgoingTx':
|
||||
notification.sent(gettext('Payment Sent'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
case 'NewIncomingTx':
|
||||
notification.funds(gettext('Funds received'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
case 'ScanFinished':
|
||||
notification.success(gettext('Scan Finished'),
|
||||
name, {
|
||||
color: color
|
||||
});
|
||||
break;
|
||||
|
||||
case 'NewCopayer':
|
||||
// No UX notification
|
||||
break;
|
||||
case 'BalanceUpdated':
|
||||
// No UX notification
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, sjcl, lodash, storageService, bwcService, configService, notificationService, pushNotificationsService, gettext, gettextCatalog, bwcError, uxLanguage, bitcore, platformInfo, $ionicHistory) {
|
||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, sjcl, lodash, storageService, bwcService, configService, pushNotificationsService, gettext, gettextCatalog, bwcError, uxLanguage, bitcore, platformInfo, $ionicHistory) {
|
||||
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
|
|
@ -67,9 +67,7 @@ angular.module('copayApp.services')
|
|||
wallet.on('notification', function(n) {
|
||||
$log.debug('BWC Notification:', n);
|
||||
|
||||
notificationService.newBWCNotification(n,
|
||||
walletId, wallet.credentials.walletName);
|
||||
|
||||
// notification?
|
||||
|
||||
// TODO (put this in wallet ViewModel)
|
||||
if (wallet.cachedStatus)
|
||||
|
|
|
|||
|
|
@ -433,107 +433,17 @@ ul.wallet-selection.wallets {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* notifications */
|
||||
|
||||
.dr-notification-container {
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
width: 100%;
|
||||
&.bottom {
|
||||
bottom: 20px;
|
||||
// History
|
||||
.updatingHistory {
|
||||
div {
|
||||
text-align: center;
|
||||
}
|
||||
&.right {
|
||||
right: 0;
|
||||
}
|
||||
&.left {
|
||||
left: 20px;
|
||||
}
|
||||
&.top {
|
||||
top: 45px;
|
||||
}
|
||||
&.center {
|
||||
left: 50%;
|
||||
margin-left: -190px;
|
||||
}
|
||||
}
|
||||
|
||||
.dr-notification-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
&.offline {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
z-index: 2000;
|
||||
opacity: 1.0 !important;
|
||||
background-color: #2C3E50;
|
||||
.spinner {
|
||||
margin: auto;
|
||||
height: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
&.client-error {
|
||||
position: absolute;
|
||||
top: 45px;
|
||||
z-index: 11;
|
||||
}
|
||||
}
|
||||
|
||||
.dr-notification-close-btn {
|
||||
color: #A5B2BF;
|
||||
border: 1px solid #A5B2BF;
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
padding: 0px 8px;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
margin: 14px 8px 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.dr-notification-image {
|
||||
float: left;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: #213140;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 1.5rem;
|
||||
border-radius: 100%;
|
||||
margin: 0.6rem;
|
||||
img {
|
||||
margin: 15px;
|
||||
max-width: 70px;
|
||||
min-width: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.dr-notification-content {
|
||||
line-height: 90%;
|
||||
padding: 10px 50px 5px 60px;
|
||||
}
|
||||
|
||||
.dr-notification-title {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
margin-bottom: 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.dr-notification {
|
||||
background: rgba(44, 62, 80, 0.9);
|
||||
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.2);
|
||||
width: 100%;
|
||||
clear: both;
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.dr-notification-text {
|
||||
font-size: 11px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue