diff --git a/css/main.css b/css/main.css index 9321a5d7f..f44f11a5e 100644 --- a/css/main.css +++ b/css/main.css @@ -496,6 +496,142 @@ a.loading { vertical-align:middle } -input.ng-invalid-wallet-secret { - background: #FFB6C1; +/* 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; +} + +input.ng-invalid-wallet-secret { + background: #FFB6C1; } diff --git a/index.html b/index.html index 9a3d18c05..186c92917 100644 --- a/index.html +++ b/index.html @@ -112,6 +112,8 @@ +
+
@@ -681,6 +683,7 @@ on supported browsers please check http://www.w + diff --git a/js/app.js b/js/app.js index 30a55782e..d048c71b2 100644 --- a/js/app.js +++ b/js/app.js @@ -7,6 +7,7 @@ var copayApp = window.copayApp = angular.module('copay',[ 'ngRoute', 'mm.foundation', 'monospaced.qrcode', + 'notifications', 'copay.header', 'copay.footer', 'copay.addresses', diff --git a/js/controllers/header.js b/js/controllers/header.js index 3ceb1d865..331fa668d 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -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.txAlertCount = 0; + $notification.enableHtml5Mode(); // for chrome: if support, enable it + $rootScope.$watch('txAlertCount', function(txAlertCount) { + if (txAlertCount && txAlertCount > 0) { + $notification.info('New Transaction', ($rootScope.txAlertCount == 1) ? 'You have a pending transaction proposal' : 'You have ' + $rootScope.txAlertCount + ' pending transaction proposals', txAlertCount); + } + }); + $scope.isActive = function(item) { if (item.link && item.link.replace('#','') == $location.path()) { return true; diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js index 0b0f7361f..a4abebd72 100644 --- a/js/services/controllerUtils.js +++ b/js/services/controllerUtils.js @@ -128,6 +128,8 @@ angular.module('copay.controllerUtils') var w = $rootScope.wallet; if (!w) return; + var myCopayerId = w.getMyCopayerId(); + var pending = 0; var inT = w.getTxProposals(); var txs = []; @@ -149,13 +151,16 @@ angular.module('copay.controllerUtils') i.fee = i.builder.feeSat/bitcore.util.COIN; i.missingSignatures = tx.countInputMissingSignatures(0); txs.push(i); - }); - $rootScope.txs = txs; - var pending = 0; - for(var i=0; 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 = + '
' + + '
' + + '' + + '
' + + '
' + + '
' + + '' + + '' + + '
' + + '
' + + '

{{noti.title}}

' + + '

{{noti.content}}

' + + '
' + + '
' + + '
'; + + + 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); + }; + } + ] + + }; + }]);