Mediator awareness
This commit is contained in:
parent
29d1799d56
commit
c74d265579
|
@ -0,0 +1,67 @@
|
||||||
|
/* Usage:
|
||||||
|
|
||||||
|
channel.emit('audio:play',message);
|
||||||
|
channel.emit('audio:on');
|
||||||
|
channel.emit('audio:off');
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Sounds module, used for emitting those annoying bl-up sounds when receiving a message
|
||||||
|
define(['queue','mediator'], function (queue,mediator) {
|
||||||
|
|
||||||
|
var ac = false,
|
||||||
|
enabled = true,
|
||||||
|
|
||||||
|
channel = mediator(),
|
||||||
|
|
||||||
|
// Recursive function for playing tones, takes an array of [tone,start_ms,duration_ms] - entries
|
||||||
|
// i is only used for recursion
|
||||||
|
playTones = function (tones, i) {
|
||||||
|
|
||||||
|
// Parameter defaults
|
||||||
|
i = (i === undefined) ? 0 : i;
|
||||||
|
|
||||||
|
// Stop if we've reached the end of iteration, and require ac
|
||||||
|
if( !(i < Object.keys(tones).length) || !ac || !enabled ) return;
|
||||||
|
|
||||||
|
// Add tones to execution queue
|
||||||
|
var current_tones = tones[i],
|
||||||
|
freqs = current_tones[0],
|
||||||
|
start = current_tones[1],
|
||||||
|
duration = current_tones[2];
|
||||||
|
|
||||||
|
var o = ac.createOscillator();
|
||||||
|
var g = ac.createGain();
|
||||||
|
o.frequency.value = freqs;
|
||||||
|
o.connect(g);
|
||||||
|
g.gain.value = 0.25;
|
||||||
|
g.connect(ac.destination);
|
||||||
|
queue.add_function_delayed(start,function() { o.noteOn(0); });
|
||||||
|
queue.add_function_delayed(start+duration,function() { o.noteOff(0); });
|
||||||
|
|
||||||
|
// Iterate, or start playing
|
||||||
|
i++;
|
||||||
|
if( i < Object.keys(tones).length ) {
|
||||||
|
playTones(tones,i);
|
||||||
|
} else {
|
||||||
|
queue.run();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
on = function() {
|
||||||
|
enabled = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
off = function() {
|
||||||
|
enabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( window.AudioContext || window.webkitAudioContext ) ac = new ( window.AudioContext || window.webkitAudioContext );
|
||||||
|
|
||||||
|
channel.on('audio:play',function(message) { playTones(message) });
|
||||||
|
channel.on('audio:on',function(message) { on(); });
|
||||||
|
channel.on('audio:off',function(message) { off(); });
|
||||||
|
|
||||||
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
// Main cryptalk module
|
// Main cryptalk module
|
||||||
define({
|
define({
|
||||||
compiles: ['$'],
|
compiles: ['$'],
|
||||||
requires: ['hosts', 'templates', 'sound', 'fandango','notifications']
|
requires: ['mediator','hosts', 'templates', 'audio', 'fandango','notifications','sounds']
|
||||||
}, function ($, requires, data) {
|
}, function ($, requires, data) {
|
||||||
var socket,
|
var socket,
|
||||||
key,
|
key,
|
||||||
|
@ -9,7 +9,7 @@ define({
|
||||||
room,
|
room,
|
||||||
hash,
|
hash,
|
||||||
nick,
|
nick,
|
||||||
mute,
|
mute = false,
|
||||||
|
|
||||||
settings = {},
|
settings = {},
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ define({
|
||||||
hosts = requires.hosts,
|
hosts = requires.hosts,
|
||||||
fandango = requires.fandango,
|
fandango = requires.fandango,
|
||||||
templates = requires.templates,
|
templates = requires.templates,
|
||||||
sound = requires.sound,
|
sounds = requires.sounds,
|
||||||
notifications = requires.notifications,
|
channel = requires.mediator(),
|
||||||
|
|
||||||
lockInput = function () {
|
lockInput = function () {
|
||||||
components.input[0].setAttribute('disabled', 'disabled');
|
components.input[0].setAttribute('disabled', 'disabled');
|
||||||
|
@ -44,16 +44,21 @@ define({
|
||||||
},
|
},
|
||||||
|
|
||||||
showNotification = function (type, nick, text) {
|
showNotification = function (type, nick, text) {
|
||||||
if (!mute) {
|
|
||||||
if ( type == 'message') {
|
var title = (type!='message') ? 'Cryptalk' : nick,
|
||||||
notifications.notify(nick.substring(0, 20), text.substring(0, 80),'gfx/icon_128x128.png',true);
|
icon = (type == 'message') ? 'gfx/icon_128x128.png' : (type == 'error') ? 'gfx/icon_128x128_error.png' : 'gfx/icon_128x128_info.png';
|
||||||
} else if ( type == 'error' ) {
|
|
||||||
notifications.notify('Cryptalk', text.substring(0, 80),'gfx/icon_128x128_error.png',true);
|
// Emit notification
|
||||||
} else {
|
channel.emit('notification:send',
|
||||||
notifications.notify('Cryptalk', text.substring(0, 80),'gfx/icon_128x128_info.png',true);
|
{
|
||||||
}
|
title: title.substring(0, 20),
|
||||||
|
body: text.substring(0, 80),
|
||||||
}
|
icon: icon
|
||||||
|
});
|
||||||
|
|
||||||
|
// Emit sound
|
||||||
|
if ( type == 'message' ) channel.emit('audio:play',sounds.message);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Adds a new message to the DOM
|
// Adds a new message to the DOM
|
||||||
|
@ -63,8 +68,7 @@ define({
|
||||||
post,
|
post,
|
||||||
data = fandango.merge({}, settings, {
|
data = fandango.merge({}, settings, {
|
||||||
nick: nick,
|
nick: nick,
|
||||||
room: room,
|
room: room
|
||||||
mute: mute
|
|
||||||
});
|
});
|
||||||
|
|
||||||
data.text = $.template(text, data);
|
data.text = $.template(text, data);
|
||||||
|
@ -77,7 +81,6 @@ define({
|
||||||
|
|
||||||
showNotification(type, nick, text)
|
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);
|
||||||
},
|
},
|
||||||
|
@ -214,7 +217,6 @@ 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 && !notifications.windowActive()) sound.playTones(sound.messages.message);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -228,10 +230,6 @@ define({
|
||||||
} else {
|
} else {
|
||||||
post('server', templates.server[sanitized]);
|
post('server', templates.server[sanitized]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play sound
|
|
||||||
//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);
|
||||||
}
|
}
|
||||||
|
@ -347,11 +345,11 @@ define({
|
||||||
},
|
},
|
||||||
|
|
||||||
mute: function () {
|
mute: function () {
|
||||||
// Invert mute
|
mute = true;
|
||||||
mute = !mute;
|
},
|
||||||
|
|
||||||
// Inform that the key has been set
|
unmute: function () {
|
||||||
post('info', $.template(templates.messages[mute ? 'muted' : 'unmuted']));
|
mute = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
join: function (payload) {
|
join: function (payload) {
|
||||||
|
@ -516,9 +514,17 @@ define({
|
||||||
// Post the help/welcome message
|
// Post the help/welcome message
|
||||||
post('motd', templates.motd, true);
|
post('motd', templates.motd, true);
|
||||||
|
|
||||||
unlockInput();
|
// Route mediator messages
|
||||||
|
channel.on('window:focused',function() {
|
||||||
|
channel.emit('audio:off');
|
||||||
|
channel.emit('notification:off');
|
||||||
|
});
|
||||||
|
channel.on('window:blurred',function() {
|
||||||
|
if( !mute ) channel.emit('audio:on');
|
||||||
|
channel.emit('notification:on');
|
||||||
|
});
|
||||||
|
|
||||||
notifications.enableNative();
|
unlockInput();
|
||||||
|
|
||||||
// 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).
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
/*
|
/*
|
||||||
Usage
|
Usage
|
||||||
|
|
||||||
Native notifications without fallback:
|
// Send an notification
|
||||||
notification.enableNative(); // Once
|
channel.emit('notification:send',{
|
||||||
notification.notify("Woop Woop");
|
title: 'Woop',
|
||||||
|
body: 'Woop woop',
|
||||||
Native notifications with fallback:
|
icon: 'gfx/icon.png'
|
||||||
notification.enableNative(); // Once
|
});
|
||||||
notification.notify("Woop Woop",true); // True in 2nd parameter enables fallback
|
|
||||||
|
// Turn notifications on
|
||||||
Title blink only:
|
channel.emit('notification:on');
|
||||||
notifications.blinkTitleUntilFocus("Woop Woop",1000);
|
|
||||||
|
// Turn notifications off
|
||||||
|
channel.emit('notification:off');
|
||||||
|
|
||||||
*/
|
*/
|
||||||
define(function (){
|
define(['mediator','window'],function (mediator,win){
|
||||||
|
|
||||||
var exports = {},
|
var enabled = true,
|
||||||
|
|
||||||
window_active,
|
|
||||||
blur_delay_timer,
|
|
||||||
native_supported = false,
|
native_supported = false,
|
||||||
|
|
||||||
new_title,
|
new_title,
|
||||||
|
@ -26,108 +26,93 @@ define(function (){
|
||||||
blink_timer,
|
blink_timer,
|
||||||
interval,
|
interval,
|
||||||
|
|
||||||
now = function () {
|
channel = mediator(),
|
||||||
return performance.now() || Date.now();
|
|
||||||
},
|
now = function () {
|
||||||
|
return performance.now() || Date.now();
|
||||||
focusCallback = function() {
|
|
||||||
/* Reset everything after regaining focus */
|
|
||||||
resetState();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
on = function () {
|
||||||
|
enabled = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
off = function () {
|
||||||
|
enabled = false;
|
||||||
|
},
|
||||||
|
|
||||||
resetState = function() {
|
resetState = function() {
|
||||||
clearTimeout(blur_delay_timer);
|
|
||||||
clearTimeout(blink_timer);
|
clearTimeout(blink_timer);
|
||||||
if (original_title !== undefined) setTitle(original_title);
|
if (original_title !== undefined) setTitle(original_title);
|
||||||
original_title = undefined;
|
original_title = undefined;
|
||||||
new_title = undefined;
|
new_title = undefined;
|
||||||
window_active = true;
|
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() {
|
doBlink = function() {
|
||||||
if(!window_active) {
|
if(enabled) {
|
||||||
if( getTitle() == original_title )
|
if( win.getTitle() == original_title )
|
||||||
setTitle( new_title );
|
win.setTitle( new_title );
|
||||||
else
|
else
|
||||||
setTitle( original_title);
|
win.setTitle( original_title);
|
||||||
|
|
||||||
blink_timer = setTimeout(doBlink,interval);
|
blink_timer = setTimeout(doBlink,interval);
|
||||||
} else {
|
} else {
|
||||||
resetState();
|
resetState();
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
|
||||||
exports.enableNative = function() {
|
|
||||||
if( native_supported && Notification.permission !== 'denied' ) {
|
|
||||||
Notification.requestPermission(function (status) {
|
|
||||||
Notification.permission = status;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.windowActive = function() {
|
enableNative = function() {
|
||||||
return window_active;
|
if( native_supported && Notification.permission !== 'denied' ) {
|
||||||
};
|
Notification.requestPermission(function (status) {
|
||||||
|
Notification.permission = status;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
|
||||||
|
|
||||||
|
blinkTitleUntilFocus = function(t,i) {
|
||||||
|
interval = (i == undefined) ? 1000 : i;
|
||||||
|
if ( enabled ) {
|
||||||
|
new_title = t;
|
||||||
|
original_title = getTitle();
|
||||||
|
doBlink();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
notify = function(title,body,icon,fallback) {
|
||||||
|
// Only notify while in background
|
||||||
|
if( enabled) {
|
||||||
|
|
||||||
|
// 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);
|
native_supported = (window.Notification !== undefined);
|
||||||
|
|
||||||
// Keep track of document focus/blur
|
channel.on('notification:send',function(data) { notify(data.title,data.body,data.icon,true); });
|
||||||
if (window.addEventListener){
|
channel.on('notification:on',function() { on(); });
|
||||||
// Normal browsers
|
channel.on('notification:off',function() { off(); });
|
||||||
window.addEventListener("focus", focusCallback, true);
|
|
||||||
window.addEventListener("blur", blurCallback, true);
|
enableNative();
|
||||||
} else {
|
|
||||||
// IE
|
off();
|
||||||
window.observe("focusin", focusCallback);
|
|
||||||
window.observe("focusout", blurCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we are at square one
|
// Make sure we are at square one
|
||||||
resetState();
|
resetState();
|
||||||
|
|
||||||
return exports;
|
|
||||||
|
|
||||||
});
|
});
|
|
@ -1,69 +0,0 @@
|
||||||
// Sounds module, used for emitting those annoying bl-up sounds when receiving a message
|
|
||||||
define(['queue'], function (queue) {
|
|
||||||
|
|
||||||
var exports = { messages: {} },
|
|
||||||
|
|
||||||
ac = false;
|
|
||||||
|
|
||||||
if( window.AudioContext || window.webkitAudioContext ) ac = new ( window.AudioContext || window.webkitAudioContext );
|
|
||||||
|
|
||||||
// Recursive function for playing tones, takes an array of [tone,start_ms,duration_ms] - entries
|
|
||||||
// i is only used for recursion
|
|
||||||
exports.playTones = function (tones, i) {
|
|
||||||
|
|
||||||
// Parameter defaults
|
|
||||||
i = (i === undefined) ? 0 : i;
|
|
||||||
|
|
||||||
// Stop if we've reached the end of iteration, and require ac
|
|
||||||
if( ac && !(i < Object.keys(tones).length) || !ac ) return;
|
|
||||||
|
|
||||||
// Add tones to execution queue
|
|
||||||
var current_tones = tones[i],
|
|
||||||
freqs = current_tones[0],
|
|
||||||
start = current_tones[1],
|
|
||||||
duration = current_tones[2];
|
|
||||||
|
|
||||||
var o = ac.createOscillator();
|
|
||||||
var g = ac.createGain();
|
|
||||||
o.frequency.value = freqs;
|
|
||||||
o.connect(g);
|
|
||||||
g.gain.value = 0.25;
|
|
||||||
g.connect(ac.destination);
|
|
||||||
queue.add_function_delayed(start,function() { o.noteOn(0); });
|
|
||||||
queue.add_function_delayed(start+duration,function() { o.noteOff(0); });
|
|
||||||
|
|
||||||
// Iterate, or start playing
|
|
||||||
i++;
|
|
||||||
if( i < Object.keys(tones).length ) {
|
|
||||||
exports.playTones(tones,i);
|
|
||||||
} else {
|
|
||||||
queue.run();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.messages = {
|
|
||||||
message: [
|
|
||||||
[261.63*2,0,50],
|
|
||||||
[261.63*3,0,50],
|
|
||||||
[261.63*4,50,50],
|
|
||||||
[261.63*5,50,50]
|
|
||||||
],
|
|
||||||
person_joined: [
|
|
||||||
[261.63*3,0,200],
|
|
||||||
[261.63*1,0,200],
|
|
||||||
[261.63*3,200,500],
|
|
||||||
[261.63*2,200,500]
|
|
||||||
],
|
|
||||||
person_left: [
|
|
||||||
[261.63*3,0,200],
|
|
||||||
[261.63*2,0,200],
|
|
||||||
[261.63*3,200,500],
|
|
||||||
[261.63*1,200,500]
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
return exports;
|
|
||||||
|
|
||||||
});
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
define({
|
||||||
|
message: [
|
||||||
|
[261.63*2,0,50],
|
||||||
|
[261.63*3,0,50],
|
||||||
|
[261.63*4,50,50],
|
||||||
|
[261.63*5,50,50]
|
||||||
|
],
|
||||||
|
person_joined: [
|
||||||
|
[261.63*3,0,200],
|
||||||
|
[261.63*1,0,200],
|
||||||
|
[261.63*3,200,500],
|
||||||
|
[261.63*2,200,500]
|
||||||
|
],
|
||||||
|
person_left: [
|
||||||
|
[261.63*3,0,200],
|
||||||
|
[261.63*2,0,200],
|
||||||
|
[261.63*3,200,500],
|
||||||
|
[261.63*1,200,500]
|
||||||
|
]
|
||||||
|
});
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Emits:
|
||||||
|
'window:focused'
|
||||||
|
'window:blurred'
|
||||||
|
|
||||||
|
Exports:
|
||||||
|
title = window.getTitle();
|
||||||
|
window.setTitle(title);
|
||||||
|
|
||||||
|
*/
|
||||||
|
define(['mediator'],function (mediator){
|
||||||
|
|
||||||
|
var exports = {},
|
||||||
|
channel = mediator(),
|
||||||
|
|
||||||
|
focusCallback = function() {
|
||||||
|
channel.emit('window:focused');
|
||||||
|
},
|
||||||
|
|
||||||
|
blurCallback = function() {
|
||||||
|
channel.emit('window:blurred');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getTitle = function(t) { document.title = t; },
|
||||||
|
exports.setTitle = function() { return document.title; };
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exports;
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue