From fb38738d2faac0136b3fc2d30342e1a696657bec Mon Sep 17 00:00:00 2001
From: Robin Nilsson <robinnilsson@gmail.com>
Date: Thu, 25 Sep 2014 23:43:24 +0200
Subject: [PATCH] Various fixes

Configurable mininum delay between notifications added
Grouped settings
Configurable default + host specific title
win -> window
removed /generate-command
deprecated dependency on node-uuid
---
 package.json                                  |  1 -
 public/js/cryptalk_modules/cryptalk.js        | 62 ++++++++++---------
 public/js/cryptalk_modules/notifications.js   | 26 +++++---
 public/js/cryptalk_modules/settings.js        | 22 +++++--
 public/js/cryptalk_modules/templates.js       | 10 +--
 .../js/cryptalk_modules/{win.js => window.js} |  0
 server.js                                     |  5 --
 7 files changed, 75 insertions(+), 51 deletions(-)
 rename public/js/cryptalk_modules/{win.js => window.js} (100%)

diff --git a/package.json b/package.json
index f7e8bfd..4a50d98 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,6 @@
   },
   "bin" : "./server.js",
   "dependencies": {
-    "node-uuid": ">= 1.4.1",
     "express.io": ">= 1.1.13"
   },
   "os": [
diff --git a/public/js/cryptalk_modules/cryptalk.js b/public/js/cryptalk_modules/cryptalk.js
index ef0e46f..700a87c 100644
--- a/public/js/cryptalk_modules/cryptalk.js
+++ b/public/js/cryptalk_modules/cryptalk.js
@@ -1,12 +1,14 @@
 // Main cryptalk module
 define({
 	compiles: ['$'],
-	requires: ['mediator', 'hosts', 'templates', 'audio', 'fandango','notifications', 'sounds', 'win']
+	requires: ['mediator', 'hosts', 'templates', 'audio', 'fandango','notifications', 'sounds', 'window']
 }, function ($, requires, data) {
+
 	var socket,
 		key,
 		host,
 		room,
+		room_raw,
 		hash,
 		nick,
 		mute = false,
@@ -31,7 +33,7 @@ define({
 		mediator = requires.mediator,
 		templates = requires.templates,
 		sounds = requires.sounds,
-		win = requires.win,
+		win = requires.window,
 
 		lockInput = function () {
 			components.input[0].setAttribute('disabled', 'disabled');
@@ -187,29 +189,29 @@ define({
 					'force new connection': true
 				});
 
+				// Set window title
+				win.setTitle(settings.client.title);
+
 				// Bind socket events
 				socket
-					.on('room:generated', function (data) {
-						var sanitized = $.escapeHtml(data);
-						post('server', $.template(templates.server.room_generated, { payload: sanitized }));
-						socket.emit('room:join', sanitized);
-					})
 
 					.on('room:joined', function (data) {
 						room = $.escapeHtml(data);
-						post('info', $.template(templates.messages.joined_room, { roomName: room }));
+
+						post('info', $.template(templates.messages.joined_room, { roomName: $.escapeHtml(room_raw) }));
 
 						// Automatically count persons on join
 						socket.emit('room:count');
 					})
 
 					.on('room:left', function () {
-						post('info', $.template(templates.messages.left_room, { roomName: room }));
+						post('info', $.template(templates.messages.left_room, { roomName: $.escapeHtml(room_raw) }));
 
 						// Clear history on leaving room
 						clearHistory();
 
 						room = false;
+						room_raw = "";
 					})
 
 					.on('message:send', function (data) {
@@ -262,6 +264,9 @@ define({
 						post('info', $.template(templates.messages.disconnected, {
 							host: host.name || 'localhost'
 						}));
+
+						// Revert title
+						win.setTitle(templates.client.title);
 					})
 
 					.on('error', function () {
@@ -320,10 +325,10 @@ define({
 				}
 
 				// Make sure the key meets the length requirements
-				if (payload.length > settings.key_maxLen) {
-					return post('error', templates.messages.key_to_long);
-				} else if (payload.length < settings.key_minLen) {
-					return post('error', templates.messages.key_to_short);
+				if (payload.length > settings.key.maxLen) {
+					return post('error', $.template(templates.messages.key_to_long, { key_maxLen: settings.key_maxLen } ));
+				} else if (payload.length < settings.key.minLen) {
+					return post('error', $.template(templates.messages.key_to_short, { key_maxLen: settings.key_minLen } ));
 				}
 
 				// Set key
@@ -335,10 +340,10 @@ define({
 
 			nick: function (payload) {
 				// Make sure the key meets the length requirements
-				if (payload.length > settings.nick_maxLen) {
-					return post('error', templates.messages.nick_to_long);
-				} else if (payload.length < settings.nick_minLen) {
-					return post('error', templates.messages.nick_to_short);
+				if (payload.length > settings.nick.maxLen) {
+					return post('error', $.template(templates.messages.nick_to_long, { nick_maxLen: settings.nick.maxLen } ));
+				} else if (payload.length < settings.nick.minLen) {
+					return post('error', $.template(templates.messages.nick_to_short, {nick_minLen: settings.nick.minLen } ));
 				}
 
 				// Set nick
@@ -368,20 +373,14 @@ define({
 					return post('error', templates.messages.join_no_host);
 				}
 
-				return (
-					room
-						? post('error', templates.messages.already_in_room)
-						: socket.emit('room:join', $.SHA1(payload))
-				);
-			},
-
-			generate: function (payload) {
-				return (
-					room
-						? post('error', templates.messages.already_in_room)
-						: socket.emit('room:generate')
-				);
+				if (room) {
+					return post('error', templates.messages.already_in_room);
+				} else {
+					room_raw = payload;
+					return socket.emit('room:join', $.SHA1(payload))
+				}
 			}
+
 		},
 
 		// Push input buffer to history
@@ -537,6 +536,9 @@ define({
 
 	unlockInput();
 
+	// Revert title
+	win.setTitle(templates.client.title);
+
 	// It's possible to provide room and key using the hashtag.
 	// 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.
diff --git a/public/js/cryptalk_modules/notifications.js b/public/js/cryptalk_modules/notifications.js
index 11d941e..8b267ba 100644
--- a/public/js/cryptalk_modules/notifications.js
+++ b/public/js/cryptalk_modules/notifications.js
@@ -15,7 +15,8 @@ Usage
 	mediator.emit('notification:off');
 
 */
-define(['mediator','win'], function (mediator, win) { 
+define(['mediator','window','settings'], function (mediator, win, settings) { 
+
 	var enabled = true,
  
 		native_supported = false,
@@ -25,6 +26,8 @@ define(['mediator','win'], function (mediator, win) {
 		blink_timer,
 		interval,
 
+		last,
+
 		now = function () {
 			return performance.now() || Date.now();
 		},
@@ -39,7 +42,7 @@ define(['mediator','win'], function (mediator, win) {
 
 		resetState = function() {
 			clearTimeout(blink_timer);
-			if (original_title !== undefined) setTitle(original_title);
+			if (original_title !== undefined) win.setTitle(original_title);
 			original_title = undefined;
 			new_title = undefined;
 			window_active = true;
@@ -68,16 +71,17 @@ define(['mediator','win'], function (mediator, win) {
  
 		blinkTitleUntilFocus = function(t,i) {
 			interval = (i == undefined) ? 1000 : i;
-			if ( enabled ) {
+			if ( enabled && original_title === undefined ) {
 				new_title = t;
-				original_title = getTitle();
+				original_title = win.getTitle();
 				doBlink();
 			}
 		},
  
 		notify = function(title,body,icon,fallback) {
-			// Only notify while in background
-			if( enabled) {
+
+			// Only notify while in background, and if sufficient time has passed
+			if( enabled && (now() - last) > settings.notifications.maxOnePerMs ) {
 
 				// Set default value for fallback parameter
 				if ( fallback === undefined) fallback = false;
@@ -93,8 +97,11 @@ define(['mediator','win'], function (mediator, win) {
 						setTimeout(function(){n.close();},3000);
 					}
 
+					last = now();
+
 				} else if ( fallback ) {
-					exports.blinkTitleUntilFocus("Attention",1000);
+					blinkTitleUntilFocus("Attention",1000);
+
 				}
 			}
 		};
@@ -105,10 +112,15 @@ define(['mediator','win'], function (mediator, win) {
 	mediator.on('notification:on',function() { on(); });
 	mediator.on('notification:off',function() { off(); });
 
+	// Always enable native notifications
  	enableNative();
 
+ 	// Start with notifications disabled
  	off();
 
+ 	// If this is undefined, notifications will fail to show
+	last = now();
+
 	// Make sure we are at square one
 	resetState();
  
diff --git a/public/js/cryptalk_modules/settings.js b/public/js/cryptalk_modules/settings.js
index a54b96d..4b52116 100644
--- a/public/js/cryptalk_modules/settings.js
+++ b/public/js/cryptalk_modules/settings.js
@@ -1,7 +1,21 @@
 define({
-	nick_maxLen: 20,
-	nick_minLen: 3,
 
-	key_maxLen: Infinity,
-	key_minLen: 8
+	client: {
+		title: "Cryptalk - Online"
+	},
+
+	nick: {
+		maxLen: 20,
+		minLen: 2,	
+	},
+
+	key: {
+		maxLen: Infinity,
+		minLen: 8,	
+	},
+
+	notifications: {
+		maxOnePerMs: 3000
+	}
+
 });
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/templates.js b/public/js/cryptalk_modules/templates.js
index dba77a6..d2ac4ef 100644
--- a/public/js/cryptalk_modules/templates.js
+++ b/public/js/cryptalk_modules/templates.js
@@ -33,7 +33,6 @@ define({
 		'	/title					Set your local page title					\n' +
 		'                                                                       \n' +
 		'Room:                                                    				\n' +
-		' 	/generate 				Generate random room                        \n' +
 		'	/join		RoomId			Join a room	                            \n' +
 		'	/leave					Leave the room                              \n' +
 		'	/count					Count participants                          \n' +
@@ -93,8 +92,8 @@ define({
 
 		unrecognized_command: 	'Unrecognized command: "{commandName}"',
 
-		joined_room: 			'Joined room {room}',
-		left_room: 				'Left room {room}',
+		joined_room: 			'Joined room {roomName}.',
+		left_room: 				'Left room {roomName}.',
 		already_in_room: 		'You are already in a room ({room}), stoopid.',
 
 		unable_to_decrypt: 		'Unabled to decrypt received message, keys does not match.',
@@ -113,9 +112,12 @@ define({
 	server: {
 		person_joined: 			'A person joined this room.',
 		person_left: 			'A person left this room.',
-		room_generated: 		'Room {payload} generated.',
 		person_count: 			'There is {payload} person(s) in this room, including you.',
 		command_failed: 		'Server command failed, you\'re probably trying to du something bogus.',
 		bogus: 					'Received a bogus message from server.'
+	},
+
+	client: {
+		title: 					'Cryptalk - Offline'
 	}
 });
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/win.js b/public/js/cryptalk_modules/window.js
similarity index 100%
rename from public/js/cryptalk_modules/win.js
rename to public/js/cryptalk_modules/window.js
diff --git a/server.js b/server.js
index c080ee2..c78e44f 100644
--- a/server.js
+++ b/server.js
@@ -1,17 +1,12 @@
 #!/usr/bin/env node
 
 var express = require('express.io'),
-    uuid = require('node-uuid'),
 
     app = express();app.http().io();
 
 app.use(express.static(__dirname + '/public'));
 
 app.io.route('room', {
-    generate: function(req) {
-      var room = uuid.v4();
-      req.socket.emit('room:generated',room);
-    },
     join: function(req) {
       if( req.data ) {
         req.socket.emit('room:joined',req.data);