commit
						1b86e1feb6
					
				
					 12 changed files with 209 additions and 19 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_128x128.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_128x128.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 8.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_error.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_error.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 8.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_info.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_128x128_info.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_16x16.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_16x16.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 628 B  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_32x32.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_32x32.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/gfx/icon_64x64.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/gfx/icon_64x64.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.3 KiB  | 
| 
						 | 
					@ -5,6 +5,11 @@
 | 
				
			||||||
	<title>Cryptalk</title>
 | 
						<title>Cryptalk</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<link rel="stylesheet" type="text/css" href="css/default.css">
 | 
						<link rel="stylesheet" type="text/css" href="css/default.css">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<head profile="http://www.w3.org/2005/10/profile">
 | 
				
			||||||
 | 
						<link rel="icon" 
 | 
				
			||||||
 | 
						      type="image/png" 
 | 
				
			||||||
 | 
						      href="gfx/icon_32x32.png">
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
// Main cryptalk module
 | 
					// Main cryptalk module
 | 
				
			||||||
define({
 | 
					define({
 | 
				
			||||||
	compiles: ['$'],
 | 
						compiles: ['$'],
 | 
				
			||||||
	requires: ['hosts', 'templates', 'sound', 'fandango']
 | 
						requires: ['hosts', 'templates', 'sound', 'fandango','notifications']
 | 
				
			||||||
}, function ($, requires, data) {
 | 
					}, function ($, requires, data) {
 | 
				
			||||||
	var socket,
 | 
						var socket,
 | 
				
			||||||
		key,
 | 
							key,
 | 
				
			||||||
| 
						 | 
					@ -26,10 +26,11 @@ define({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Shortcut
 | 
							// Shortcut
 | 
				
			||||||
		hosts = requires.hosts.hosts;
 | 
							hosts = requires.hosts.hosts,
 | 
				
			||||||
		fandango = requires.fandango;
 | 
							fandango = requires.fandango,
 | 
				
			||||||
		templates = requires.templates;
 | 
							templates = requires.templates,
 | 
				
			||||||
		sound = requires.sound;
 | 
							sound = requires.sound,
 | 
				
			||||||
 | 
							notifications = requires.notifications,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lockInput = function () {
 | 
							lockInput = function () {
 | 
				
			||||||
			components.input[0].setAttribute('disabled', 'disabled');
 | 
								components.input[0].setAttribute('disabled', 'disabled');
 | 
				
			||||||
| 
						 | 
					@ -42,8 +43,22 @@ define({
 | 
				
			||||||
			components.input.focus();
 | 
								components.input.focus();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							showNotification = function (type, nick, text) {
 | 
				
			||||||
 | 
								if (!mute) {
 | 
				
			||||||
 | 
									if ( type == 'message') {
 | 
				
			||||||
 | 
										notifications.notify(nick.substring(0, 20), text.substring(0, 80),'gfx/icon_128x128.png',true);
 | 
				
			||||||
 | 
									} else if ( type == 'error' ) {
 | 
				
			||||||
 | 
										notifications.notify('Cryptalk', text.substring(0, 80),'gfx/icon_128x128_error.png',true);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										notifications.notify('Cryptalk', text.substring(0, 80),'gfx/icon_128x128_info.png',true);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Adds a new message to the DOM
 | 
							// Adds a new message to the DOM
 | 
				
			||||||
		post = function (type, text, clearChat, clearBuffer, nick) {
 | 
							post = function (type, text, clearChat, clearBuffer, nick) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var tpl = templates.post[type],
 | 
								var tpl = templates.post[type],
 | 
				
			||||||
				post,
 | 
									post,
 | 
				
			||||||
				data = fandango.merge({}, settings, {
 | 
									data = fandango.merge({}, settings, {
 | 
				
			||||||
| 
						 | 
					@ -60,6 +75,9 @@ define({
 | 
				
			||||||
				clearInput();
 | 
									clearInput();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								showNotification(type, nick, text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Append the post to the chat DOM element
 | 
								// Append the post to the chat DOM element
 | 
				
			||||||
			components.chat[clearChat ? 'html' : 'append'](post);
 | 
								components.chat[clearChat ? 'html' : 'append'](post);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					@ -196,7 +214,7 @@ define({
 | 
				
			||||||
							post('error', templates.messages.unable_to_decrypt);
 | 
												post('error', templates.messages.unable_to_decrypt);
 | 
				
			||||||
						} else {
 | 
											} else {
 | 
				
			||||||
							post('message', sanitized, false, false, nick);
 | 
												post('message', sanitized, false, false, nick);
 | 
				
			||||||
							if( !mute ) sound.playTones(sound.messages.message);
 | 
												//if( !mute && !notifications.windowActive()) sound.playTones(sound.messages.message);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,7 +230,7 @@ define({
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								// Play sound
 | 
													// Play sound
 | 
				
			||||||
								if (sound.messages[sanitized] !== undefined && !mute ) sound.playTones(sound.messages[sanitized]);
 | 
													//if (sound.messages[sanitized] !== undefined && !mute && !notifications.windowActive() ) sound.playTones(sound.messages[sanitized]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								post('error', templates.server.bogus);
 | 
													post('error', templates.server.bogus);
 | 
				
			||||||
| 
						 | 
					@ -500,13 +518,18 @@ define({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unlockInput();
 | 
						unlockInput();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						notifications.enableNative();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// It's possible to provide room and key using the hashtag.
 | 
						// It's possible to provide room and key using the hashtag.
 | 
				
			||||||
	// The room and key is then seperated by semicolon (room:key).
 | 
						// The room and key is then seperated by semicolon (room:key).
 | 
				
			||||||
	// If there is no semicolon present, the complete hash will be treated as the room name and the key has to be set manually.
 | 
						// If there is no semicolon present, the complete hash will be treated as the room name and the key has to be set manually.
 | 
				
			||||||
	if (host && (hash = window.location.hash)) {
 | 
						commands.connect(0, function() {
 | 
				
			||||||
		parts = hash.slice(1).split(':');
 | 
							if (host && (hash = window.location.hash)) {
 | 
				
			||||||
 | 
								parts = hash.slice(1).split(':');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								parts[0] && commands.join(parts[0]);
 | 
				
			||||||
 | 
								parts[1] && commands.key(parts[1]);
 | 
				
			||||||
 | 
							}	
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		parts[0] && commands.join(parts[0]);
 | 
					 | 
				
			||||||
		parts[1] && commands.key(parts[1]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
							
								
								
									
										133
									
								
								public/js/cryptalk_modules/notifications.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								public/js/cryptalk_modules/notifications.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,133 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Usage
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					Native notifications without fallback:
 | 
				
			||||||
 | 
						notification.enableNative(); // Once
 | 
				
			||||||
 | 
						notification.notify("Woop Woop");
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					Native notifications with fallback:
 | 
				
			||||||
 | 
						notification.enableNative(); // Once
 | 
				
			||||||
 | 
						notification.notify("Woop Woop",true); // True in 2nd parameter enables fallback
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					Title blink only:
 | 
				
			||||||
 | 
						notifications.blinkTitleUntilFocus("Woop Woop",1000);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					define(function (){
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						var exports = {},
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							window_active,
 | 
				
			||||||
 | 
							blur_delay_timer,
 | 
				
			||||||
 | 
							native_supported = false,
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							new_title,
 | 
				
			||||||
 | 
							original_title,
 | 
				
			||||||
 | 
							blink_timer,
 | 
				
			||||||
 | 
							interval,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        now = function () {
 | 
				
			||||||
 | 
					            return performance.now() || Date.now();
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							focusCallback = function() {
 | 
				
			||||||
 | 
								/* Reset everything after regaining focus */
 | 
				
			||||||
 | 
								resetState();
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							resetState = function() {
 | 
				
			||||||
 | 
								clearTimeout(blur_delay_timer);
 | 
				
			||||||
 | 
								clearTimeout(blink_timer);
 | 
				
			||||||
 | 
								if (original_title !== undefined) setTitle(original_title);
 | 
				
			||||||
 | 
								original_title = undefined;
 | 
				
			||||||
 | 
								new_title = undefined;
 | 
				
			||||||
 | 
								window_active = true;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							blurCallback = function() {
 | 
				
			||||||
 | 
								/* Apply a slight delay to prevent notifications from popping when the notifications
 | 
				
			||||||
 | 
								   cause the windows to lose focus */
 | 
				
			||||||
 | 
								clearTimeout(blur_delay_timer);
 | 
				
			||||||
 | 
								blur_delay_timer = setTimeout(function() { window_active = false; },1000);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							setTitle = function(t) 	{ document.title = t; },
 | 
				
			||||||
 | 
							getTitle = function() 	{ return document.title; },
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
							doBlink = function() {
 | 
				
			||||||
 | 
								if(!window_active) {
 | 
				
			||||||
 | 
									if( getTitle() == original_title )
 | 
				
			||||||
 | 
										setTitle( new_title );
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										setTitle( original_title);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
									blink_timer = setTimeout(doBlink,interval);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									resetState();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						exports.enableNative = function() {
 | 
				
			||||||
 | 
							if( native_supported && Notification.permission !== 'denied' ) {
 | 
				
			||||||
 | 
								Notification.requestPermission(function (status) {
 | 
				
			||||||
 | 
									Notification.permission = status;
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						exports.windowActive = function() {
 | 
				
			||||||
 | 
							return window_active;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						exports.blinkTitleUntilFocus = function(t,i) {
 | 
				
			||||||
 | 
							interval = (i == undefined) ? 1000 : i;
 | 
				
			||||||
 | 
							if (!window_active) {
 | 
				
			||||||
 | 
								new_title = t;
 | 
				
			||||||
 | 
								original_title = getTitle();
 | 
				
			||||||
 | 
								doBlink();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						exports.notify = function(title,body,icon,fallback) {
 | 
				
			||||||
 | 
							// Only notify while in background
 | 
				
			||||||
 | 
							if( !window_active ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Set default value for fallback parameter
 | 
				
			||||||
 | 
								if ( fallback === undefined) fallback = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ( native_supported && Notification.permission === "granted") {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Create notification
 | 
				
			||||||
 | 
									var n = new Notification(title, {body: body, icon:icon});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Handle on show event
 | 
				
			||||||
 | 
									n.onshow = function () { 
 | 
				
			||||||
 | 
									  	// Automatically close the notification after 5000ms
 | 
				
			||||||
 | 
										setTimeout(function(){n.close();},3000);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								} else if ( fallback ) {
 | 
				
			||||||
 | 
									exports.blinkTitleUntilFocus("Attention",1000);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						native_supported = (window.Notification !== undefined);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						// Keep track of document focus/blur
 | 
				
			||||||
 | 
						if (window.addEventListener){
 | 
				
			||||||
 | 
							// Normal browsers
 | 
				
			||||||
 | 
							window.addEventListener("focus", focusCallback, true);
 | 
				
			||||||
 | 
							window.addEventListener("blur", blurCallback, true);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// IE
 | 
				
			||||||
 | 
							window.observe("focusin", focusCallback);
 | 
				
			||||||
 | 
							window.observe("focusout", blurCallback);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						// Make sure we are at square one
 | 
				
			||||||
 | 
						resetState();
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
						return exports;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -79,8 +79,8 @@ define({
 | 
				
			||||||
		leave_from_nowhere: 	'How are you supposed to leave, while being nowhere?',
 | 
							leave_from_nowhere: 	'How are you supposed to leave, while being nowhere?',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Sounds
 | 
							// Sounds
 | 
				
			||||||
		muted: 					'Notification sounds is now muted.',
 | 
							muted: 					'Notifications and sounds are now muted.',
 | 
				
			||||||
		unmuted: 				'Notifications sounds is now on.',
 | 
							unmuted: 				'Notifications and sounds are now on.',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Extra variables: 'commandName'
 | 
							// Extra variables: 'commandName'
 | 
				
			||||||
		unrecognized_command: 	'Unrecognized command: "{commandName}"',
 | 
							unrecognized_command: 	'Unrecognized command: "{commandName}"',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								server.js
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								server.js
									
										
									
									
									
								
							| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
var express = require('express.io'),
 | 
					var express = require('express.io'),
 | 
				
			||||||
    uuid = require('node-uuid');
 | 
					    uuid = require('node-uuid'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app = express();app.http().io();
 | 
					    app = express();app.http().io();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.use(express.static(__dirname + '/public'));
 | 
					app.use(express.static(__dirname + '/public'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,9 +43,38 @@ app.io.route('room', {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.io.route('message', {
 | 
					app.io.route('message', {
 | 
				
			||||||
    send: function(req) {
 | 
					    send: function(req) {
 | 
				
			||||||
      if(req.data && req.data.room) req.socket.broadcast.to(req.data.room).emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
					
 | 
				
			||||||
      req.socket.emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
					      // Check that the user is in a room
 | 
				
			||||||
 | 
					      if(req.data && req.data.room) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check that the message size is within bounds
 | 
				
			||||||
 | 
					        var total_msg_size = (req.data.msg) ? req.data.msg.length : 0 + (req.data.nick) ? req.data.nick.length : 0;
 | 
				
			||||||
 | 
					        if( total_msg_size <= 4096) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Check that at least 100ms has passed since last message
 | 
				
			||||||
 | 
					          if( req.socket.last_message === undefined || new Date().getTime() - req.socket.last_message > 100 ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            req.socket.broadcast.to(req.data.room).emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
				
			||||||
 | 
					            req.socket.emit('message:send', { msg: req.data.msg, nick: req.data.nick} );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            req.socket.last_message = new Date().getTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Do not complain if message rate is too fast, that would only generate more traffic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Message size is out of bounds, complain
 | 
				
			||||||
 | 
					          req.socket.emit('message:server', {msg:'command_failed'} );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.io.sockets.on('connection', function(socket) {
 | 
					app.io.sockets.on('connection', function(socket) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue