We are no longer offering accounts on this server. Consider https://gitlab.freedesktop.org/ as a place to host projects.

Commit 58ea0004 authored by Evan Prodromou's avatar Evan Prodromou

JavaScript and other changes to make realtime_channel management work

parent 3c3ab128
......@@ -93,16 +93,24 @@ class RealtimePlugin extends Plugin
*/
function onRouterInitialized($m)
{
// Discovery actions
$m->connect('main/channel/:channel_key/keepalive',
array('action' => 'keepalivechannel'));
$m->connect('main/channel/:channel_key/close',
array('action' => 'closechannel'));
$m->connect('main/channel/:channelkey/keepalive',
array('action' => 'keepalivechannel'),
array('channelkey' => '[a-z0-9]{32}'));
$m->connect('main/channel/:channelkey/close',
array('action' => 'closechannel'),
array('channelkey' => '[a-z0-9]{32}'));
return true;
}
function onEndShowScripts($action)
{
$timeline = $this->_getTimeline($action);
$channel = $this->_getChannel($action);
if (empty($channel)) {
return true;
}
$timeline = $this->_pathToChannel(array($channel->channel_key));
// If there's not a timeline on this page,
// just return true
......@@ -137,12 +145,14 @@ class RealtimePlugin extends Plugin
}
else {
$pluginPath = common_path('plugins/Realtime/');
$realtimeUI = ' RealtimeUpdate.initActions("'.$url.'", "'.$timeline.'", "'. $pluginPath .'");';
$keepalive = common_local_url('keepalivechannel', array('channelkey' => $channel->channel_key));
$close = common_local_url('closechannel', array('channelkey' => $channel->channel_key));
$realtimeUI = ' RealtimeUpdate.initActions("'.$url.'", "'.$timeline.'", "'. $pluginPath .'", "'.$keepalive.'", "'.$close.'"); ';
}
$script = ' $(document).ready(function() { '.
$realtimeUI.
$this->_updateInitialize($timeline, $user_id).
$this->_updateInitialize($timeline, $user_id).
'}); ';
$action->inlineScript($script);
......@@ -431,7 +441,18 @@ class RealtimePlugin extends Plugin
return '';
}
function _getTimeline($action)
{
$channel = $this->_getChannel($action);
if (empty($channel)) {
return null;
}
return $this->_pathToChannel(array($channel->channel_key));
}
function _getChannel($action)
{
$timeline = null;
$arg1 = null;
......@@ -480,12 +501,8 @@ class RealtimePlugin extends Plugin
$action_name,
$arg1,
$arg2);
if (!empty($channel)) {
$timeline = $this->_pathToChannel(array($channel->channel_key));
}
return $timeline;
return $channel;
}
function onStartReadWriteTables(&$alwaysRW, &$rwdb)
......
......@@ -58,6 +58,7 @@ class Realtime_channel extends Managed_DataObject
public $arg1; // argument
public $arg2; // argument, usually null
public $channel_key; // 128-bit shared secret key
public $audience; // listener count
public $created; // created date
public $modified; // modified date
......@@ -117,6 +118,10 @@ class Realtime_channel extends Managed_DataObject
'length' => 32,
'not null' => true,
'description' => 'shared secret key for this channel'),
'audience' => array('type' => 'integer',
'not null' => true,
'default' => 0,
'description' => 'reference count'),
'created' => array('type' => 'datetime',
'not null' => true,
'description' => 'date this record was created'),
......@@ -144,6 +149,7 @@ class Realtime_channel extends Managed_DataObject
$channel->action = $action;
$channel->arg1 = $arg1;
$channel->arg2 = $arg2;
$channel->audience = 1;
$channel->channel_key = common_good_rand(16); // 128-bit key, 32 hex chars
......@@ -230,18 +236,40 @@ class Realtime_channel extends Managed_DataObject
}
if ($channel->find(true)) {
$channel->touch();
$channel->increment();
return $channel;
} else {
return null;
}
}
function increment()
{
// XXX: race
$orig = clone($this);
$this->audience++;
$this->modified = common_sql_now();
$this->update($orig);
}
function touch()
{
// Touch it!
// XXX: race
$orig = clone($this);
$this->modified = common_sql_now();
$this->update($orig);
}
}
\ No newline at end of file
function decrement()
{
// XXX: race
if ($this->audience == 1) {
$this->delete();
} else {
$orig = clone($this);
$this->audience--;
$this->modified = common_sql_now();
$this->update($orig);
}
}
}
......@@ -66,7 +66,7 @@ class ClosechannelAction extends Action
throw new ClientException(_m('You have to POST it.'));
}
$this->channelKey = $this->trimmed('channel_key');
$this->channelKey = $this->trimmed('channelkey');
if (empty($this->channelKey)) {
throw new ClientException(_m('No channel key argument.'));
......@@ -91,7 +91,7 @@ class ClosechannelAction extends Action
function handle($argarray=null)
{
$this->channel->delete();
$this->channel->decrement();
header('HTTP/1.1 204 No Content');
......
......@@ -66,7 +66,7 @@ class KeepalivechannelAction extends Action
throw new ClientException(_m('You have to POST it.'));
}
$this->channelKey = $this->trimmed('channel_key');
$this->channelKey = $this->trimmed('channelkey');
if (empty($this->channelKey)) {
throw new ClientException(_m('No channel key argument.'));
......
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2008, StatusNet, Inc.
* Copyright (C) 2009-2011, StatusNet, Inc.
*
* Add a notice encoded as JSON into the current timeline
*
......@@ -21,7 +21,7 @@
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Sarven Capadisli <csarven@status.net>
* @copyright 2009 StatusNet, Inc.
* @copyright 2009-2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
......@@ -45,6 +45,8 @@
RealtimeUpdate = {
_userid: 0,
_showurl: '',
_keepaliveurl: '',
_closeurl: '',
_updatecounter: 0,
_maxnotices: 50,
_windowhasfocus: true,
......@@ -390,11 +392,28 @@ RealtimeUpdate = {
*
* @access private
*/
initActions: function(url, timeline, path)
initActions: function(url, timeline, path, keepaliveurl, closeurl)
{
$('#notices_primary').prepend('<ul id="realtime_actions"><li id="realtime_playpause"></li><li id="realtime_timeline"></li></ul>');
RealtimeUpdate._pluginPath = path;
RealtimeUpdate._keepaliveurl = keepaliveurl;
RealtimeUpdate._closeurl = closeurl;
// On unload, let the server know we're no longer listening
$(window).unload(function() {
$.ajax({
type: 'POST',
url: RealtimeUpdate._closeurl});
});
setInterval(function() {
$.ajax({
type: 'POST',
url: RealtimeUpdate._keepaliveurl});
}, 15 * 60 * 1000 ); // every 15 min; timeout in 30 min
RealtimeUpdate.initPlayPause();
RealtimeUpdate.initAddPopup(url, timeline, RealtimeUpdate._pluginPath);
......
RealtimeUpdate={_userid:0,_showurl:"",_updatecounter:0,_maxnotices:50,_windowhasfocus:true,_documenttitle:"",_paused:false,_queuedNotices:[],init:function(a,b){RealtimeUpdate._userid=a;RealtimeUpdate._showurl=b;RealtimeUpdate._documenttitle=document.title;$(window).bind("focus",function(){RealtimeUpdate._windowhasfocus=true;RealtimeUpdate._updatecounter=0;RealtimeUpdate.removeWindowCounter()});$(window).bind("blur",function(){$("#notices_primary .notice").removeClass("mark-top");$("#notices_primary .notice:first").addClass("mark-top");RealtimeUpdate._windowhasfocus=false;return false})},receive:function(a){if(RealtimeUpdate.isNoticeVisible(a.id)){return}if(RealtimeUpdate._paused===false){RealtimeUpdate.purgeLastNoticeItem();RealtimeUpdate.insertNoticeItem(a)}else{RealtimeUpdate._queuedNotices.push(a);RealtimeUpdate.updateQueuedCounter()}RealtimeUpdate.updateWindowCounter()},insertNoticeItem:function(a){if(RealtimeUpdate.isNoticeVisible(a.id)){return}RealtimeUpdate.makeNoticeItem(a,function(b){if(RealtimeUpdate.isNoticeVisible(a.id)){return}var c=$(b).attr("id");var d=$("#notices_primary .notices:first");var j=true;var e=d.hasClass("threaded-notices");if(e&&a.in_reply_to_status_id){var g=$("#notice-"+a.in_reply_to_status_id);if(g.length==0){}else{var h=g.closest(".notices");if(h.hasClass("threaded-replies")){g=h.closest(".notice")}d=g.find(".threaded-replies");if(d.length==0){d=$('<ul class="notices threaded-replies xoxo"></ul>');g.append(d);SN.U.NoticeInlineReplyPlaceholder(g)}j=false}}var i=$(b);if(j){d.prepend(i)}else{var f=d.find("li.notice-reply-placeholder");if(f.length>0){i.insertBefore(f)}else{i.appendTo(d)}}i.css({display:"none"}).fadeIn(1000);SN.U.NoticeReplyTo($("#"+c));SN.U.NoticeWithAttachment($("#"+c))})},isNoticeVisible:function(a){return($("#notice-"+a).length>0)},purgeLastNoticeItem:function(){if($("#notices_primary .notice").length>RealtimeUpdate._maxnotices){$("#notices_primary .notice:last").remove()}},updateWindowCounter:function(){if(RealtimeUpdate._windowhasfocus===false){RealtimeUpdate._updatecounter+=1;document.title="("+RealtimeUpdate._updatecounter+") "+RealtimeUpdate._documenttitle}},removeWindowCounter:function(){document.title=RealtimeUpdate._documenttitle},makeNoticeItem:function(b,c){var a=RealtimeUpdate._showurl.replace("0000000000",b.id);$.get(a,{ajax:1},function(f,h,g){var e=$("li.notice:first",f);if(e.length){var d=document._importNode(e[0],true);c(d)}})},makeFavoriteForm:function(c,b){var a;a='<form id="favor-'+c+'" class="form_favor" method="post" action="'+RealtimeUpdate._favorurl+'"><fieldset><legend>Favor this notice</legend><input name="token-'+c+'" type="hidden" id="token-'+c+'" value="'+b+'"/><input name="notice" type="hidden" id="notice-n'+c+'" value="'+c+'"/><input type="submit" id="favor-submit-'+c+'" name="favor-submit-'+c+'" class="submit" value="Favor" title="Favor this notice"/></fieldset></form>';return a},makeReplyLink:function(c,a){var b;b='<a class="notice_reply" href="'+RealtimeUpdate._replyurl+"?replyto="+a+'" title="Reply to this notice">Reply <span class="notice_id">'+c+"</span></a>";return b},makeRepeatForm:function(c,b){var a;a='<form id="repeat-'+c+'" class="form_repeat" method="post" action="'+RealtimeUpdate._repeaturl+'"><fieldset><legend>Repeat this notice?</legend><input name="token-'+c+'" type="hidden" id="token-'+c+'" value="'+b+'"/><input name="notice" type="hidden" id="notice-'+c+'" value="'+c+'"/><input type="submit" id="repeat-submit-'+c+'" name="repeat-submit-'+c+'" class="submit" value="Yes" title="Repeat this notice"/></fieldset></form>';return a},makeDeleteLink:function(c){var b,a;a=RealtimeUpdate._deleteurl.replace("0000000000",c);b='<a class="notice_delete" href="'+a+'" title="Delete this notice">Delete</a>';return b},initActions:function(a,b,c){$("#notices_primary").prepend('<ul id="realtime_actions"><li id="realtime_playpause"></li><li id="realtime_timeline"></li></ul>');RealtimeUpdate._pluginPath=c;RealtimeUpdate.initPlayPause();RealtimeUpdate.initAddPopup(a,b,RealtimeUpdate._pluginPath)},initPlayPause:function(){if(typeof(localStorage)=="undefined"){RealtimeUpdate.showPause()}else{if(localStorage.getItem("RealtimeUpdate_paused")==="true"){RealtimeUpdate.showPlay()}else{RealtimeUpdate.showPause()}}},showPause:function(){RealtimeUpdate.setPause(false);RealtimeUpdate.showQueuedNotices();RealtimeUpdate.addNoticesHover();$("#realtime_playpause").remove();$("#realtime_actions").prepend('<li id="realtime_playpause"><button id="realtime_pause" class="pause"></button></li>');$("#realtime_pause").text(SN.msg("realtime_pause")).attr("title",SN.msg("realtime_pause_tooltip")).bind("click",function(){RealtimeUpdate.removeNoticesHover();RealtimeUpdate.showPlay();return false})},showPlay:function(){RealtimeUpdate.setPause(true);$("#realtime_playpause").remove();$("#realtime_actions").prepend('<li id="realtime_playpause"><span id="queued_counter"></span> <button id="realtime_play" class="play"></button></li>');$("#realtime_play").text(SN.msg("realtime_play")).attr("title",SN.msg("realtime_play_tooltip")).bind("click",function(){RealtimeUpdate.showPause();return false})},setPause:function(a){RealtimeUpdate._paused=a;if(typeof(localStorage)!="undefined"){localStorage.setItem("RealtimeUpdate_paused",RealtimeUpdate._paused)}},showQueuedNotices:function(){$.each(RealtimeUpdate._queuedNotices,function(a,b){RealtimeUpdate.insertNoticeItem(b)});RealtimeUpdate._queuedNotices=[];RealtimeUpdate.removeQueuedCounter()},updateQueuedCounter:function(){$("#realtime_playpause #queued_counter").html("("+RealtimeUpdate._queuedNotices.length+")")},removeQueuedCounter:function(){$("#realtime_playpause #queued_counter").empty()},addNoticesHover:function(){$("#notices_primary .notices").hover(function(){if(RealtimeUpdate._paused===false){RealtimeUpdate.showPlay()}},function(){if(RealtimeUpdate._paused===true){RealtimeUpdate.showPause()}})},removeNoticesHover:function(){$("#notices_primary .notices").unbind()},initAddPopup:function(a,b,c){$("#realtime_timeline").append('<button id="realtime_popup"></button>');$("#realtime_popup").text(SN.msg("realtime_popup")).attr("title",SN.msg("realtime_popup_tooltip")).bind("click",function(){window.open(a,"","toolbar=no,resizable=yes,scrollbars=yes,status=no,menubar=no,personalbar=no,location=no,width=500,height=550");return false})},initPopupWindow:function(){$(".notices .entry-title a, .notices .entry-content a").bind("click",function(){window.open(this.href,"");return false});$("#showstream .entity_profile").css({width:"69%"})}};
\ No newline at end of file
RealtimeUpdate={_userid:0,_showurl:"",_keepaliveurl:"",_closeurl:"",_updatecounter:0,_maxnotices:50,_windowhasfocus:true,_documenttitle:"",_paused:false,_queuedNotices:[],init:function(a,b){RealtimeUpdate._userid=a;RealtimeUpdate._showurl=b;RealtimeUpdate._documenttitle=document.title;$(window).bind("focus",function(){RealtimeUpdate._windowhasfocus=true;RealtimeUpdate._updatecounter=0;RealtimeUpdate.removeWindowCounter()});$(window).bind("blur",function(){$("#notices_primary .notice").removeClass("mark-top");$("#notices_primary .notice:first").addClass("mark-top");RealtimeUpdate._windowhasfocus=false;return false})},receive:function(a){if(RealtimeUpdate.isNoticeVisible(a.id)){return}if(RealtimeUpdate._paused===false){RealtimeUpdate.purgeLastNoticeItem();RealtimeUpdate.insertNoticeItem(a)}else{RealtimeUpdate._queuedNotices.push(a);RealtimeUpdate.updateQueuedCounter()}RealtimeUpdate.updateWindowCounter()},insertNoticeItem:function(a){if(RealtimeUpdate.isNoticeVisible(a.id)){return}RealtimeUpdate.makeNoticeItem(a,function(b){if(RealtimeUpdate.isNoticeVisible(a.id)){return}var c=$(b).attr("id");var d=$("#notices_primary .notices:first");var j=true;var e=d.hasClass("threaded-notices");if(e&&a.in_reply_to_status_id){var g=$("#notice-"+a.in_reply_to_status_id);if(g.length==0){}else{var h=g.closest(".notices");if(h.hasClass("threaded-replies")){g=h.closest(".notice")}d=g.find(".threaded-replies");if(d.length==0){d=$('<ul class="notices threaded-replies xoxo"></ul>');g.append(d);SN.U.NoticeInlineReplyPlaceholder(g)}j=false}}var i=$(b);if(j){d.prepend(i)}else{var f=d.find("li.notice-reply-placeholder");if(f.length>0){i.insertBefore(f)}else{i.appendTo(d)}}i.css({display:"none"}).fadeIn(1000);SN.U.NoticeReplyTo($("#"+c));SN.U.NoticeWithAttachment($("#"+c))})},isNoticeVisible:function(a){return($("#notice-"+a).length>0)},purgeLastNoticeItem:function(){if($("#notices_primary .notice").length>RealtimeUpdate._maxnotices){$("#notices_primary .notice:last").remove()}},updateWindowCounter:function(){if(RealtimeUpdate._windowhasfocus===false){RealtimeUpdate._updatecounter+=1;document.title="("+RealtimeUpdate._updatecounter+") "+RealtimeUpdate._documenttitle}},removeWindowCounter:function(){document.title=RealtimeUpdate._documenttitle},makeNoticeItem:function(b,c){var a=RealtimeUpdate._showurl.replace("0000000000",b.id);$.get(a,{ajax:1},function(f,h,g){var e=$("li.notice:first",f);if(e.length){var d=document._importNode(e[0],true);c(d)}})},makeFavoriteForm:function(c,b){var a;a='<form id="favor-'+c+'" class="form_favor" method="post" action="'+RealtimeUpdate._favorurl+'"><fieldset><legend>Favor this notice</legend><input name="token-'+c+'" type="hidden" id="token-'+c+'" value="'+b+'"/><input name="notice" type="hidden" id="notice-n'+c+'" value="'+c+'"/><input type="submit" id="favor-submit-'+c+'" name="favor-submit-'+c+'" class="submit" value="Favor" title="Favor this notice"/></fieldset></form>';return a},makeReplyLink:function(c,a){var b;b='<a class="notice_reply" href="'+RealtimeUpdate._replyurl+"?replyto="+a+'" title="Reply to this notice">Reply <span class="notice_id">'+c+"</span></a>";return b},makeRepeatForm:function(c,b){var a;a='<form id="repeat-'+c+'" class="form_repeat" method="post" action="'+RealtimeUpdate._repeaturl+'"><fieldset><legend>Repeat this notice?</legend><input name="token-'+c+'" type="hidden" id="token-'+c+'" value="'+b+'"/><input name="notice" type="hidden" id="notice-'+c+'" value="'+c+'"/><input type="submit" id="repeat-submit-'+c+'" name="repeat-submit-'+c+'" class="submit" value="Yes" title="Repeat this notice"/></fieldset></form>';return a},makeDeleteLink:function(c){var b,a;a=RealtimeUpdate._deleteurl.replace("0000000000",c);b='<a class="notice_delete" href="'+a+'" title="Delete this notice">Delete</a>';return b},initActions:function(a,c,d,b,e){$("#notices_primary").prepend('<ul id="realtime_actions"><li id="realtime_playpause"></li><li id="realtime_timeline"></li></ul>');RealtimeUpdate._pluginPath=d;RealtimeUpdate._keepaliveurl=b;RealtimeUpdate._closeurl=e;$(window).unload(function(){$.ajax({type:"POST",url:RealtimeUpdate._closeurl})});setInterval(function(){$.ajax({type:"POST",url:RealtimeUpdate._keepaliveurl})},15*60*1000);RealtimeUpdate.initPlayPause();RealtimeUpdate.initAddPopup(a,c,RealtimeUpdate._pluginPath)},initPlayPause:function(){if(typeof(localStorage)=="undefined"){RealtimeUpdate.showPause()}else{if(localStorage.getItem("RealtimeUpdate_paused")==="true"){RealtimeUpdate.showPlay()}else{RealtimeUpdate.showPause()}}},showPause:function(){RealtimeUpdate.setPause(false);RealtimeUpdate.showQueuedNotices();RealtimeUpdate.addNoticesHover();$("#realtime_playpause").remove();$("#realtime_actions").prepend('<li id="realtime_playpause"><button id="realtime_pause" class="pause"></button></li>');$("#realtime_pause").text(SN.msg("realtime_pause")).attr("title",SN.msg("realtime_pause_tooltip")).bind("click",function(){RealtimeUpdate.removeNoticesHover();RealtimeUpdate.showPlay();return false})},showPlay:function(){RealtimeUpdate.setPause(true);$("#realtime_playpause").remove();$("#realtime_actions").prepend('<li id="realtime_playpause"><span id="queued_counter"></span> <button id="realtime_play" class="play"></button></li>');$("#realtime_play").text(SN.msg("realtime_play")).attr("title",SN.msg("realtime_play_tooltip")).bind("click",function(){RealtimeUpdate.showPause();return false})},setPause:function(a){RealtimeUpdate._paused=a;if(typeof(localStorage)!="undefined"){localStorage.setItem("RealtimeUpdate_paused",RealtimeUpdate._paused)}},showQueuedNotices:function(){$.each(RealtimeUpdate._queuedNotices,function(a,b){RealtimeUpdate.insertNoticeItem(b)});RealtimeUpdate._queuedNotices=[];RealtimeUpdate.removeQueuedCounter()},updateQueuedCounter:function(){$("#realtime_playpause #queued_counter").html("("+RealtimeUpdate._queuedNotices.length+")")},removeQueuedCounter:function(){$("#realtime_playpause #queued_counter").empty()},addNoticesHover:function(){$("#notices_primary .notices").hover(function(){if(RealtimeUpdate._paused===false){RealtimeUpdate.showPlay()}},function(){if(RealtimeUpdate._paused===true){RealtimeUpdate.showPause()}})},removeNoticesHover:function(){$("#notices_primary .notices").unbind()},initAddPopup:function(a,b,c){$("#realtime_timeline").append('<button id="realtime_popup"></button>');$("#realtime_popup").text(SN.msg("realtime_popup")).attr("title",SN.msg("realtime_popup_tooltip")).bind("click",function(){window.open(a,"","toolbar=no,resizable=yes,scrollbars=yes,status=no,menubar=no,personalbar=no,location=no,width=500,height=550");return false})},initPopupWindow:function(){$(".notices .entry-title a, .notices .entry-content a").bind("click",function(){window.open(this.href,"");return false});$("#showstream .entity_profile").css({width:"69%"})}};
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment