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