HTML5 Notification support on chrome

This commit is contained in:
Gustavo Cortez 2014-05-15 02:13:25 -03:00
parent 19573dc327
commit 2dc5513592
5 changed files with 408 additions and 1 deletions

View File

@ -496,3 +496,138 @@ a.loading {
vertical-align:middle
}
/* notifications */
.dr-notification-container {
position: absolute;
z-index: 10000;
}
.dr-notification-container.bottom {
bottom: 20px;
}
.dr-notification-container.right {
right: 20px;
}
.dr-notification-container.left {
left: 20px;
}
.dr-notification-container.top {
top: 20px;
}
.dr-notification-container.center {
left: 50%;
margin-left: -190px;
}
.dr-notification-wrapper {
width: 380px;
position: relative;
margin: 10px 0;
}
.dr-notification {
width: 380px;
background-color: #2C3E50;
clear: both;
min-height: 80px;
max-height: 90px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
border-radius: 5px;
color: #bfe2de;
border: 1px solid rgba(4, 94, 123, 0.85);
overflow: hidden;
}
.dr-notification-close-btn {
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
-ms-border-radius: 20px;
border-radius: 20px;
display: inline-block;
padding: 3px;
background-color: #2C3E50;
font-size: 14px;
color: #adfaff;
border: 1px solid rgba(4, 94, 123, 0.85);
position: absolute;
right: -11px;
top: 5px;
-webkit-transition: all 0.35s cubic-bezier(0.31, 0.39, 0.21, 1.65);
-moz-transition: all 0.35s cubic-bezier(0.31, 0.39, 0.21, 1.65);
transition: all 0.35s cubic-bezier(0.31, 0.39, 0.21, 1.65);
cursor: pointer;
}
.dr-notification-close-btn i {
padding-left: 3px;
}
.dr-notification-close-btn:hover {
-webkit-transform: scale3d(1.25, 1.25, 1);
-moz-transform: scale3d(1.25, 1.25, 1);
-ms-transform: scale3d(1.25, 1.25, 1);
transform: scale3d(1.25, 1.25, 1);
}
.dr-notification-image {
width: 80px;
height: 80px;
border-right: 1px solid rgba(4, 94, 123, 0.85);
float: left;
display: block;
font-size: 40px;
color: white;
text-align: center;
}
.dr-notification-image i {
display: block;
width: 100%;
padding-top: 25px;
}
.dr-notification-image img {
margin: 15px;
max-width: 70px;
min-width: 48px;
}
.dr-notification-image.dr-notification-type-info {
color: #FFF;
}
.dr-notification-image.dr-notification-type-warning {
color: #FFA226;
}
.dr-notification-image.dr-notification-type-error {
color: #FF4B4F;
}
.dr-notification-image.dr-notification-type-success {
color: #B4D455;
}
.dr-notification-image.success {
color: #B4D455;
}
.dr-notification-content {
padding-left: 100px;
padding-right: 15px;
padding-top: 10px;
}
.dr-notification-title {
color: white;
padding: 0px;
font-size: 20px;
}
p.dr-notification-text {
margin-top: -5px;
font-size: 12px;
}

View File

@ -111,6 +111,8 @@
</div>
<div notifications="middle right"></div>
<div id="main" class="row" ng-class="{'main-home': !$root.wallet}">
<div class="large-12 columns" ng-view></div>
</div>
@ -680,6 +682,7 @@ on supported browsers please check <a href="http://www.webrtc.org/">http://www.w
<script src="js/services/walletFactory.js"></script>
<script src="js/services/controllerUtils.js"></script>
<script src="js/services/passphrase.js"></script>
<script src="js/services/notifications.js"></script>
<script src="js/controllers/header.js"></script>
<script src="js/controllers/footer.js"></script>

View File

@ -7,6 +7,7 @@ var copayApp = window.copayApp = angular.module('copay',[
'ngRoute',
'mm.foundation',
'monospaced.qrcode',
'notifications',
'copay.header',
'copay.footer',
'copay.addresses',

View File

@ -1,7 +1,7 @@
'use strict';
angular.module('copay.header').controller('HeaderController',
function($scope, $rootScope, $location, walletFactory, controllerUtils) {
function($scope, $rootScope, $location, $notification, walletFactory, controllerUtils) {
$scope.menu = [
{
'title': 'Addresses',
@ -27,6 +27,15 @@ angular.module('copay.header').controller('HeaderController',
}
});
// Initialize alert notification (not show when init wallet)
$rootScope.showTxAlert = 0;
$notification.enableHtml5Mode(); // for chrome: if support, enable it
$rootScope.$watch('showTxAlert', function(showTxAlert) {
if (showTxAlert && showTxAlert > 0) {
$notification.info('New Transaction', ($rootScope.showTxAlert == 1) ? 'You have pending a transaction proposal' : 'You have pending ' + $rootScope.showTxAlert + ' transaction proposals', showTxAlert);
}
});
$scope.isActive = function(item) {
if (item.link && item.link.replace('#','') == $location.path()) {
return true;

View File

@ -0,0 +1,259 @@
'use strict';
angular.module('notifications', []).
factory('$notification', ['$timeout',function($timeout){
console.log('notification service online');
var notifications = JSON.parse(localStorage.getItem('$notifications')) || [],
queue = [];
var settings = {
info: { duration: 5000, enabled: true },
warning: { duration: 5000, enabled: true },
error: { duration: 5000, 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/satoshi.gif'
};
function html5Notify(icon, title, content, ondisplay, onclose){
if(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){
console.log('notifications are available');
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{
console.log('notifications are not supported');
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){
console.log(title, content);
return this.awesomeNotify('info','info', title, content, userData);
},
error: function(title, content, userData){
return this.awesomeNotify('error', 'remove', title, content, userData);
},
success: function(title, content, userData){
return this.awesomeNotify('success', 'ok', title, content, userData);
},
warning: function(title, content, userData){
return this.awesomeNotify('warning', 'exclamation', 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(){
console.log("inner on display function");
}, function(){
console.log("inner on close function");
});
}
else{
queue.push(notification);
$timeout(function removeFromQueueTimeout(){
queue.splice(queue.indexOf(notification), 1);
}, settings[type].duration);
}
this.save();
return notification;
},
/* ============ PERSISTENCE METHODS ============ */
save: function(){
// Save all the notifications into localStorage
// console.log(JSON);
if(settings.localStorage){
localStorage.setItem('$notifications', JSON.stringify(notifications));
}
// console.log(localStorage.getItem('$notifications'));
},
restore: function(){
// Load all notifications from localStorage
},
clear: function(){
notifications = [];
this.save();
}
};
}]).
directive('notifications', ['$notification', '$compile', 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
*/
// console.log('this is a new directive');
var html =
'<div class="dr-notification-wrapper" ng-repeat="noti in queue">' +
'<div class="dr-notification-close-btn" ng-click="removeNotification(noti)">' +
'<i class="fi-x"></i>' +
'</div>' +
'<div class="dr-notification">' +
'<div class="dr-notification-image dr-notification-type-{{noti.type}}" ng-switch on="noti.image">' +
'<i class="icon-{{noti.icon}}" ng-switch-when="false"></i>' +
'<img ng-src="{{noti.image}}" ng-switch-default />' +
'</div>' +
'<div class="dr-notification-content">' +
'<h3 class="dr-notification-title">{{noti.title}}</h3>' +
'<p class="dr-notification-text">{{noti.content}}</p>' +
'</div>' +
'</div>' +
'</div>';
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: {},
template: html,
link: link,
controller: ['$scope', function NotificationsCtrl( $scope ){
$scope.queue = $notification.getQueue();
$scope.removeNotification = function(noti){
$scope.queue.splice($scope.queue.indexOf(noti), 1);
};
}
]
};
}]);