]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/Realtime/RealtimePlugin.php
Merge remote branch 'origin/pluginstatic' into testing
[quix0rs-gnu-social.git] / plugins / Realtime / RealtimePlugin.php
index 82eca3d08c0d1cd67700ee69394563af534d5a73..246b1f9735d9ef8596115c17cf95708404239649 100644 (file)
@@ -43,43 +43,45 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  * @link     http://status.net/
  */
-
 class RealtimePlugin extends Plugin
 {
     protected $replyurl = null;
     protected $favorurl = null;
     protected $deleteurl = null;
 
+    /**
+     * When it's time to initialize the plugin, calculate and
+     * pass the URLs we need.
+     */
+
     function onInitializePlugin()
     {
         $this->replyurl = common_local_url('newnotice');
         $this->favorurl = common_local_url('favor');
+        $this->repeaturl = common_local_url('repeat');
         // FIXME: need to find a better way to pass this pattern in
         $this->deleteurl = common_local_url('deletenotice',
                                             array('notice' => '0000000000'));
+        return true;
     }
 
     function onEndShowScripts($action)
     {
-        $path = null;
+        $timeline = $this->_getTimeline($action);
 
-        switch ($action->trimmed('action')) {
-         case 'public':
-            $path = array('public');
-            break;
-         case 'tag':
-            $tag = $action->trimmed('tag');
-            if (!empty($tag)) {
-                $path = array('tag', $tag);
-            } else {
-                return true;
-            }
-            break;
-         default:
+        // If there's not a timeline on this page,
+        // just return true
+
+        if (empty($timeline)) {
             return true;
         }
 
-        $timeline = $this->_pathToChannel($path);
+        $base = $action->selfUrl();
+        if (mb_strstr($base, '?')) {
+            $url = $base . '&realtime=1';
+        } else {
+            $url = $base . '?realtime=1';
+        }
 
         $scripts = $this->_getScripts();
 
@@ -95,26 +97,52 @@ class RealtimePlugin extends Plugin
             $user_id = 0;
         }
 
-        $action->elementStart('script', array('type' => 'text/javascript'));
-        $action->raw("$(document).ready(function() { ");
-        $action->raw($this->_updateInitialize($timeline, $user_id));
-        $action->raw(" });");
-        $action->elementEnd('script');
+        if ($action->boolean('realtime')) {
+            $realtimeUI = ' RealtimeUpdate.initPopupWindow();';
+        }
+        else {
+            $pluginPath = common_path('plugins/Realtime/');
+            $realtimeUI = ' RealtimeUpdate.initActions("'.$url.'", "'.$timeline.'", "'. $pluginPath .'");';
+        }
+
+        $script = ' $(document).ready(function() { '.
+          $realtimeUI.
+          $this->_updateInitialize($timeline, $user_id).
+          '}); ';
+        $action->inlineScript($script);
+
+        return true;
+    }
 
+    function onEndShowStatusNetStyles($action)
+    {
+        $action->cssLink(Plugin::staticPath('Realtime', 'realtimeupdate.css'),
+                         null,
+                         'screen, projection, tv');
         return true;
     }
 
-    function onEndNoticeSave($notice)
+    function onHandleQueuedNotice($notice)
     {
         $paths = array();
 
-        // XXX: Add other timelines; this is just for the public one
+        // Add to the author's timeline
+
+        $user = User::staticGet('id', $notice->profile_id);
+
+        if (!empty($user)) {
+            $paths[] = array('showstream', $user->nickname);
+        }
+
+        // Add to the public timeline
 
-        if ($notice->is_local ||
-            ($notice->is_local == 0 && !common_config('public', 'localonly'))) {
+        if ($notice->is_local == Notice::LOCAL_PUBLIC ||
+            ($notice->is_local == Notice::REMOTE_OMB && !common_config('public', 'localonly'))) {
             $paths[] = array('public');
         }
 
+        // Add to the tags timeline
+
         $tags = $this->getNoticeTags($notice);
 
         if (!empty($tags)) {
@@ -123,6 +151,43 @@ class RealtimePlugin extends Plugin
             }
         }
 
+        // Add to inbox timelines
+        // XXX: do a join
+
+        $ni = $notice->whoGets();
+
+        foreach (array_keys($ni) as $user_id) {
+            $user = User::staticGet('id', $user_id);
+            $paths[] = array('all', $user->nickname);
+        }
+
+        // Add to the replies timeline
+
+        $reply = new Reply();
+        $reply->notice_id = $notice->id;
+
+        if ($reply->find()) {
+            while ($reply->fetch()) {
+                $user = User::staticGet('id', $reply->profile_id);
+                if (!empty($user)) {
+                    $paths[] = array('replies', $user->nickname);
+                }
+            }
+        }
+
+        // Add to the group timeline
+        // XXX: join
+
+        $gi = new Group_inbox();
+        $gi->notice_id = $notice->id;
+
+        if ($gi->find()) {
+            while ($gi->fetch()) {
+                $ug = User_group::staticGet('id', $gi->group_id);
+                $paths[] = array('showgroup', $ug->nickname);
+            }
+        }
+
         if (count($paths) > 0) {
 
             $json = $this->noticeAsJson($notice);
@@ -140,33 +205,71 @@ class RealtimePlugin extends Plugin
         return true;
     }
 
+    function onStartShowBody($action)
+    {
+        $realtime = $action->boolean('realtime');
+        if (!$realtime) {
+            return true;
+        }
+
+        $action->elementStart('body',
+                              (common_current_user()) ? array('id' => $action->trimmed('action'),
+                                                              'class' => 'user_in realtime-popup')
+                              : array('id' => $action->trimmed('action'),
+                                      'class'=> 'realtime-popup'));
+
+        // XXX hack to deal with JS that tries to get the
+        // root url from page output
+
+        $action->elementStart('address');
+        $action->element('a', array('class' => 'url',
+                                  'href' => common_local_url('public')),
+                         '');
+        $action->elementEnd('address');
+
+        if (common_logged_in()) {
+            $action->showNoticeForm();
+        }
+
+        $action->showContentBlock();
+        $action->showScripts();
+        $action->elementEnd('body');
+        return false; // No default processing
+    }
+
     function noticeAsJson($notice)
     {
         // FIXME: this code should be abstracted to a neutral third
         // party, like Notice::asJson(). I'm not sure of the ethics
         // of refactoring from within a plugin, so I'm just abusing
-        // the TwitterApiAction method. Don't do this unless you're me!
-
-        require_once(INSTALLDIR.'/lib/twitterapi.php');
+        // the ApiAction method. Don't do this unless you're me!
 
-        $act = new TwitterApiAction('/dev/null');
+        $act = new ApiAction('/dev/null');
 
-        $arr = $act->twitter_status_array($notice, true);
+        $arr = $act->twitterStatusArray($notice, true);
         $arr['url'] = $notice->bestUrl();
         $arr['html'] = htmlspecialchars($notice->rendered);
         $arr['source'] = htmlspecialchars($arr['source']);
-
-        if (!empty($notice->reply_to)) {
-            $reply_to = Notice::staticGet('id', $notice->reply_to);
-            if (!empty($reply_to)) {
-                $arr['in_reply_to_status_url'] = $reply_to->bestUrl();
-            }
-            $reply_to = null;
-        }
+        $arr['conversation_url'] = $this->getConversationUrl($notice);
 
         $profile = $notice->getProfile();
         $arr['user']['profile_url'] = $profile->profileurl;
 
+        // Add needed repeat data
+
+        if (!empty($notice->repeat_of)) {
+            $original = Notice::staticGet('id', $notice->repeat_of);
+            if (!empty($original)) {
+                $arr['retweeted_status']['url'] = $original->bestUrl();
+                $arr['retweeted_status']['html'] = htmlspecialchars($original->rendered);
+                $arr['retweeted_status']['source'] = htmlspecialchars($original->source);
+                $originalProfile = $original->getProfile();
+                $arr['retweeted_status']['user']['profile_url'] = $originalProfile->profileurl;
+                $arr['retweeted_status']['conversation_url'] = $this->getConversationUrl($original);
+            }
+            $original = null;
+        }
+
         return $arr;
     }
 
@@ -190,22 +293,68 @@ class RealtimePlugin extends Plugin
         return $tags;
     }
 
-    // Push this up to Plugin
-
-    function log($level, $msg)
+    function getConversationUrl($notice)
     {
-        common_log($level, get_class($this) . ': '.$msg);
+        $convurl = null;
+
+        if ($notice->hasConversation()) {
+            $conv = Conversation::staticGet(
+                'id',
+                $notice->conversation
+            );
+            $convurl = $conv->uri;
+
+            if(empty($convurl)) {
+                $msg = sprintf(
+                    "Couldn't find Conversation ID %d to make 'in context'"
+                    . "link for Notice ID %d",
+                    $notice->conversation,
+                    $notice->id
+                );
+
+                common_log(LOG_WARNING, $msg);
+            } else {
+                $convurl .= '#notice-' . $notice->id;
+            }
+        }
+
+        return $convurl;
     }
 
     function _getScripts()
     {
-        return array('plugins/Realtime/realtimeupdate.js',
-                     'plugins/Realtime/json2.js');
+        return array(Plugin::staticPath('Realtime', 'realtimeupdate.min.js'));
+    }
+
+    /**
+     * Export any i18n messages that need to be loaded at runtime...
+     *
+     * @param Action $action
+     * @param array $messages
+     *
+     * @return boolean hook return value
+     */
+    function onEndScriptMessages($action, &$messages)
+    {
+        // TRANS: Text label for realtime view "play" button, usually replaced by an icon.
+        $messages['realtime_play'] = _m('BUTTON', 'Play');
+        // TRANS: Tooltip for realtime view "play" button.
+        $messages['realtime_play_tooltip'] = _m('TOOLTIP', 'Play');
+        // TRANS: Text label for realtime view "pause" button
+        $messages['realtime_pause'] = _m('BUTTON', 'Pause');
+        // TRANS: Tooltip for realtime view "pause" button
+        $messages['realtime_pause_tooltip'] = _m('TOOLTIP', 'Pause');
+        // TRANS: Text label for realtime view "popup" button, usually replaced by an icon.
+        $messages['realtime_popup'] = _m('BUTTON', 'Pop up');
+        // TRANS: Tooltip for realtime view "popup" button.
+        $messages['realtime_popup_tooltip'] = _m('TOOLTIP', 'Pop up in a window');
+
+        return true;
     }
 
     function _updateInitialize($timeline, $user_id)
     {
-        return "RealtimeUpdate.init($user_id, \"$this->replyurl\", \"$this->favorurl\", \"$this->deleteurl\"); ";
+        return "RealtimeUpdate.init($user_id, \"$this->replyurl\", \"$this->favorurl\", \"$this->repeaturl\", \"$this->deleteurl\"); ";
     }
 
     function _connect()
@@ -224,4 +373,41 @@ class RealtimePlugin extends Plugin
     {
         return '';
     }
+
+    function _getTimeline($action)
+    {
+        $path = null;
+        $timeline = null;
+
+        $action_name = $action->trimmed('action');
+
+        switch ($action_name) {
+         case 'public':
+            $path = array('public');
+            break;
+         case 'tag':
+            $tag = $action->trimmed('tag');
+            if (!empty($tag)) {
+                $path = array('tag', $tag);
+            }
+            break;
+         case 'showstream':
+         case 'all':
+         case 'replies':
+         case 'showgroup':
+            $nickname = common_canonical_nickname($action->trimmed('nickname'));
+            if (!empty($nickname)) {
+                $path = array($action_name, $nickname);
+            }
+            break;
+         default:
+            break;
+        }
+
+        if (!empty($path)) {
+            $timeline = $this->_pathToChannel($path);
+        }
+
+        return $timeline;
+    }
 }