site notice, notifications, etc
This commit is contained in:
parent
146231dbe1
commit
cc3eb5fdda
|
@ -74,6 +74,16 @@ class QvitterPlugin extends Plugin {
|
|||
return $settings[$setting];
|
||||
}
|
||||
|
||||
|
||||
// make sure we have a notifications table
|
||||
function onCheckSchema()
|
||||
{
|
||||
$schema = Schema::get();
|
||||
$schema->ensureTable('qvitternotification', QvitterNotification::schemaDef());
|
||||
return true;
|
||||
}
|
||||
|
||||
// route/reroute urls
|
||||
public function onRouterInitialized($m)
|
||||
{
|
||||
|
||||
|
@ -102,8 +112,18 @@ class QvitterPlugin extends Plugin {
|
|||
'id' => Nickname::INPUT_FMT));
|
||||
$m->connect('api/qvitter/statuses/mentions.:format',
|
||||
array('action' => 'apiqvittermentions'));
|
||||
$m->connect('api/qvitter/statuses/notifications.json',
|
||||
array('action' => 'apiqvitternotifications'));
|
||||
$m->connect(':nickname/notifications',
|
||||
array('action' => 'qvitter',
|
||||
'nickname' => Nickname::INPUT_FMT));
|
||||
$m->connect('api/qvitter/newnotifications.json',
|
||||
array('action' => 'ApiNewNotifications'));
|
||||
$m->connect('settings/qvitter',
|
||||
array('action' => 'qvittersettings'));
|
||||
$m->connect('panel/qvitter',
|
||||
array('action' => 'qvitteradminsettings'));
|
||||
common_config_append('admin', 'panels', 'qvitteradm');
|
||||
$m->connect('main/qlogin',
|
||||
array('action' => 'qvitterlogin'));
|
||||
|
||||
|
@ -182,6 +202,10 @@ class QvitterPlugin extends Plugin {
|
|||
array('action' => 'showstream'),
|
||||
array('tag' => Router::REGEX_TAG),
|
||||
'qvitter');
|
||||
URLMapperOverwrite::overwrite_variable($m, 'notice/:notice',
|
||||
array('action' => 'shownotice'),
|
||||
array('notice' => '[0-9]+'),
|
||||
'qvitter');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -208,6 +232,31 @@ class QvitterPlugin extends Plugin {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu item for admin panel
|
||||
*
|
||||
* @param Action $action action being executed
|
||||
*
|
||||
* @return boolean hook return
|
||||
*/
|
||||
|
||||
function onEndAdminPanelNav($action)
|
||||
{
|
||||
|
||||
$action_name = $action->trimmed('action');
|
||||
|
||||
$action->out->menuItem(common_local_url('qvitteradminsettings'),
|
||||
// TRANS: Poll plugin menu item on user settings page.
|
||||
_m('MENU', 'Qvitter'),
|
||||
// TRANS: Poll plugin tooltip for user settings menu item.
|
||||
_m('Qvitter Sidebar Notice'),
|
||||
$action_name === 'qvitteradminsettings');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Group addresses in API response
|
||||
|
@ -249,6 +298,163 @@ class QvitterPlugin extends Plugin {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Insert into notification table
|
||||
*/
|
||||
function insertNotification($to_profile_id, $from_profile_id, $ntype, $notice_id=false)
|
||||
{
|
||||
|
||||
// never notify myself
|
||||
if($to_profile_id != $from_profile_id) {
|
||||
|
||||
// insert
|
||||
$notif = new QvitterNotification();
|
||||
$notif->to_profile_id = $to_profile_id;
|
||||
$notif->from_profile_id = $from_profile_id;
|
||||
$notif->ntype = $ntype;
|
||||
$notif->notice_id = $notice_id;
|
||||
$notif->created = common_sql_now();
|
||||
if (!$notif->insert()) {
|
||||
common_log_db_error($notif, 'INSERT', __FILE__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert likes in notification table
|
||||
*/
|
||||
public function onEndFavorNotice($profile, $notice)
|
||||
{
|
||||
|
||||
// don't notify people favoriting their own notices
|
||||
if($notice->profile_id != $profile->id) {
|
||||
$this->insertNotification($notice->profile_id, $profile->id, 'like', $notice->id, $notice->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove likes in notification table on dislike
|
||||
*/
|
||||
public function onEndDisfavorNotice($profile, $notice)
|
||||
{
|
||||
$notif = new QvitterNotification();
|
||||
$notif->from_profile_id = $profile->id;
|
||||
$notif->notice_id = $notice->id;
|
||||
$notif->ntype = 'like';
|
||||
$notif->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Insert notifications for replies, mentions and repeats
|
||||
*
|
||||
* @return boolean hook flag
|
||||
*/
|
||||
function onStartNoticeDistribute($notice) {
|
||||
|
||||
|
||||
// repeats
|
||||
if ($notice->isRepeat()) {
|
||||
$repeated_notice = Notice::getKV('id', $notice->repeat_of);
|
||||
if ($repeated_notice instanceof Notice) {
|
||||
$this->insertNotification($repeated_notice->profile_id, $notice->profile_id, 'repeat', $repeated_notice->id);
|
||||
}
|
||||
}
|
||||
|
||||
// replies and mentions (no notifications for these if this is a repeat)
|
||||
else {
|
||||
// check for reply to insert in notifications
|
||||
if($notice->reply_to) {
|
||||
$replyparent = $notice->getParent();
|
||||
$replyauthor = $replyparent->getProfile();
|
||||
if ($replyauthor instanceof Profile) {
|
||||
$reply_notification_to = $replyauthor->id;
|
||||
$this->insertNotification($replyauthor->id, $notice->profile_id, 'reply', $notice->id);
|
||||
}
|
||||
}
|
||||
|
||||
// check for mentions to insert in notifications
|
||||
$mentions = common_find_mentions($notice->content, $notice);
|
||||
$sender = Profile::getKV($notice->profile_id);
|
||||
foreach ($mentions as $mention) {
|
||||
foreach ($mention['mentioned'] as $mentioned) {
|
||||
|
||||
// Not from blocked profile
|
||||
$mentioned_user = User::getKV('id', $mentioned->id);
|
||||
if ($mentioned_user instanceof User && $mentioned_user->hasBlocked($sender)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only notify if mentioned user is not already notified for reply
|
||||
if($reply_notification_to != $mentioned->id) {
|
||||
$this->insertNotification($mentioned->id, $notice->profile_id, 'mention', $notice->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete any notifications tied to deleted notices and un-repeats
|
||||
*
|
||||
* @return boolean hook flag
|
||||
*/
|
||||
public function onNoticeDeleteRelated($notice)
|
||||
{
|
||||
|
||||
$notif = new QvitterNotification();
|
||||
|
||||
// unrepeats
|
||||
if ($notice->isRepeat()) {
|
||||
$repeated_notice = Notice::getKV('id', $notice->repeat_of);
|
||||
$notif->notice_id = $repeated_notice->id;
|
||||
$notif->from_profile_id = $notice->profile_id;
|
||||
}
|
||||
// notices
|
||||
else {
|
||||
$notif->notice_id = $notice->id;
|
||||
}
|
||||
|
||||
$notif->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notification on subscription, remove on unsubscribe
|
||||
*
|
||||
* @return boolean hook flag
|
||||
*/
|
||||
public function onEndSubscribe($subscriber, $other)
|
||||
{
|
||||
if(Subscription::exists($subscriber, $other)) {
|
||||
$this->insertNotification($other->id, $subscriber->id, 'follow');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public function onEndUnsubscribe($subscriber, $other)
|
||||
{
|
||||
if(!Subscription::exists($subscriber, $other)) {
|
||||
$notif = new QvitterNotification();
|
||||
$notif->to_profile_id = $other->id;
|
||||
$notif->from_profile_id = $subscriber->id;
|
||||
$notif->ntype = 'follow';
|
||||
$notif->delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
24
README.md
24
README.md
|
@ -45,14 +45,24 @@ TODO
|
|||
|
||||
1. "following you" badge on other peoples profiles
|
||||
|
||||
1. better user popup, with e.g. latest queets
|
||||
|
||||
1. Faq
|
||||
|
||||
1. DM's
|
||||
|
||||
1. lists
|
||||
|
||||
1. user actions-cog wheel in users lists, with block, list etc
|
||||
|
||||
1. proxy to non-https for getting conversations the instance doesn't have via jsonp
|
||||
|
||||
1. preview different types of attachments, not just images. e.g. mp3's, torrents etc etc
|
||||
|
||||
1. Join _new_ external groups and follow _new_ external users ("New" meaning users/groups that the server don't know yet)
|
||||
|
||||
2. Creating groups, make admin, block user
|
||||
|
||||
3. Background image uploading/editing
|
||||
|
||||
6. Auto url-shortening setting under queet box
|
||||
|
||||
7. Settings (e.g. don't show replies to people I don't follow)
|
||||
|
||||
9. Image/file upload
|
||||
|
@ -65,14 +75,8 @@ TODO
|
|||
|
||||
14. More languages, maybe make proper po/mo-files
|
||||
|
||||
15. Notice-page
|
||||
|
||||
16. Admin-interface
|
||||
|
||||
16. New api for serving _number_ of new items in several streams (to show number of new items in menu/history)
|
||||
|
||||
17. Notifications-page with likes and repeats
|
||||
|
||||
17. New "expand queet" api for getting conversation, retweets, favs and attachment in the same request
|
||||
|
||||
19. Node.js long polling server and an new api that serve aggregate of all polling users requests in one go
|
99
actions/apinewnotifications.php
Normal file
99
actions/apinewnotifications.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* Qvitter: Unread notifications
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category API
|
||||
* @package GNUsocial
|
||||
* @author Hannes Mannerheim <h@nnesmannerhe.im>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://www.gnu.org/software/social/
|
||||
*/
|
||||
|
||||
if (!defined('GNUSOCIAL')) { exit(1); }
|
||||
|
||||
class ApiNewNotificationsAction extends ApiAction
|
||||
{
|
||||
|
||||
/**
|
||||
* Take arguments for running
|
||||
*
|
||||
* @param array $args $_REQUEST args
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
protected function prepare(array $args=array())
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function handle()
|
||||
{
|
||||
parent::handle();
|
||||
|
||||
$user_id = Profile::current()->id;
|
||||
$new_notifications = array();
|
||||
if($user_id) {
|
||||
$notification = new QvitterNotification();
|
||||
|
||||
$notification->selectAdd();
|
||||
$notification->selectAdd('ntype');
|
||||
$notification->selectAdd('count(id) as count');
|
||||
$notification->whereAdd("(to_profile_id = '".$user_id."')");
|
||||
$notification->groupBy('ntype');
|
||||
$notification->whereAdd("(is_seen = '0')");
|
||||
$notification->find();
|
||||
|
||||
while ($notification->fetch()) {
|
||||
$new_notifications[$notification->ntype] = $notification->count;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$new_notifications = 'You must be logged in.';
|
||||
}
|
||||
|
||||
|
||||
$this->initDocument('json');
|
||||
$this->showJsonObjects($new_notifications);
|
||||
$this->endDocument('json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if read only.
|
||||
*
|
||||
* MAY override
|
||||
*
|
||||
* @param array $args other arguments
|
||||
*
|
||||
* @return boolean is read only action?
|
||||
*/
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
198
actions/apiqvitternotifications.php
Normal file
198
actions/apiqvitternotifications.php
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||
· ·
|
||||
· ·
|
||||
· Q V I T T E R ·
|
||||
· ·
|
||||
· http://github.com/hannesmannerheim/qvitter ·
|
||||
· ·
|
||||
· ·
|
||||
· <o) ·
|
||||
· /_//// ·
|
||||
· (____/ ·
|
||||
· (o< ·
|
||||
· o> \\\\_\ ·
|
||||
· \\) \____) ·
|
||||
· ·
|
||||
· ·
|
||||
· ·
|
||||
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||
· under the terms of the GNU Affero General Public License as published by ·
|
||||
· the Free Software Foundation, either version three of the License or (at ·
|
||||
· your option) any later version. ·
|
||||
· ·
|
||||
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||
· more details. ·
|
||||
· ·
|
||||
· You should have received a copy of the GNU Affero General Public License ·
|
||||
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||
· ·
|
||||
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||
· ·
|
||||
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class ApiQvitterNotificationsAction extends ApiPrivateAuthAction
|
||||
{
|
||||
var $notifications = null;
|
||||
var $notices = null;
|
||||
var $profiles = null;
|
||||
|
||||
/**
|
||||
* Take arguments for running
|
||||
*
|
||||
* @param array $args $_REQUEST args
|
||||
*
|
||||
* @return boolean success flag
|
||||
*
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->notifications = $this->getNotifications();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* Just show the notices
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showTimeline();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the timeline of notices
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showTimeline()
|
||||
{
|
||||
|
||||
$notice = null;
|
||||
|
||||
$notifications_populated = array();
|
||||
|
||||
foreach($this->notifications as $notification) {
|
||||
|
||||
// all but follow has an notice
|
||||
if($notification->ntype != 'follow') {
|
||||
$notice = self::twitterSimpleStatusArray(Notice::getKV($notification->notice_id));
|
||||
}
|
||||
|
||||
$notifications_populated[] = array(
|
||||
'id'=> $notification->id,
|
||||
'from_profile'=> self::twitterUserArray(Profile::getKV($notification->from_profile_id)),
|
||||
'ntype'=> $notification->ntype,
|
||||
'notice'=> $notice,
|
||||
'created_at'=>self::dateTwitter($notification->created),
|
||||
'is_seen'=>$notification->is_seen
|
||||
);
|
||||
}
|
||||
|
||||
// mark as seen
|
||||
foreach($this->notifications as $notification) {
|
||||
if($notification->is_seen == 0) {
|
||||
$notification->is_seen = 1;
|
||||
$notification->update();
|
||||
}
|
||||
}
|
||||
|
||||
$this->initDocument('json');
|
||||
$this->showJsonObjects($notifications_populated);
|
||||
$this->endDocument('json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notices
|
||||
*
|
||||
* @return array notices
|
||||
*/
|
||||
function getNotifications()
|
||||
{
|
||||
$notices = array();
|
||||
|
||||
$profile = ($this->auth_user) ? $this->auth_user->getProfile() : null;
|
||||
|
||||
$stream = new NotificationStream($profile);
|
||||
|
||||
$notifications = $stream->getNotifications(($this->page - 1) * $this->count,
|
||||
$this->count,
|
||||
$this->since_id,
|
||||
$this->max_id);
|
||||
|
||||
$notifications = $notifications->fetchAll();
|
||||
|
||||
return $notifications;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is this action read only?
|
||||
*
|
||||
* @param array $args other arguments
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* When was this feed last modified?
|
||||
*
|
||||
* @return string datestamp of the latest notice in the stream
|
||||
*/
|
||||
function lastModified()
|
||||
{
|
||||
if (!empty($this->notifications) && (count($this->notifications) > 0)) {
|
||||
return strtotime($this->notifications[0]->created);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this stream
|
||||
*
|
||||
* Returns an Etag based on the action name, language, and
|
||||
* timestamps of the first and last notice in the timeline
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
function etag()
|
||||
{
|
||||
if (!empty($this->notifications) && (count($this->notifications) > 0)) {
|
||||
|
||||
$last = count($this->notifications) - 1;
|
||||
|
||||
return '"' . implode(
|
||||
':',
|
||||
array($this->arg('action'),
|
||||
common_user_cache_hash($this->auth_user),
|
||||
common_language(),
|
||||
strtotime($this->notifications[0]->created),
|
||||
strtotime($this->notifications[$last]->created))
|
||||
)
|
||||
. '"';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +1,37 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show the public timeline
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category API
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author mac65 <mac65@mac65.com>
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||
· ·
|
||||
· ·
|
||||
· Q V I T T E R ·
|
||||
· ·
|
||||
· http://github.com/hannesmannerheim/qvitter ·
|
||||
· ·
|
||||
· ·
|
||||
· <o) ·
|
||||
· /_//// ·
|
||||
· (____/ ·
|
||||
· (o< ·
|
||||
· o> \\\\_\ ·
|
||||
· \\) \____) ·
|
||||
· ·
|
||||
· ·
|
||||
· ·
|
||||
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||
· under the terms of the GNU Affero General Public License as published by ·
|
||||
· the Free Software Foundation, either version three of the License or (at ·
|
||||
· your option) any later version. ·
|
||||
· ·
|
||||
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||
· more details. ·
|
||||
· ·
|
||||
· You should have received a copy of the GNU Affero General Public License ·
|
||||
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||
· ·
|
||||
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||
· ·
|
||||
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
|
@ -54,94 +53,6 @@ if (!defined('STATUSNET')) {
|
|||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
/* External API usage documentation. Please update when you change how this method works. */
|
||||
|
||||
/*! @page publictimeline statuses/public_timeline
|
||||
|
||||
@section Description
|
||||
Returns the 20 most recent notices from users throughout the system who have
|
||||
uploaded their own avatars. Depending on configuration, it may or may not
|
||||
not include notices from automatic posting services.
|
||||
|
||||
@par URL patterns
|
||||
@li /api/statuses/public_timeline.:format
|
||||
|
||||
@par Formats (:format)
|
||||
xml, json, rss, atom
|
||||
|
||||
@par HTTP Method(s)
|
||||
GET
|
||||
|
||||
@par Requires Authentication
|
||||
No
|
||||
|
||||
@param since_id (Optional) Returns only statuses with an ID greater
|
||||
than (that is, more recent than) the specified ID.
|
||||
@param max_id (Optional) Returns only statuses with an ID less than
|
||||
(that is, older than) or equal to the specified ID.
|
||||
@param count (Optional) Specifies the number of statuses to retrieve.
|
||||
@param page (Optional) Specifies the page of results to retrieve.
|
||||
|
||||
@sa @ref apiroot
|
||||
|
||||
@subsection usagenotes Usage notes
|
||||
@li The URL pattern is relative to the @ref apiroot.
|
||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
||||
to encode the latitude and longitude (see example response below <georss:point>).
|
||||
|
||||
@subsection exampleusage Example usage
|
||||
|
||||
@verbatim
|
||||
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
|
||||
@endverbatim
|
||||
|
||||
@subsection exampleresponse Example response
|
||||
|
||||
@verbatim
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<statuses type="array">
|
||||
<status>
|
||||
<text>@skwashd oh, commbank reenabled me super quick both times. but disconcerting when you don't expect it though</text>
|
||||
<truncated>false</truncated>
|
||||
<created_at>Sat Apr 17 00:49:12 +0000 2010</created_at>
|
||||
<in_reply_to_status_id>28838393</in_reply_to_status_id>
|
||||
<source>xmpp</source>
|
||||
<id>28838456</id>
|
||||
<in_reply_to_user_id>39303</in_reply_to_user_id>
|
||||
<in_reply_to_screen_name>skwashd</in_reply_to_screen_name>
|
||||
<geo></geo>
|
||||
<favorited>false</favorited>
|
||||
<user>
|
||||
<id>44517</id>
|
||||
<name>joshua may</name>
|
||||
<screen_name>notjosh</screen_name>
|
||||
<location></location>
|
||||
<description></description>
|
||||
<profile_image_url>http://avatar.identi.ca/44517-48-20090321004106.jpeg</profile_image_url>
|
||||
<url></url>
|
||||
<protected>false</protected>
|
||||
<followers_count>17</followers_count>
|
||||
<profile_background_color></profile_background_color>
|
||||
<profile_text_color></profile_text_color>
|
||||
<profile_link_color></profile_link_color>
|
||||
<profile_sidebar_fill_color></profile_sidebar_fill_color>
|
||||
<profile_sidebar_border_color></profile_sidebar_border_color>
|
||||
<friends_count>20</friends_count>
|
||||
<created_at>Sat Mar 21 00:40:25 +0000 2009</created_at>
|
||||
<favourites_count>0</favourites_count>
|
||||
<utc_offset>0</utc_offset>
|
||||
<time_zone>UTC</time_zone>
|
||||
<profile_background_image_url></profile_background_image_url>
|
||||
<profile_background_tile>false</profile_background_tile>
|
||||
<statuses_count>100</statuses_count>
|
||||
<following>false</following>
|
||||
<notifications>false</notifications>
|
||||
</user>
|
||||
</status>
|
||||
[....]
|
||||
</statuses>
|
||||
@endverbatim
|
||||
*/
|
||||
class ApiTimelinePublicAndExternalAction extends ApiPrivateAuthAction
|
||||
{
|
||||
var $notices = null;
|
||||
|
|
|
@ -189,7 +189,9 @@ class QvitterAction extends ApiAction
|
|||
color:#0084B4;/*COLOREND*/
|
||||
}
|
||||
.topbar .global-nav,
|
||||
.menu-container {
|
||||
.menu-container,
|
||||
#unseen-notifications,
|
||||
.stream-item.notification .not-seen {
|
||||
background-color:#0084B4;/*BACKGROUNDCOLOREND*/
|
||||
}
|
||||
</style>
|
||||
|
@ -278,7 +280,14 @@ class QvitterAction extends ApiAction
|
|||
</div>
|
||||
</div>
|
||||
<div id="page-container">
|
||||
<div class="front-welcome-text">
|
||||
<?php
|
||||
|
||||
$site_notice = common_config('site', 'notice');
|
||||
if(!empty($site_notice)) {
|
||||
print '<div id="site-notice">'.common_config('site', 'notice').'</div>';
|
||||
}
|
||||
|
||||
?><div class="front-welcome-text">
|
||||
<h1></h1>
|
||||
<p></p>
|
||||
</div>
|
||||
|
@ -343,6 +352,7 @@ class QvitterAction extends ApiAction
|
|||
</div>
|
||||
<div class="menu-container">
|
||||
<a class="stream-selection friends-timeline" data-stream-header="" data-stream-name="qvitter/statuses/friends_timeline.json"><i class="chev-right"></i></a>
|
||||
<a class="stream-selection notifications" data-stream-header="" data-stream-name="qvitter/statuses/notifications.json"><span id="unseen-notifications"></span><i class="chev-right"></i></a>
|
||||
<a class="stream-selection mentions" data-stream-header="" data-stream-name="qvitter/statuses/mentions.json"><i class="chev-right"></i></a>
|
||||
<a class="stream-selection my-timeline" data-stream-header="@statuses/user_timeline.json" data-stream-name="statuses/user_timeline.json"><i class="chev-right"></i></a>
|
||||
<a class="stream-selection favorites" data-stream-header="" data-stream-name="favorites.json"><i class="chev-right"></i></a>
|
||||
|
@ -350,6 +360,7 @@ class QvitterAction extends ApiAction
|
|||
<a href="<?php print $instanceurl ?>main/all" class="stream-selection public-and-external-timeline" data-stream-header="" data-stream-name="statuses/public_and_external_timeline.json"><i class="chev-right"></i></a>
|
||||
</div>
|
||||
<div class="menu-container" id="history-container"></div>
|
||||
<div id="qvitter-notice"><?php print common_config('site', 'qvitternotice'); ?></div>
|
||||
</div>
|
||||
<div id="feed">
|
||||
<div id="feed-header">
|
||||
|
@ -364,7 +375,7 @@ class QvitterAction extends ApiAction
|
|||
|
||||
<div id="footer"></div>
|
||||
</div>
|
||||
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery-2.0.2.min.js"></script>
|
||||
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery-2.1.1.min.js"></script>
|
||||
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery-ui-1.10.3.min.js"></script>
|
||||
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery.easing.1.3.js"></script>
|
||||
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery.minicolors.min.js"></script>
|
||||
|
|
203
actions/qvitteradminsettings.php
Normal file
203
actions/qvitteradminsettings.php
Normal file
|
@ -0,0 +1,203 @@
|
|||
<?php
|
||||
|
||||
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
||||
· ·
|
||||
· ·
|
||||
· Q V I T T E R ·
|
||||
· ·
|
||||
· http://github.com/hannesmannerheim/qvitter ·
|
||||
· ·
|
||||
· ·
|
||||
· <o) ·
|
||||
· /_//// ·
|
||||
· (____/ ·
|
||||
· (o< ·
|
||||
· o> \\\\_\ ·
|
||||
· \\) \____) ·
|
||||
· ·
|
||||
· ·
|
||||
· ·
|
||||
· Qvitter is free software: you can redistribute it and / or modify it ·
|
||||
· under the terms of the GNU Affero General Public License as published by ·
|
||||
· the Free Software Foundation, either version three of the License or (at ·
|
||||
· your option) any later version. ·
|
||||
· ·
|
||||
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
||||
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
||||
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
||||
· more details. ·
|
||||
· ·
|
||||
· You should have received a copy of the GNU Affero General Public License ·
|
||||
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
||||
· ·
|
||||
· Contact h@nnesmannerhe.im if you have any questions. ·
|
||||
· ·
|
||||
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
|
||||
|
||||
|
||||
class QvitterAdminSettingsAction extends AdminPanelAction
|
||||
{
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
function title()
|
||||
{
|
||||
// TRANS: Page title for site-wide notice tab in admin panel.
|
||||
return _('Qvitter Sidebar Notice');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for using this form.
|
||||
*
|
||||
* @return string instructions
|
||||
*/
|
||||
function getInstructions()
|
||||
{
|
||||
// TRANS: Instructions for site-wide notice tab in admin panel.
|
||||
return _('Edit notice in Qvitter\'s sidebar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the site notice admin panel form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showForm()
|
||||
{
|
||||
$form = new QvitterNoticeAdminPanelForm($this);
|
||||
$form->show();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings from the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function saveSettings()
|
||||
{
|
||||
$qvitterNotice = $this->trimmed('qvitter-notice');
|
||||
|
||||
// assert(all values are valid);
|
||||
// This throws an exception on validation errors
|
||||
|
||||
$this->validate($qvitterNotice);
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$result = Config::save('site', 'qvitternotice', $qvitterNotice);
|
||||
|
||||
if (!$result) {
|
||||
// TRANS: Server error displayed when saving a sidebar notice was impossible.
|
||||
$this->ServerError(_('Unable to save qvitter sidebar notice.'));
|
||||
}
|
||||
}
|
||||
|
||||
function validate(&$qvitterNotice)
|
||||
{
|
||||
// Validate notice text
|
||||
|
||||
if (mb_strlen($qvitterNotice) > 255) {
|
||||
$this->clientError(
|
||||
// TRANS: Client error displayed when a sidebar notice was longer than allowed.
|
||||
_('Maximum length for the sidebar notice is 255 characters.')
|
||||
);
|
||||
}
|
||||
|
||||
// scrub HTML input
|
||||
|
||||
$config = array(
|
||||
'safe' => 1,
|
||||
'deny_attribute' => 'on*'
|
||||
);
|
||||
|
||||
$qvitterNotice = htmLawed($qvitterNotice, $config);
|
||||
}
|
||||
}
|
||||
|
||||
class QvitterNoticeAdminPanelForm extends AdminForm
|
||||
{
|
||||
/**
|
||||
* ID of the form
|
||||
*
|
||||
* @return int ID of the form
|
||||
*/
|
||||
|
||||
function id()
|
||||
{
|
||||
return 'form_qvitter_notice_admin_panel';
|
||||
}
|
||||
|
||||
/**
|
||||
* class of the form
|
||||
*
|
||||
* @return string class of the form
|
||||
*/
|
||||
|
||||
function formClass()
|
||||
{
|
||||
return 'form_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action of the form
|
||||
*
|
||||
* @return string URL of the action
|
||||
*/
|
||||
|
||||
function action()
|
||||
{
|
||||
return common_local_url('qvitteradminsettings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formData()
|
||||
{
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
||||
$this->out->elementStart('li');
|
||||
$this->out->textarea(
|
||||
'qvitter-notice',
|
||||
// TRANS: Label for sidebar notice text field in admin panel.
|
||||
_('Qvitter sidebar notice text'),
|
||||
common_config('site', 'qvitternotice'),
|
||||
// TRANS: Tooltip for sidebar notice text field in admin panel.
|
||||
_('Qvitter\'s sidebar notice text (255 characters maximum; HTML allowed)')
|
||||
);
|
||||
$this->out->elementEnd('li');
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formActions()
|
||||
{
|
||||
$this->out->submit(
|
||||
'submit',
|
||||
// TRANS: Button text for saving sidebar notice in admin panel.
|
||||
_m('BUTTON','Save'),
|
||||
'submit',
|
||||
null,
|
||||
// TRANS: Button title to save sidebar notice in admin panel.
|
||||
_('Save sidebar notice.')
|
||||
);
|
||||
}
|
||||
}
|
85
classes/NotificationStream.php
Normal file
85
classes/NotificationStream.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* Notification stream
|
||||
*
|
||||
*/
|
||||
|
||||
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
|
||||
|
||||
class NotificationStream
|
||||
{
|
||||
protected $target = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Profile $target Profile to get a stream for
|
||||
*/
|
||||
function __construct(Profile $target)
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IDs in a range
|
||||
*
|
||||
* @param int $offset Offset from start
|
||||
* @param int $limit Limit of number to get
|
||||
* @param int $since_id Since this notice
|
||||
* @param int $max_id Before this notice
|
||||
*
|
||||
* @return Array IDs found
|
||||
*/
|
||||
function getNotificationIds($offset, $limit, $since_id, $max_id)
|
||||
{
|
||||
$notification = new QvitterNotification();
|
||||
$notification->selectAdd();
|
||||
$notification->selectAdd('id');
|
||||
$notification->whereAdd(sprintf('qvitternotification.to_profile_id = "%s"', $notification->escape($this->target->id)));
|
||||
$notification->whereAdd(sprintf('qvitternotification.created > "%s"', $notification->escape($this->target->created)));
|
||||
$notification->limit($offset, $limit);
|
||||
$notification->orderBy('qvitternotification.created DESC');
|
||||
|
||||
QvitterNotification::addWhereSinceId($notification, $since_id);
|
||||
QvitterNotification::addWhereMaxId($notification, $max_id);
|
||||
|
||||
if (!$notification->find()) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$ids = $notification->fetchAll('id');
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
function getNotifications($offset, $limit, $sinceId, $maxId)
|
||||
{
|
||||
|
||||
$all = array();
|
||||
|
||||
do {
|
||||
|
||||
$ids = $this->getNotificationIds($offset, $limit, $sinceId, $maxId);
|
||||
|
||||
$notifications = QvitterNotification::pivotGet('id', $ids);
|
||||
|
||||
// By default, takes out false values
|
||||
|
||||
$notifications = array_filter($notifications);
|
||||
|
||||
$all = array_merge($all, $notifications);
|
||||
|
||||
if (count($notifications < count($ids))) {
|
||||
$offset += $limit;
|
||||
$limit -= count($notifications);
|
||||
}
|
||||
|
||||
} while (count($notifications) < count($ids) && count($ids) > 0);
|
||||
|
||||
return new ArrayWrapper($all);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
152
classes/QvitterNotification.php
Normal file
152
classes/QvitterNotification.php
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
/**
|
||||
* Table Definition for reply
|
||||
*/
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class QvitterNotification extends Managed_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'qvitternotification'; // table name
|
||||
public $id; // int(4) primary_key not_null
|
||||
public $to_profile_id; // int(4) primary_key not_null
|
||||
public $from_profile_id; // int(4) primary_key not_null
|
||||
public $type; // varchar(7)
|
||||
public $notice_id; // int(4) primary_key not_null
|
||||
public $date; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
public static function schemaDef()
|
||||
{
|
||||
return array(
|
||||
'fields' => array(
|
||||
'id' => array('type' => 'serial', 'not null' => true),
|
||||
'to_profile_id' => array('type' => 'int', 'description' => 'the profile being notified'),
|
||||
'from_profile_id' => array('type' => 'int', 'description' => 'the profile that is notifying'),
|
||||
'ntype' => array('type' => 'varchar', 'length' => 7, 'description' => 'reply, like, mention or follow'),
|
||||
'notice_id' => array('type' => 'int', 'description' => 'id for the reply or mention or notice being faved'),
|
||||
'is_seen' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'if the notification has been seen'),
|
||||
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created')
|
||||
),
|
||||
'primary key' => array('id')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for record insertion to update related caches
|
||||
*/
|
||||
function insert()
|
||||
{
|
||||
$result = parent::insert();
|
||||
|
||||
if ($result) {
|
||||
self::blow('qvitternotification:stream:%d', $this->to_profile_id);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the creation timestamp for a given notice ID, even
|
||||
* if it's been deleted.
|
||||
*
|
||||
* @param int $id
|
||||
* @return mixed string recorded creation timestamp, or false if can't be found
|
||||
*/
|
||||
public static function getAsTimestamp($id)
|
||||
{
|
||||
if (!$id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$notice = QvitterNotification::getKV('id', $id);
|
||||
if ($notice) {
|
||||
return $notice->created;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL 'where' fragment for timestamp-based sorting from a since_id
|
||||
* parameter, matching notices posted after the given one (exclusive).
|
||||
*
|
||||
* If the referenced notice can't be found, will return false.
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $idField
|
||||
* @param string $createdField
|
||||
* @return mixed string or false if no match
|
||||
*/
|
||||
public static function whereSinceId($id, $idField='id', $createdField='created')
|
||||
{
|
||||
$since = QvitterNotification::getAsTimestamp($id);
|
||||
if ($since) {
|
||||
return sprintf("($createdField = '%s' and $idField > %d) or ($createdField > '%s')", $since, $id, $since);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL 'where' fragment for timestamp-based sorting from a since_id
|
||||
* parameter, matching notices posted after the given one (exclusive), and
|
||||
* if necessary add it to the data object's query.
|
||||
*
|
||||
* @param DB_DataObject $obj
|
||||
* @param int $id
|
||||
* @param string $idField
|
||||
* @param string $createdField
|
||||
* @return mixed string or false if no match
|
||||
*/
|
||||
public static function addWhereSinceId(DB_DataObject $obj, $id, $idField='id', $createdField='created')
|
||||
{
|
||||
$since = self::whereSinceId($id, $idField, $createdField);
|
||||
if ($since) {
|
||||
$obj->whereAdd($since);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL 'where' fragment for timestamp-based sorting from a max_id
|
||||
* parameter, matching notices posted before the given one (inclusive).
|
||||
*
|
||||
* If the referenced notice can't be found, will return false.
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $idField
|
||||
* @param string $createdField
|
||||
* @return mixed string or false if no match
|
||||
*/
|
||||
public static function whereMaxId($id, $idField='id', $createdField='created')
|
||||
{
|
||||
$max = QvitterNotification::getAsTimestamp($id);
|
||||
if ($max) {
|
||||
return sprintf("($createdField < '%s') or ($createdField = '%s' and $idField <= %d)", $max, $max, $id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL 'where' fragment for timestamp-based sorting from a max_id
|
||||
* parameter, matching notices posted before the given one (inclusive), and
|
||||
* if necessary add it to the data object's query.
|
||||
*
|
||||
* @param DB_DataObject $obj
|
||||
* @param int $id
|
||||
* @param string $idField
|
||||
* @param string $createdField
|
||||
* @return mixed string or false if no match
|
||||
*/
|
||||
public static function addWhereMaxId(DB_DataObject $obj, $id, $idField='id', $createdField='created')
|
||||
{
|
||||
$max = self::whereMaxId($id, $idField, $createdField);
|
||||
if ($max) {
|
||||
$obj->whereAdd($max);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
149
css/qvitter.css
149
css/qvitter.css
|
@ -436,7 +436,8 @@ body.rtl .dropdown-menu li:not(.dropdown-caret) {
|
|||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
.front-welcome-text {
|
||||
.front-welcome-text,
|
||||
#site-notice {
|
||||
color: #EEEEEE;
|
||||
font-size: 30px;
|
||||
font-weight: 300;
|
||||
|
@ -453,6 +454,26 @@ body.rtl .front-welcome-text {
|
|||
text-align:right;
|
||||
font-family:Tahoma,Arial,sans-serif;
|
||||
}
|
||||
#site-notice{
|
||||
display:block;
|
||||
}
|
||||
#qvitter-notice {
|
||||
text-shadow:none;
|
||||
color:#fff;
|
||||
font-size:11px;
|
||||
padding:10px;
|
||||
display:none;
|
||||
}
|
||||
#qvitter-notice a {
|
||||
color:#fff;
|
||||
opacity:0.5;
|
||||
line-height:17px;
|
||||
display:inline-block;
|
||||
}
|
||||
#qvitter-notice a:hover {
|
||||
opacity:0.8;
|
||||
}
|
||||
|
||||
.front-welcome-text h1 {
|
||||
color: #FFFFFF;
|
||||
font-size: 30px;
|
||||
|
@ -993,6 +1014,31 @@ button#submit-login:hover {
|
|||
#history-container a:hover .chev-right:hover {
|
||||
background-position:-40px -508px;
|
||||
}
|
||||
|
||||
.menu-container a.notifications {
|
||||
line-height:32px;
|
||||
padding:0 12px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
#unseen-notifications {
|
||||
display:block;
|
||||
position:absolute;
|
||||
right:0px;
|
||||
top:0;
|
||||
width:24px;
|
||||
height:24px;
|
||||
line-height:24px;
|
||||
border-radius:12px;
|
||||
color:#fff;
|
||||
text-shadow:none;
|
||||
margin:4px 5px;
|
||||
z-index:10;
|
||||
display:none;
|
||||
text-align:center;
|
||||
font-weight:normal;
|
||||
}
|
||||
|
||||
#history-container {
|
||||
display:none;
|
||||
}
|
||||
|
@ -1204,6 +1250,7 @@ button#submit-login:hover {
|
|||
-o-transition: opacity 0.1s ease, height 0s linear, margin 0.1s ease;
|
||||
transition: opacity 0.1s ease, height 0s linear, margin 0.1s ease;
|
||||
height:auto;
|
||||
/* position:relative; */
|
||||
}
|
||||
.stream-item.hidden {
|
||||
display:none;
|
||||
|
@ -1230,6 +1277,70 @@ button#submit-login:hover {
|
|||
.stream-item.conversation .queet:hover {
|
||||
background-color:#F6F6F6;
|
||||
}
|
||||
|
||||
.stream-item.notification .not-seen {
|
||||
position:absolute;
|
||||
left:-5px;
|
||||
top:50%;
|
||||
margin-top:-5px;
|
||||
width:10px;
|
||||
height:10px;
|
||||
border-radius:5px;
|
||||
z-index:10;
|
||||
}
|
||||
|
||||
.stream-item.notification.repeat .dogear,
|
||||
.stream-item.notification.like .dogear {
|
||||
display:block;
|
||||
left: 36px;
|
||||
top: 7px;
|
||||
z-index: 10;
|
||||
width:24px;
|
||||
height:24px;
|
||||
}
|
||||
.stream-item.notification.repeat .dogear {
|
||||
background-position:-70px -1072px;
|
||||
}
|
||||
.stream-item.notification.like .dogear {
|
||||
background-position:-115px -1075px;
|
||||
}
|
||||
.stream-item.notification.follow .queet,
|
||||
.stream-item.notification.repeat .queet,
|
||||
.stream-item.notification.like .queet {
|
||||
min-height:37px;
|
||||
cursor:default;
|
||||
}
|
||||
.stream-item.notification.follow .queet .queet-content,
|
||||
.stream-item.notification.repeat .queet .queet-content,
|
||||
.stream-item.notification.like .queet .queet-content {
|
||||
cursor:default;
|
||||
}
|
||||
.stream-item.notification.follow .queet:hover,
|
||||
.stream-item.notification.repeat .queet:hover,
|
||||
.stream-item.notification.like .queet:hover {
|
||||
background-color:transparent;
|
||||
}
|
||||
.stream-item.notification.follow a.account-group img.avatar,
|
||||
.stream-item.notification.repeat a.account-group img.avatar,
|
||||
.stream-item.notification.like a.account-group img.avatar {
|
||||
width:24px;
|
||||
height:24px;
|
||||
left:36px;
|
||||
top:4px;
|
||||
}
|
||||
|
||||
.stream-item.notification .small-grey-notice,
|
||||
.stream-item.notification .small-grey-notice a {
|
||||
color:#999;
|
||||
}
|
||||
.stream-item.notification .small-grey-notice a:hover {
|
||||
color:#333;
|
||||
text-decoration:underline;
|
||||
}
|
||||
.stream-item.notification .stream-item-header {
|
||||
color:#333;
|
||||
}
|
||||
|
||||
.show-full-conversation {
|
||||
float:right;
|
||||
font-style:italic;
|
||||
|
@ -1281,6 +1392,14 @@ button#submit-login:hover {
|
|||
border-radius:0 0 6px 6px;
|
||||
}
|
||||
|
||||
.expanded-content {
|
||||
-webkit-transition: height 0s linear;
|
||||
-moz-transition: height 0s linear;
|
||||
-o-transition: height 0s linear;
|
||||
transition: height 0s linear;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
body.rtl .queet.rtl .expanded-content {
|
||||
direction:rtl;
|
||||
}
|
||||
|
@ -3718,6 +3837,12 @@ body.rtl #feed-header-inner h2 {
|
|||
|
||||
@media (max-width: 866px) {
|
||||
|
||||
#site-notice,
|
||||
#qvitter-notice {
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
|
||||
#new-queets-bar-container {
|
||||
height:77px;
|
||||
}
|
||||
|
@ -4060,6 +4185,7 @@ body.rtl #feed-header-inner h2 {
|
|||
display:block;
|
||||
}
|
||||
.menu-container a.favorites,
|
||||
.menu-container a.mentions,
|
||||
.menu-container a.public-and-external-timeline {
|
||||
display:none;
|
||||
}
|
||||
|
@ -4071,7 +4197,7 @@ body.rtl #feed-header-inner h2 {
|
|||
font-size:0;
|
||||
color:transparent;
|
||||
height:55px;
|
||||
padding:0;
|
||||
padding:0 !important;
|
||||
margin:0;
|
||||
border-radius:0 0 0 0 !important;
|
||||
background-image: url("../img/sprite.png?v=2");
|
||||
|
@ -4098,7 +4224,7 @@ body.rtl #feed-header-inner h2 {
|
|||
}
|
||||
|
||||
.stream-selection.friends-timeline:after,
|
||||
.stream-selection.mentions:after,
|
||||
.stream-selection.notifications:after,
|
||||
.stream-selection.my-timeline:after,
|
||||
.stream-selection.public-timeline:after {
|
||||
content: "";
|
||||
|
@ -4115,7 +4241,7 @@ body.rtl #feed-header-inner h2 {
|
|||
.stream-selection.friends-timeline:after {
|
||||
background-position:0px -861px ;
|
||||
}
|
||||
.stream-selection.mentions:after {
|
||||
.stream-selection.notifications:after {
|
||||
background-position:-78px -861px ;
|
||||
}
|
||||
.stream-selection.my-timeline:after {
|
||||
|
@ -4249,7 +4375,11 @@ body.rtl #feed-header-inner h2 {
|
|||
border-top: 1px solid #E8E8E8;
|
||||
border-bottom: 1px solid #E8E8E8;
|
||||
height:45px;
|
||||
margin-top:20px;
|
||||
margin-top:9px;
|
||||
}
|
||||
.queet-content {
|
||||
margin-bottom: -1px;
|
||||
padding-bottom:0;
|
||||
}
|
||||
/* .stream-item.collapsing > .queet ul.queet-actions {
|
||||
display:none !important;
|
||||
|
@ -4289,9 +4419,6 @@ body.rtl #feed-header-inner h2 {
|
|||
}
|
||||
|
||||
.queet ul.stats {
|
||||
border-top: 0 none;
|
||||
margin-left:-63px;
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
.queet ul.stats li.rq-count a,
|
||||
|
@ -4302,7 +4429,11 @@ body.rtl #feed-header-inner h2 {
|
|||
.queet ul.stats li:first-child a {
|
||||
padding-left:0 !important;
|
||||
}
|
||||
.client-and-actions {
|
||||
.expanded-content {
|
||||
-webkit-transition: none !important;
|
||||
-moz-transition: none !important;
|
||||
-o-transition: none !important;
|
||||
transition: none !important;
|
||||
margin-left:-63px;
|
||||
}
|
||||
.client-and-actions .permalink-link {
|
||||
|
|
BIN
img/sprite.png
BIN
img/sprite.png
Binary file not shown.
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 60 KiB |
3117
img/sprite.png.ai
3117
img/sprite.png.ai
File diff suppressed because one or more lines are too long
|
@ -327,3 +327,52 @@ function getFavsOrRequeetsForQueet(apiaction,qid,actionOnSuccess) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Check for unseen notifications
|
||||
·
|
||||
· @param actionOnSuccess: callback function
|
||||
·
|
||||
· · · · · · · · · */
|
||||
|
||||
function checkForNewNotifications() {
|
||||
$.ajax({ url: window.apiRoot + "qvitter/newnotifications.json",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
|
||||
if(data.length == 0) {
|
||||
$('#unseen-notifications').hide();
|
||||
document.title = window.siteTitle;
|
||||
}
|
||||
else {
|
||||
|
||||
var totNotif = 0;
|
||||
$.each(data,function(k,v){
|
||||
totNotif = totNotif + parseInt(v,10);
|
||||
});
|
||||
|
||||
if(totNotif>0) {
|
||||
$('#unseen-notifications').html(totNotif);
|
||||
document.title = window.siteTitle + ' (' + totNotif + ')'; // update html page title
|
||||
$('#unseen-notifications').show();
|
||||
}
|
||||
else {
|
||||
$('#unseen-notifications').hide();
|
||||
document.title = window.siteTitle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
error: function(data) {
|
||||
$('#unseen-notifications').hide();
|
||||
document.title = window.siteTitle;
|
||||
remove_spinner();
|
||||
console.log(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -302,6 +302,7 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
|
||||
// halt interval that checks for new queets
|
||||
window.clearInterval(checkForNewQueetsInterval);
|
||||
window.clearInterval(checkForNewNotificationsInterval);
|
||||
|
||||
display_spinner();
|
||||
|
||||
|
@ -335,6 +336,7 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
// if this is one of the default streams, get header from DOM
|
||||
else if(stream == 'qvitter/statuses/friends_timeline.json'
|
||||
|| stream == 'qvitter/statuses/mentions.json'
|
||||
|| stream == 'qvitter/statuses/notifications.json'
|
||||
|| stream == 'favorites.json'
|
||||
|| stream == 'statuses/public_timeline.json'
|
||||
|| stream == 'statuses/public_and_external_timeline.json') {
|
||||
|
@ -354,6 +356,11 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
var defaultStreamName = stream;
|
||||
var streamHeader = '#' + stream.substring(stream.indexOf('/timeline/')+10,stream.indexOf('.json'));
|
||||
}
|
||||
// if this is a notice stream
|
||||
else if(stream.substring(0,14) == 'statuses/show/') {
|
||||
var defaultStreamName = stream;
|
||||
var streamHeader = 'notice/' + stream.substring(stream.indexOf('/show/')+6,stream.indexOf('.json'));
|
||||
}
|
||||
// if this is a search stream
|
||||
else if(stream.substring(0,11) == 'search.json') {
|
||||
var defaultStreamName = stream;
|
||||
|
@ -362,10 +369,10 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
|
||||
// set the h2 header in the feed
|
||||
if(stream.substring(0,23) == 'statuses/followers.json') {
|
||||
var h2FeedHeader = window.sL.followers;
|
||||
var h2FeedHeader = '<div class="queet-streams"><a class="queet-stream following">' + window.sL.following + '</a> / </div>' + window.sL.followers;
|
||||
}
|
||||
else if(stream.substring(0,21) == 'statuses/friends.json') {
|
||||
var h2FeedHeader = window.sL.following;
|
||||
var h2FeedHeader = window.sL.following + '<div class="queet-streams">/ <a class="queet-stream followers">' + window.sL.followers + '</a></div>';
|
||||
}
|
||||
else if(stream.substring(0,40) == 'statuses/user_timeline.json?screen_name=') {
|
||||
var h2FeedHeader = window.sL.notices + '<div class="queet-streams">/ <a class="queet-stream mentions">' + window.sL.mentions + '</a> / <a class="queet-stream favorites">' + window.sL.favoritesNoun +'</a></div>';
|
||||
|
@ -428,6 +435,7 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
$('.stream-selection').removeClass('current');
|
||||
$('.stream-selection[data-stream-header="' + streamHeader + '"]').addClass('current');
|
||||
|
||||
|
||||
// if this is user's user feed, i.e. followers etc, we want a profile card, which we need to get from user_timeline since the users/show api action is broken (auth doesn't work)
|
||||
if(stream.substring(0,23) == 'statuses/followers.json'
|
||||
|| stream.substring(0,21) == 'statuses/friends.json'
|
||||
|
@ -454,7 +462,14 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
}
|
||||
|
||||
profileCardFromFirstObject(profile_data,thisUsersScreenName); // show profile card
|
||||
checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling); // start interval again
|
||||
|
||||
// start checking for new queets again
|
||||
window.clearInterval(checkForNewQueetsInterval);
|
||||
window.clearInterval(checkForNewNotificationsInterval);
|
||||
checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling);
|
||||
checkForNewNotificationsInterval=window.setInterval(function(){checkForNewNotifications()},window.timeBetweenPolling);
|
||||
checkForNewNotifications();
|
||||
|
||||
remove_spinner();
|
||||
$('#feed-body').html(''); // empty feed only now so the scrollers don't flicker on and off
|
||||
$('#new-queets-bar').parent().addClass('hidden'); document.title = window.siteTitle; // hide new queets bar if it's visible there
|
||||
|
@ -493,7 +508,19 @@ function setNewCurrentStream(stream,actionOnSuccess,setLocation) {
|
|||
groupProfileCard(thisGroupAlias);
|
||||
}
|
||||
|
||||
checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling); // start interval again
|
||||
// start checking for new queets again
|
||||
window.clearInterval(checkForNewQueetsInterval);
|
||||
window.clearInterval(checkForNewNotificationsInterval);
|
||||
checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling);
|
||||
if(window.currentStream != 'qvitter/statuses/notifications.json') { // don't check for notifications if this is the notifications page
|
||||
checkForNewNotifications();
|
||||
checkForNewNotificationsInterval=window.setInterval(function(){checkForNewNotifications()},window.timeBetweenPolling);
|
||||
}
|
||||
else {
|
||||
$('#unseen-notifications').hide();
|
||||
document.title = window.siteTitle;
|
||||
}
|
||||
|
||||
remove_spinner();
|
||||
$('#feed-body').html(''); // empty feed only now so the scrollers don't flicker on and off
|
||||
$('#new-queets-bar').parent().addClass('hidden'); document.title = window.siteTitle; // hide new queets bar if it's visible there
|
||||
|
@ -547,6 +574,9 @@ function convertStreamToPath(stream) {
|
|||
else if(stream == 'qvitter/statuses/mentions.json') {
|
||||
return window.loggedIn.screen_name + '/replies';
|
||||
}
|
||||
else if(stream == 'qvitter/statuses/notifications.json') {
|
||||
return window.loggedIn.screen_name + '/notifications';
|
||||
}
|
||||
else if(stream == 'favorites.json') {
|
||||
return window.loggedIn.screen_name + '/favorites';
|
||||
}
|
||||
|
@ -564,9 +594,6 @@ function convertStreamToPath(stream) {
|
|||
var screenName = stream.substring(stream.indexOf('=')+1);
|
||||
return screenName + '/all';
|
||||
}
|
||||
else if (stream == 'qvitter/statuses/mentions.json') {
|
||||
return window.loggedIn.screen_name + '/replies';
|
||||
}
|
||||
else if(stream == 'statuses/public_timeline.json') {
|
||||
return '';
|
||||
}
|
||||
|
@ -589,6 +616,10 @@ function convertStreamToPath(stream) {
|
|||
var tagName = stream.substring(stream.indexOf('/timeline/')+10,stream.indexOf('.json'));
|
||||
return 'tag/' + tagName;
|
||||
}
|
||||
else if(stream.substring(0,14) == 'statuses/show/') {
|
||||
var noticeId = stream.substring(stream.indexOf('/show/')+6,stream.indexOf('.json'));
|
||||
return 'notice/' + noticeId;
|
||||
}
|
||||
else if(stream.substring(0,11) == 'search.json') {
|
||||
var searchTerms = stream.substring(stream.indexOf('?q=')+3);
|
||||
return 'search/notice?q=' + searchTerms;
|
||||
|
@ -663,6 +694,21 @@ function getStreamFromUrl() {
|
|||
}
|
||||
}
|
||||
|
||||
// {domain}/{screen_name}/notifications
|
||||
else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/notifications','')))) {
|
||||
var userToStream = loc.replace('/','').replace('/notifications','');
|
||||
if(userToStream.length>0) {
|
||||
if(window.loggedIn.screen_name == userToStream) {
|
||||
streamToSet = 'qvitter/statuses/notifications.json';
|
||||
}
|
||||
else {
|
||||
// not allowed for others than logged in user
|
||||
window.location.replace(window.siteInstanceURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// {domain}/{screen_name}/favorites
|
||||
else if ((/^[a-zA-Z0-9]+$/.test(loc.replace('/','').replace('/favorites','')))) {
|
||||
var userToStream = loc.replace('/','').replace('/favorites','');
|
||||
|
@ -723,6 +769,15 @@ function getStreamFromUrl() {
|
|||
}
|
||||
}
|
||||
|
||||
// {domain}/notice/{notide_id}
|
||||
else if (loc.indexOf('/notice/')>-1) {
|
||||
var noticeToStream = loc.replace('/notice/','');
|
||||
if(noticeToStream.length>0) {
|
||||
streamToSet = 'statuses/show/' + noticeToStream + '.json';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// {domain}/group/{group}/members, {domain}/group/{group}/admins or {domain}/group/{group}
|
||||
else if (loc.indexOf('/group/')>-1) {
|
||||
|
||||
|
@ -776,6 +831,10 @@ function expand_queet(q,doScrolling) {
|
|||
var sel = getSelection().toString();
|
||||
|
||||
if(!sel && !q.find('.queet-button').children('button').hasClass('enabled')) { // don't collapse if text is selected, or if queet has an active queet button
|
||||
|
||||
// remove some things right away
|
||||
q.find('.inline-reply-caret').remove();
|
||||
|
||||
q.addClass('collapsing');
|
||||
q.css('overflow','hidden');
|
||||
q.find('.stream-item-expand').html(window.sL.expand);
|
||||
|
@ -793,11 +852,12 @@ function expand_queet(q,doScrolling) {
|
|||
|
||||
// give stream item a height
|
||||
q.css('height',q.height() + 'px');
|
||||
q.children('.queet').find('.expanded-content').css('height',q.find('.expanded-content').height() + 'px');
|
||||
|
||||
q.children('div').not('.queet').children('a').css('opacity','0.5');
|
||||
q.children('div').not('.queet').children().children().css('opacity','0.5');
|
||||
|
||||
var collapseTime = 150 + q.find('.stream-item.conversation:not(.hidden-conversation)').length*50;
|
||||
var collapseTime = 350 + q.find('.stream-item.conversation:not(.hidden-conversation)').length*50;
|
||||
|
||||
// set transition time (needs to be delayed, otherwise webkit animates the height-setting above)
|
||||
setTimeout(function() {
|
||||
|
@ -809,10 +869,15 @@ function expand_queet(q,doScrolling) {
|
|||
q.css('-o-transition-duration',Math.round( collapseTime / 1000 * 10) / 10 + 's');
|
||||
q.css('-webkit-transition-duration',Math.round( collapseTime * 1000 * 10) / 10 + 's');
|
||||
q.css('transition-duration',Math.round( collapseTime / 1000 * 10) / 10 + 's');
|
||||
q.find('.expanded-content').css('-moz-transition-duration',Math.round( collapseTime / 1000 * 10) / 10 + 's');
|
||||
q.find('.expanded-content').css('-o-transition-duration',Math.round( collapseTime / 1000 * 10) / 10 + 's');
|
||||
q.find('.expanded-content').css('-webkit-transition-duration',Math.round( collapseTime * 1000 * 10) / 10 + 's');
|
||||
q.find('.expanded-content').css('transition-duration',Math.round( collapseTime / 1000 * 10) / 10 + 's');
|
||||
|
||||
// set new heights and margins to animate to
|
||||
q.css('height',(q.children('.queet').find('.queet-content').outerHeight() - q.children('.queet').find('.expanded-content').outerHeight() - 10) + 'px');
|
||||
q.css('height',(q.children('.queet').find('.queet-content').outerHeight() - q.children('.queet').find('.expanded-content').outerHeight()) + 'px');
|
||||
q.children('.queet').css('margin-top', '-' + (q.children('.queet').offset().top - q.offset().top) + 'px');
|
||||
q.children('.queet').find('.expanded-content').css('height','0');
|
||||
|
||||
}, 50);
|
||||
|
||||
|
@ -839,12 +904,12 @@ function expand_queet(q,doScrolling) {
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if(!q.hasClass('collapsing')) {
|
||||
|
||||
rememberMyScrollPos(q,qid,-8);
|
||||
|
||||
// not for acitivity
|
||||
if(!q.hasClass('activity')) {
|
||||
// not for acitivity or notifications
|
||||
if(!q.hasClass('activity') && !q.hasClass('repeat') && !q.hasClass('like') && !q.hasClass('follow')) {
|
||||
|
||||
q.addClass('expanded');
|
||||
q.find('.stream-item-expand').html(window.sL.collapse);
|
||||
|
@ -869,7 +934,7 @@ function expand_queet(q,doScrolling) {
|
|||
var metadata = '<span class="longdate" title="' + longdate + '">' + longdate + ' · ' + unescape(q.attr('data-source')) + '</span> · <a href="' + qurl + '" class="permalink-link">' + window.sL.details + '</a>';
|
||||
|
||||
// show expanded content
|
||||
q.find('.stream-item-footer').after('<div class="expanded-content"><div class="queet-stats-container"></div><div class="client-and-actions"><span class="metadata">' + metadata + '</span></div></div>');
|
||||
q.find('.stream-item-footer').before('<div class="expanded-content"><div class="queet-stats-container"></div><div class="client-and-actions"><span class="metadata">' + metadata + '</span></div></div>');
|
||||
|
||||
|
||||
// maybe show images or videos
|
||||
|
@ -1328,12 +1393,67 @@ function checkForHiddenConversationQueets(qid) {
|
|||
|
||||
function addToFeed(feed, after, extraClasses) {
|
||||
|
||||
// some streams, e.g. /statuses/show/1234.json is not enclosed in an array, make sure it is
|
||||
if(!$.isArray(feed)) {
|
||||
feed = [feed];
|
||||
}
|
||||
|
||||
$.each(feed.reverse(), function (key,obj) {
|
||||
|
||||
var extraClassesThisRun = extraClasses;
|
||||
|
||||
// if this is the notifications feed
|
||||
if(window.currentStream.substring(0,35) == 'qvitter/statuses/notifications.json') {
|
||||
|
||||
|
||||
// only if this notification isn't already in stream
|
||||
if($('#stream-item-' + obj.id).length == 0) {
|
||||
|
||||
obj.from_profile.description = obj.from_profile.description || '';
|
||||
var notificationTime = parseTwitterDate(obj.created_at);
|
||||
|
||||
if(obj.is_seen == '0') {
|
||||
extraClassesThisRun = extraClassesThisRun + ' not-seen'
|
||||
}
|
||||
|
||||
if(obj.ntype == 'like') {
|
||||
var noticeTime = parseTwitterDate(obj.notice.created_at);
|
||||
obj.notice = convertNewGNUSocialURItoURL(obj.notice);
|
||||
var notificationHtml = '<div data-quitter-id-in-stream="' + obj.id + '" id="stream-item-' + obj.id + '" class="stream-item ' + extraClassesThisRun + ' notification like"><div class="queet"><div class="queet-content"><div class="stream-item-header"><small class="created-at" data-created-at="' + obj.created_at + '" title="' + obj.created_at + '">' + notificationTime + '</small><a class="account-group" href="' + obj.from_profile.statusnet_profile_url + '"><span class="dogear"></span><img class="avatar" src="' + obj.from_profile.profile_image_url + '" /><strong class="name" data-user-id="' + obj.from_profile.id + '" title="@' + obj.from_profile.screen_name + '">' + obj.from_profile.name + '</strong></a> ' + window.sL.xFavedYourQueet + '</div><div class="small-grey-notice"><a href="' + obj.notice.uri + '">' + noticeTime + '</a>: ' + $.trim(obj.notice.statusnet_html) + '</div></div></div></div>';
|
||||
}
|
||||
else if(obj.ntype == 'repeat') {
|
||||
obj.notice = convertNewGNUSocialURItoURL(obj.notice);
|
||||
var noticeTime = parseTwitterDate(obj.notice.created_at);
|
||||
var notificationHtml = '<div data-quitter-id-in-stream="' + obj.id + '" id="stream-item-' + obj.id + '" class="stream-item ' + extraClassesThisRun + ' notification repeat"><div class="queet"><div class="queet-content"><div class="stream-item-header"><small class="created-at" data-created-at="' + obj.created_at + '" title="' + obj.created_at + '">' + notificationTime + '</small><a class="account-group" href="' + obj.from_profile.statusnet_profile_url + '"><span class="dogear"></span><img class="avatar" src="' + obj.from_profile.profile_image_url + '" /><strong class="name" data-user-id="' + obj.from_profile.id + '" title="@' + obj.from_profile.screen_name + '">' + obj.from_profile.name + '</strong></a> ' + window.sL.xRepeatedYourQueet + '</div><div class="small-grey-notice"><a href="' + obj.notice.uri + '">' + noticeTime + '</a>: ' + $.trim(obj.notice.statusnet_html) + '</div></div></div></div>';
|
||||
}
|
||||
else if(obj.ntype == 'mention') {
|
||||
var notificationHtml = buildQueetHtml(obj.notice, obj.id, extraClassesThisRun + ' notification mention');
|
||||
}
|
||||
else if(obj.ntype == 'reply') {
|
||||
var notificationHtml = buildQueetHtml(obj.notice, obj.id, extraClassesThisRun + ' notification reply');
|
||||
}
|
||||
else if(obj.ntype == 'follow') {
|
||||
var notificationHtml = '<div data-quitter-id-in-stream="' + obj.id + '" id="stream-item-' + obj.id + '" class="stream-item ' + extraClassesThisRun + ' notification follow"><div class="queet"><div class="queet-content"><div class="stream-item-header"><small class="created-at" data-created-at="' + obj.created_at + '" title="' + obj.created_at + '">' + notificationTime + '</small><a class="account-group" href="' + obj.from_profile.statusnet_profile_url + '"><img class="avatar" src="' + obj.from_profile.profile_image_url + '" /><strong class="name" data-user-id="' + obj.from_profile.id + '" title="@' + obj.from_profile.screen_name + '">' + obj.from_profile.name + '</strong></a> ' + window.sL.xStartedFollowingYou + '</div></div></div></div>';
|
||||
}
|
||||
|
||||
if(after) {
|
||||
$('#' + after).after(notificationHtml);
|
||||
}
|
||||
else {
|
||||
$('#feed-body').prepend(notificationHtml);
|
||||
}
|
||||
|
||||
// add not seen notification circle
|
||||
$.each($('.notification.not-seen .queet'),function(){
|
||||
if($(this).children('.not-seen').length<1) {
|
||||
$(this).prepend('<div class="not-seen"></div>');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a user feed
|
||||
if(window.currentStream.substring(0,21) == 'statuses/friends.json'
|
||||
else if(window.currentStream.substring(0,21) == 'statuses/friends.json'
|
||||
|| window.currentStream.substring(0,18) == 'statuses/followers'
|
||||
|| window.currentStream.substring(0,28) == 'statusnet/groups/membership/'
|
||||
|| window.currentStream.substring(0,24) == 'statusnet/groups/admins/') {
|
||||
|
@ -1426,73 +1546,7 @@ function addToFeed(feed, after, extraClasses) {
|
|||
// retweeted object don't exist in feed
|
||||
else {
|
||||
|
||||
// we don't want to print 'null', someone might have that username!
|
||||
var in_reply_to_screen_name = '';
|
||||
if(obj.retweeted_status.in_reply_to_screen_name != null) {
|
||||
in_reply_to_screen_name = obj.retweeted_status.in_reply_to_screen_name;
|
||||
}
|
||||
|
||||
// requeet html
|
||||
var requeetedClass = '';
|
||||
if(obj.retweeted_status.user.id == window.myUserID) {
|
||||
var requeetHtml = '<li class="action-del-container"><a class="with-icn"><span class="icon sm-trash"></span> <b>' + window.sL.deleteVerb + '</b></a></li></i>';
|
||||
}
|
||||
else if(obj.retweeted_status.repeated) {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn done"><span class="icon sm-rt"></span> <b>' + window.sL.requeetedVerb + '</b></a></i>';
|
||||
requeetedClass = 'requeeted';
|
||||
}
|
||||
else {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn"><span class="icon sm-rt"></span> <b>' + window.sL.requeetVerb + '</b></a></i>';
|
||||
}
|
||||
// favorite html
|
||||
var favoritedClass = '';
|
||||
if(obj.retweeted_status.favorited) {
|
||||
var favoriteHtml = '<a class="with-icn done"><span class="icon sm-fav"></span> <b>' + window.sL.favoritedVerb + '</b></a>';
|
||||
favoritedClass = 'favorited';
|
||||
}
|
||||
else {
|
||||
var favoriteHtml = '<a class="with-icn"><span class="icon sm-fav"></span> <b>' + window.sL.favoriteVerb + '</b></a>';
|
||||
}
|
||||
|
||||
// actions only for logged in users
|
||||
var queetActions = '';
|
||||
if(typeof window.loggedIn.screen_name != 'undefined') {
|
||||
queetActions = '<ul class="queet-actions"><li class="action-reply-container"><a class="with-icn"><span class="icon sm-reply"></span> <b>' + window.sL.replyVerb + '</b></a></li>' + requeetHtml + '<li class="action-fav-container">' + favoriteHtml + '</li></ul>';
|
||||
}
|
||||
|
||||
// reply-to html
|
||||
var reply_to_html = '';
|
||||
if(obj.retweeted_status.in_reply_to_screen_name != null && obj.retweeted_status.in_reply_to_screen_name != obj.retweeted_status.user.screen_name) {
|
||||
reply_to_html = '<span class="reply-to">@' + obj.retweeted_status.in_reply_to_screen_name + '</span> ';
|
||||
}
|
||||
|
||||
// in-groups html
|
||||
var in_groups_html = '';
|
||||
if(obj.retweeted_status.statusnet_in_groups !== false && typeof obj.retweeted_status.statusnet_in_groups != 'undefined') {
|
||||
in_groups_html = '<span class="in-groups">' + obj.retweeted_status.statusnet_in_groups + '</span>';
|
||||
}
|
||||
|
||||
|
||||
// image attachment thumbnails
|
||||
var attachment_html = '';
|
||||
if(typeof obj.retweeted_status.attachments != "undefined") {
|
||||
$.each(obj.retweeted_status.attachments, function(){
|
||||
if(this.thumb_url != null) {
|
||||
attachment_html = attachment_html + '<a href="' + this.url + '"><img src="' + this.thumb_url + '"/></a>';
|
||||
}
|
||||
});
|
||||
}
|
||||
if(attachment_html.length>0) {
|
||||
attachment_html = '<div class="attachments">' + attachment_html + '</div>';
|
||||
}
|
||||
|
||||
obj.retweeted_status = convertNewGNUSocialURItoURL(obj.retweeted_status);
|
||||
|
||||
var queetTime = parseTwitterDate(obj.retweeted_status.created_at);
|
||||
var queetHtml = '<div id="stream-item-' + obj.retweeted_status.id + '" class="stream-item ' + extraClassesThisRun + ' ' + requeetedClass + ' ' + favoritedClass + '" data-source="' + escape(obj.retweeted_status.source) + '" data-quitter-id="' + obj.retweeted_status.id + '" data-conversation-id="' + obj.retweeted_status.statusnet_conversation_id + '" data-quitter-id-in-stream="' + obj.id + '" data-in-reply-to-screen-name="' + in_reply_to_screen_name + '" data-in-reply-to-status-id="' + obj.retweeted_status.in_reply_to_status_id + '"><div class="queet" id="q-' + obj.retweeted_status.id + '">' + attachment_html + '<span class="dogear"></span><div class="queet-content"><div class="stream-item-header"><a class="account-group" href="' + obj.retweeted_status.user.statusnet_profile_url + '"><img class="avatar" src="' + obj.retweeted_status.user.profile_image_url_profile_size + '" /><strong class="name" data-user-id="' + obj.retweeted_status.user.id + '">' + obj.retweeted_status.user.name + '</strong> <span class="screen-name">@' + obj.retweeted_status.user.screen_name + '</span></a><i class="addressees">' + reply_to_html + in_groups_html + '</i><small class="created-at" data-created-at="' + obj.retweeted_status.created_at + '"><a href="' + obj.retweeted_status.uri + '">' + queetTime + '</a></small></div><div class="queet-text">' + $.trim(obj.retweeted_status.statusnet_html) + '</div><div class="stream-item-footer">' + queetActions + '<div class="context" id="requeet-' + obj.id + '"><span class="with-icn"><i class="badge-requeeted"></i><span class="requeet-text"> ' + window.sL.requeetedBy + '<a href="' + obj.user.statusnet_profile_url + '"> <b>' + obj.user.name + '</b></a></span></span></div><span class="stream-item-expand">' + window.sL.expand + '</span></div></div></div></div>';
|
||||
|
||||
// detect rtl
|
||||
queetHtml = detectRTL(queetHtml);
|
||||
var queetHtml = buildQueetHtml(obj.retweeted_status, obj.id, extraClassesThisRun, obj);
|
||||
|
||||
if(after) {
|
||||
$('#' + after).after(queetHtml);
|
||||
|
@ -1549,74 +1603,7 @@ function addToFeed(feed, after, extraClasses) {
|
|||
}
|
||||
}
|
||||
|
||||
// we don't want to print 'null' in in_reply_to_screen_name-attribute, someone might have that username!
|
||||
var in_reply_to_screen_name = '';
|
||||
if(obj.in_reply_to_screen_name != null) {
|
||||
in_reply_to_screen_name = obj.in_reply_to_screen_name;
|
||||
}
|
||||
|
||||
// requeet html
|
||||
var requeetedClass = '';
|
||||
if(obj.user.id == window.myUserID) {
|
||||
var requeetHtml = '<li class="action-del-container"><a class="with-icn"><span class="icon sm-trash"></span> <b>' + window.sL.deleteVerb + '</b></a></li></i></li>';
|
||||
}
|
||||
else if(obj.repeated) {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn done"><span class="icon sm-rt"></span> <b>' + window.sL.requeetedVerb + '</b></a></li>';
|
||||
var requeetedClass = 'requeeted';
|
||||
}
|
||||
else {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn"><span class="icon sm-rt"></span> <b>' + window.sL.requeetVerb + '</b></a></li>';
|
||||
}
|
||||
// favorite html
|
||||
var favoritedClass = '';
|
||||
if(obj.favorited) {
|
||||
var favoriteHtml = '<a class="with-icn done"><span class="icon sm-fav"></span> <b>' + window.sL.favoritedVerb + '</b></a>';
|
||||
favoritedClass = 'favorited';
|
||||
}
|
||||
else {
|
||||
var favoriteHtml = '<a class="with-icn"><span class="icon sm-fav"></span> <b>' + window.sL.favoriteVerb + '</b></a>';
|
||||
}
|
||||
|
||||
|
||||
// actions only for logged in users
|
||||
var queetActions = '';
|
||||
if(typeof window.loggedIn.screen_name != 'undefined') {
|
||||
queetActions = '<ul class="queet-actions"><li class="action-reply-container"><a class="with-icn"><span class="icon sm-reply"></span> <b>' + window.sL.replyVerb + '</b></a></li>' + requeetHtml + '<li class="action-fav-container">' + favoriteHtml + '</li></ul>';
|
||||
}
|
||||
|
||||
// reply-to html
|
||||
var reply_to_html = '';
|
||||
if(obj.in_reply_to_screen_name != null && obj.in_reply_to_screen_name != obj.user.screen_name) {
|
||||
reply_to_html = '<span class="reply-to">@' + obj.in_reply_to_screen_name + '</span> ';
|
||||
}
|
||||
|
||||
// in-groups html
|
||||
var in_groups_html = '';
|
||||
if(obj.statusnet_in_groups !== false && typeof obj.statusnet_in_groups != 'undefined') {
|
||||
in_groups_html = '<span class="in-groups">' + obj.statusnet_in_groups + '</span>';
|
||||
}
|
||||
|
||||
// image attachment thumbnails
|
||||
var attachment_html = '';
|
||||
if(typeof obj.attachments != "undefined") {
|
||||
$.each(obj.attachments, function(){
|
||||
if(this.thumb_url != null) {
|
||||
attachment_html = attachment_html + '<a href="' + this.url + '"><img src="' + this.thumb_url + '"/></a>';
|
||||
}
|
||||
});
|
||||
}
|
||||
if(attachment_html.length>0) {
|
||||
attachment_html = '<div class="attachments">' + attachment_html + '</div>';
|
||||
}
|
||||
|
||||
|
||||
obj = convertNewGNUSocialURItoURL(obj);
|
||||
|
||||
var queetTime = parseTwitterDate(obj.created_at);
|
||||
var queetHtml = '<div id="stream-item-' + obj.id + '" class="stream-item ' + extraClassesThisRun + ' ' + requeetedClass + ' ' + favoritedClass + '" data-source="' + escape(obj.source) + '" data-quitter-id="' + obj.id + '" data-conversation-id="' + obj.statusnet_conversation_id + '" data-quitter-id-in-stream="' + obj.id + '" data-in-reply-to-screen-name="' + in_reply_to_screen_name + '" data-in-reply-to-status-id="' + obj.in_reply_to_status_id + '"><div class="queet" id="q-' + obj.id + '">' + attachment_html + '<span class="dogear"></span><div class="queet-content"><div class="stream-item-header"><a class="account-group" href="' + obj.user.statusnet_profile_url + '"><img class="avatar" src="' + obj.user.profile_image_url_profile_size + '" /><strong class="name" data-user-id="' + obj.user.id + '">' + obj.user.name + '</strong> <span class="screen-name">@' + obj.user.screen_name + '</span></a><i class="addressees">' + reply_to_html + in_groups_html + '</i><small class="created-at" data-created-at="' + obj.created_at + '"><a href="' + obj.uri + '">' + queetTime + '</a></small></div><div class="queet-text">' + $.trim(obj.statusnet_html) + '</div><div class="stream-item-footer">' + queetActions + '<span class="stream-item-expand">' + window.sL.expand + '</span></div></div></div></div>';
|
||||
|
||||
// detect rtl
|
||||
queetHtml = detectRTL(queetHtml);
|
||||
var queetHtml = buildQueetHtml(obj, obj.id, extraClassesThisRun);
|
||||
|
||||
if(after) {
|
||||
if($('#' + after).hasClass('conversation')) { // if this is a reply, give stream item some conversation formatting
|
||||
|
@ -1631,6 +1618,12 @@ function addToFeed(feed, after, extraClasses) {
|
|||
}
|
||||
else {
|
||||
$('#feed-body').prepend(queetHtml);
|
||||
|
||||
// if this is a single notice, we expand it
|
||||
if(window.currentStream.substring(0,14) == 'statuses/show/') {
|
||||
expand_queet($('#stream-item-' + obj.id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1642,61 +1635,125 @@ function addToFeed(feed, after, extraClasses) {
|
|||
$('.stream-selection').removeAttr('data-current-user-stream-name'); // don't remeber user feeds
|
||||
}
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· View threaded converation
|
||||
· Build HTML for a queet from an object
|
||||
·
|
||||
· @param id: the stream item id
|
||||
·
|
||||
· (experimental, not finished, commented out...)
|
||||
· @param obj: a queet object
|
||||
· @param requeeted_by: if this is a requeet
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
// $('body').on('click','.longdate',function(){
|
||||
// threadedConversation($(this).closest('.stream-item:not(.conversation)').attr('data-quitter-id'));
|
||||
// })
|
||||
// function threadedConversation(id){
|
||||
// $('body').prepend('<div id="threaded-' + id + '" class="modal-container"><div class="thread-container" style="margin-left:0;"><div></div></div></div>');
|
||||
// var scrollTop = $(window).scrollTop();
|
||||
// var containerStreamItem = $('#stream-item-' + id);
|
||||
// if(containerStreamItem.children('div:first-child').hasClass('.queet')) {
|
||||
// var firstStreamItemId = id;
|
||||
// }
|
||||
// else {
|
||||
// var firstStreamItemId = containerStreamItem.children('div:first-child').attr('data-quitter-id');
|
||||
// }
|
||||
// getThreadedReply(id,firstStreamItemId,$('#threaded-' + id + ' .thread-container div'));
|
||||
// }
|
||||
//
|
||||
// function getThreadedReply(containerStreamId,this_id,appendToObj) {
|
||||
//
|
||||
// var $this_item = $('<div/>').append($('.stream-item[data-quitter-id="' + this_id + '"]').outerHTML());
|
||||
// $this_item.children().children().remove('.stream-item.conversation');
|
||||
// $this_item.children('.stream-item').css('margin-left',parseInt(appendToObj.css('margin-left'),10)+20 + 'px');
|
||||
// $this_item.children('.stream-item').removeClass('hidden-conversation');
|
||||
// $this_item.children('.stream-item').removeClass('expanded');
|
||||
// $this_item.children('.stream-item').removeClass('activity');
|
||||
// $this_item.children('.stream-item').removeClass('conversation');
|
||||
// $this_item.children('.stream-item').removeClass('visible');
|
||||
// $this_item.children('.stream-item').children('div:not(.queet)').remove();
|
||||
// $this_item.children('.stream-item').find('.inline-reply-queetbox').remove();
|
||||
// $this_item.children('.stream-item').find('.expanded-content').remove();
|
||||
// $this_item.children('.stream-item').find('.stream-item-expand').remove();
|
||||
// $this_item.children('.stream-item').css('opacity','1');
|
||||
// appendToObj.after($this_item.html());
|
||||
//
|
||||
// $.each($('.stream-item[data-quitter-id="' + containerStreamId + '"]').children().get().reverse(),function(){
|
||||
// if($(this).hasClass('queet')) {
|
||||
// var this_reply_to = $(this).parent().attr('data-in-reply-to-status-id');
|
||||
// var childs_id = $(this).parent().attr('data-quitter-id');
|
||||
// }
|
||||
// else {
|
||||
// var this_reply_to = $(this).attr('data-in-reply-to-status-id');
|
||||
// var childs_id = $(this).attr('data-quitter-id');
|
||||
// }
|
||||
// if(this_id == this_reply_to) {
|
||||
// getThreadedReply(containerStreamId,childs_id,$('#threaded-' + containerStreamId + ' .stream-item[data-quitter-id="' + this_id + '"]'));
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by) {
|
||||
|
||||
// we don't want to print 'null' in in_reply_to_screen_name-attribute, someone might have that username!
|
||||
var in_reply_to_screen_name = '';
|
||||
if(obj.in_reply_to_screen_name != null) {
|
||||
in_reply_to_screen_name = obj.in_reply_to_screen_name;
|
||||
}
|
||||
|
||||
// requeet html
|
||||
var requeetedClass = '';
|
||||
if(obj.user.id == window.myUserID) {
|
||||
var requeetHtml = '<li class="action-del-container"><a class="with-icn"><span class="icon sm-trash"></span> <b>' + window.sL.deleteVerb + '</b></a></li></i></li>';
|
||||
}
|
||||
else if(obj.repeated) {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn done"><span class="icon sm-rt"></span> <b>' + window.sL.requeetedVerb + '</b></a></li>';
|
||||
var requeetedClass = 'requeeted';
|
||||
}
|
||||
else {
|
||||
var requeetHtml = '<li class="action-rt-container"><a class="with-icn"><span class="icon sm-rt"></span> <b>' + window.sL.requeetVerb + '</b></a></li>';
|
||||
}
|
||||
// favorite html
|
||||
var favoritedClass = '';
|
||||
if(obj.favorited) {
|
||||
var favoriteHtml = '<a class="with-icn done"><span class="icon sm-fav"></span> <b>' + window.sL.favoritedVerb + '</b></a>';
|
||||
favoritedClass = 'favorited';
|
||||
}
|
||||
else {
|
||||
var favoriteHtml = '<a class="with-icn"><span class="icon sm-fav"></span> <b>' + window.sL.favoriteVerb + '</b></a>';
|
||||
}
|
||||
|
||||
|
||||
// actions only for logged in users
|
||||
var queetActions = '';
|
||||
if(typeof window.loggedIn.screen_name != 'undefined') {
|
||||
queetActions = '<ul class="queet-actions"><li class="action-reply-container"><a class="with-icn"><span class="icon sm-reply"></span> <b>' + window.sL.replyVerb + '</b></a></li>' + requeetHtml + '<li class="action-fav-container">' + favoriteHtml + '</li></ul>';
|
||||
}
|
||||
|
||||
// reply-to html
|
||||
var reply_to_html = '';
|
||||
if(obj.in_reply_to_screen_name != null && obj.in_reply_to_screen_name != obj.user.screen_name) {
|
||||
reply_to_html = '<span class="reply-to">@' + obj.in_reply_to_screen_name + '</span> ';
|
||||
}
|
||||
|
||||
// in-groups html
|
||||
var in_groups_html = '';
|
||||
if(obj.statusnet_in_groups !== false && typeof obj.statusnet_in_groups != 'undefined') {
|
||||
in_groups_html = '<span class="in-groups">' + obj.statusnet_in_groups + '</span>';
|
||||
}
|
||||
|
||||
// image attachment thumbnails
|
||||
var attachment_html = '';
|
||||
if(typeof obj.attachments != "undefined") {
|
||||
$.each(obj.attachments, function(){
|
||||
if(this.thumb_url != null) {
|
||||
attachment_html = attachment_html + '<a href="' + this.url + '"><img src="' + this.thumb_url + '"/></a>';
|
||||
}
|
||||
});
|
||||
}
|
||||
if(attachment_html.length>0) {
|
||||
attachment_html = '<div class="attachments">' + attachment_html + '</div>';
|
||||
}
|
||||
|
||||
// requeets
|
||||
var requeetHtml = '';
|
||||
if(typeof requeeted_by != 'undefined') {
|
||||
requeetHtml = '<div class="context" id="requeet-' + requeeted_by.id + '"><span class="with-icn"><i class="badge-requeeted"></i><span class="requeet-text"> ' + window.sL.requeetedBy + '<a href="' + requeeted_by.user.statusnet_profile_url + '"> <b>' + requeeted_by.user.name + '</b></a></span></span></div>';
|
||||
}
|
||||
|
||||
|
||||
obj = convertNewGNUSocialURItoURL(obj);
|
||||
|
||||
var queetTime = parseTwitterDate(obj.created_at);
|
||||
var queetHtml = '<div \
|
||||
id="stream-item-' + obj.id + '" \
|
||||
class="stream-item ' + extraClassesThisRun + ' ' + requeetedClass + ' ' + favoritedClass + '" \
|
||||
data-source="' + escape(obj.source) + '" \
|
||||
data-quitter-id="' + obj.id + '" \
|
||||
data-conversation-id="' + obj.statusnet_conversation_id + '" \
|
||||
data-quitter-id-in-stream="' + idInStream + '" \
|
||||
data-in-reply-to-screen-name="' + in_reply_to_screen_name + '" \
|
||||
data-in-reply-to-status-id="' + obj.in_reply_to_status_id + '">\
|
||||
<div class="queet" id="q-' + obj.id + '">\
|
||||
' + attachment_html + '\
|
||||
<span class="dogear"></span>\
|
||||
<div class="queet-content">\
|
||||
<div class="stream-item-header">\
|
||||
<a class="account-group" href="' + obj.user.statusnet_profile_url + '">\
|
||||
<img class="avatar" src="' + obj.user.profile_image_url_profile_size + '" />\
|
||||
<strong class="name" data-user-id="' + obj.user.id + '">' + obj.user.name + '</strong> \
|
||||
<span class="screen-name">@' + obj.user.screen_name + '</span>\
|
||||
</a>\
|
||||
<i class="addressees">' + reply_to_html + in_groups_html + '</i>\
|
||||
<small class="created-at" data-created-at="' + obj.created_at + '">\
|
||||
<a href="' + obj.uri + '">' + queetTime + '</a>\
|
||||
</small>\
|
||||
</div>\
|
||||
<div class="queet-text">' + $.trim(obj.statusnet_html) + '</div>\
|
||||
<div class="stream-item-footer">\
|
||||
' + queetActions + '\
|
||||
' + requeetHtml + '\
|
||||
<span class="stream-item-expand">' + window.sL.expand + '</span>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
// detect rtl
|
||||
queetHtml = detectRTL(queetHtml);
|
||||
|
||||
return queetHtml;
|
||||
}
|
||||
|
||||
|
||||
|
|
75
js/lan.js
75
js/lan.js
|
@ -146,6 +146,11 @@ window.l.es.registerRepeatPassword = 'Verificar contraseña';
|
|||
window.l.es.moreSettings = 'Más configuraciones';
|
||||
window.l.es.otherServers = 'De manera alternativa, puedes crear una cuenta en otro servidor de la red GNUsocial. <a href="http://federation.skilledtests.com/select_your_server.html">Comparativa</a>';
|
||||
window.l.es.editMyProfile = 'Editar perfil';
|
||||
window.l.es.notifications = 'Notificaciones';
|
||||
window.l.es.xFavedYourQueet = 'marcó tu Queet como favorito';
|
||||
window.l.es.xRepeatedYourQueet = 'te ha requitteado ';
|
||||
window.l.es.xStartedFollowingYou = 'te ha seguido';
|
||||
|
||||
|
||||
|
||||
// Português-Brasil
|
||||
|
@ -257,6 +262,13 @@ window.l.pt_br.registerRepeatPassword = 'Repetir senha';
|
|||
window.l.pt_br.moreSettings = 'Mais configurações';
|
||||
window.l.pt_br.otherServers = 'De manera alternativa, você pode criar uma conta em outro servidor da rede GNUsocial. <a href="http://federation.skilledtests.com/select_your_server.html">Comparativo</a>';
|
||||
window.l.pt_br.editMyProfile = 'Editar perfil';
|
||||
window.l.pt_br.notifications = 'Notificações';
|
||||
window.l.pt_br.xFavedYourQueet = 'curtiu seu Queet';
|
||||
window.l.pt_br.xRepeatedYourQueet = 'requeetou você';
|
||||
window.l.pt_br.xStartedFollowingYou = 'seguiu você';
|
||||
|
||||
|
||||
|
||||
|
||||
// galician
|
||||
window.l.gl = new Object();
|
||||
|
@ -367,6 +379,10 @@ window.l.gl.registerRepeatPassword = 'Verificar contrasinal';
|
|||
window.l.gl.moreSettings = 'máis opcións';
|
||||
window.l.gl.otherServers = 'De maneira alternativa, podes crear unha conta noutro servidor da rede GNUsocial. <a href="http://federation.skilledtests.com/select_your_server.html">Comparativa</a>';
|
||||
window.l.gl.editMyProfile = 'Editar o perfil';
|
||||
window.l.gl.notifications = 'Notificacións';
|
||||
window.l.gl.xFavedYourQueet = 'marcou como favorito o teu chío';
|
||||
window.l.gl.xRepeatedYourQueet = 'rechouchioute';
|
||||
window.l.gl.xStartedFollowingYou = 'está a seguirte';
|
||||
|
||||
|
||||
// basque
|
||||
|
@ -478,6 +494,11 @@ window.l.eu.registerRepeatPassword = 'Errepikatu pasahitza';
|
|||
window.l.eu.moreSettings = 'Aukera gehiago';
|
||||
window.l.eu.otherServers = 'GNU social sareko beste nodo batean sor dezakezu kontu bat nahi izanez gero. <a href="http://federation.skilledtests.com/select_your_server.html">Alderatu</a>';
|
||||
window.l.eu.editMyProfile = 'Editatu profila';
|
||||
window.l.eu.notifications = 'Jakinarazpenak';
|
||||
window.l.eu.xFavedYourQueet = 'erabiltzaileak gustuko du zure Txioa';
|
||||
window.l.eu.xRepeatedYourQueet = 'erabiltzaileak bertxiotu zaitu';
|
||||
window.l.eu.xStartedFollowingYou = 'jarraitzen hasi zaizu';
|
||||
|
||||
|
||||
// french
|
||||
window.l.fr = new Object();
|
||||
|
@ -588,6 +609,10 @@ window.l.fr.registerRepeatPassword = 'Vérifiez votre mot de passe';
|
|||
window.l.fr.moreSettings = 'Plus de paramètres';
|
||||
window.l.fr.otherServers = '';
|
||||
window.l.fr.editMyProfile = 'Éditer le profil';
|
||||
window.l.fr.notifications = 'Notifications';
|
||||
window.l.fr.xFavedYourQueet = 'a ajouté votre Queet à ses favoris ';
|
||||
window.l.fr.xRepeatedYourQueet = 'vous a requeeté ';
|
||||
window.l.fr.xStartedFollowingYou = 'vous a suivi';
|
||||
|
||||
|
||||
// deutsch
|
||||
|
@ -711,6 +736,10 @@ window.l.de.registerRepeatPassword = 'Passwort bestätigen';
|
|||
window.l.de.moreSettings = 'Weitere Einstellungen';
|
||||
window.l.de.otherServers = 'Du kannst Dir auch gerne ein Konto auf einem anderen Server des GNUsocial-Netzwerks einrichten. <a href="http://federation.skilledtests.com/select_your_server.html">Übersicht</a>';
|
||||
window.l.de.editMyProfile = 'Profil bearbeiten';
|
||||
window.l.de.notifications = 'Mitteilungen';
|
||||
window.l.de.xFavedYourQueet = 'favorisierte Deinen Queet';
|
||||
window.l.de.xRepeatedYourQueet = 'hat Dich requeetet';
|
||||
window.l.de.xStartedFollowingYou = 'folgt Dir jetzt';
|
||||
|
||||
|
||||
// english
|
||||
|
@ -830,6 +859,12 @@ window.l.en.registerRepeatPassword = 'Repeat password';
|
|||
window.l.en.moreSettings = 'More settings';
|
||||
window.l.en.otherServers = 'Alternatively you can create an account on another server of the GNU social network. <a href="http://federation.skilledtests.com/select_your_server.html">Comparison</a>';
|
||||
window.l.en.editMyProfile = 'Edit profile';
|
||||
window.l.en.notifications = 'Notifications';
|
||||
window.l.en.xFavedYourQueet = 'favorited your Queet';
|
||||
window.l.en.xRepeatedYourQueet = 'requeeted you';
|
||||
window.l.en.xStartedFollowingYou = 'followed you';
|
||||
|
||||
|
||||
|
||||
// simplified chinese
|
||||
window.l.zh_cn = new Object();
|
||||
|
@ -940,6 +975,12 @@ window.l.zh_cn.registerRepeatPassword = '重复密码';
|
|||
window.l.zh_cn.moreSettings = '更多的设置';
|
||||
window.l.zh_cn.otherServers = '其他服务器: <a href="http://federation.skilledtests.com/select_your_server.html">对照</a>';
|
||||
window.l.zh_cn.editMyProfile = '编辑个人资料';
|
||||
window.l.zh_cn.notifications = '通知';
|
||||
window.l.zh_cn.xFavedYourQueet = '收藏了你的推文';
|
||||
window.l.zh_cn.xRepeatedYourQueet = '转推了你的推文';
|
||||
window.l.zh_cn.xStartedFollowingYou = '关注了你';
|
||||
|
||||
|
||||
|
||||
// traditional chinese
|
||||
window.l.zh_tw = new Object();
|
||||
|
@ -1050,6 +1091,12 @@ window.l.zh_tw.registerRepeatPassword = '重複密碼';
|
|||
window.l.zh_tw.moreSettings = '更多的設置';
|
||||
window.l.zh_tw.otherServers = '其他服務器: <a href="http://federation.skilledtests.com/select_your_server.html">對照</a>';
|
||||
window.l.zh_tw.editMyProfile = '編輯個人檔案';
|
||||
window.l.zh_tw.notifications = '通知';
|
||||
window.l.zh_tw.xFavedYourQueet = '已收藏你的推文';
|
||||
window.l.zh_tw.xRepeatedYourQueet = '已轉推你';
|
||||
window.l.zh_tw.xStartedFollowingYou = '已跟隨你';
|
||||
|
||||
|
||||
|
||||
// svenska
|
||||
window.l.sv = new Object();
|
||||
|
@ -1160,7 +1207,10 @@ window.l.sv.registerRepeatPassword = 'Upprepa lösenord';
|
|||
window.l.sv.moreSettings = 'Fler inställningar';
|
||||
window.l.sv.otherServers = 'Men du kan lika gärna skapa ett konto på en annan server som är del av GNU social-nätverket. <a href="http://federation.skilledtests.com/select_your_server.html">Här är en jämförelse.</a>';
|
||||
window.l.sv.editMyProfile = 'Redigera profil';
|
||||
|
||||
window.l.sv.notifications = 'Notiser';
|
||||
window.l.sv.xFavedYourQueet = 'favoritmarkerade ditt qvitter';
|
||||
window.l.sv.xRepeatedYourQueet = 'requeetade dig';
|
||||
window.l.sv.xStartedFollowingYou = 'följde dig';
|
||||
|
||||
// farsi/persian
|
||||
window.l.fa = new Object();
|
||||
|
@ -1271,6 +1321,10 @@ window.l.fa.registerRepeatPassword = 'تایید گذرواژه';
|
|||
window.l.fa.moreSettings = 'تنظیمات بیشتر';
|
||||
window.l.fa.otherServers = '';
|
||||
window.l.fa.editMyProfile = 'ویرایش نمایه';
|
||||
window.l.fa.notifications = 'آگاهسازیها';
|
||||
window.l.fa.xFavedYourQueet = 'موارد دلخواه خود را صدای جیر جیر';
|
||||
window.l.fa.xRepeatedYourQueet = 'توییت شما را باز توییت کرد.';
|
||||
window.l.fa.xStartedFollowingYou = 'شما را دنبال کرد';
|
||||
|
||||
// arabic
|
||||
window.l.ar = new Object();
|
||||
|
@ -1381,6 +1435,10 @@ window.l.ar.registerRepeatPassword = 'تأكيد كلمة المرور';
|
|||
window.l.ar.moreSettings = 'مزيد من الإعدادات';
|
||||
window.l.ar.otherServers = '';
|
||||
window.l.ar.editMyProfile = 'تعديل الملف الشخصي';
|
||||
window.l.ar.notifications = 'التنبيهات';
|
||||
window.l.ar.xFavedYourQueet = 'بتفضيل تغريدتك';
|
||||
window.l.ar.xRepeatedYourQueet = 'بإعادة تغريد';
|
||||
window.l.ar.xStartedFollowingYou = 'بمتابعتك';
|
||||
|
||||
// esperanto
|
||||
window.l.eo = new Object();
|
||||
|
@ -1500,7 +1558,10 @@ window.l.eo.registerRepeatPassword = 'Ripeti pasvorton';
|
|||
window.l.eo.moreSettings = 'Pli agordoj';
|
||||
window.l.eo.otherServers = '';
|
||||
window.l.eo.editMyProfile = 'Redaktu profilon';
|
||||
|
||||
window.l.eo.notifications = 'Sciigoj';
|
||||
window.l.eo.xFavedYourQueet = 'ŝatataj via avizo';
|
||||
window.l.eo.xRepeatedYourQueet = 'ripetis vin';
|
||||
window.l.eo.xStartedFollowingYou = 'sekvas vin';
|
||||
|
||||
// italian
|
||||
window.l.it = new Object();
|
||||
|
@ -1620,6 +1681,10 @@ window.l.it.registerRepeatPassword = 'Ripetere la password';
|
|||
window.l.it.moreSettings = 'Altre opzioni';
|
||||
window.l.it.otherServers = 'In alternativa puoi creare un account su un altro server della rete GNU Social. <a href="http://federation.skilledtests.com/select_your_server.html">Confronto</a>';
|
||||
window.l.it.editMyProfile = 'Modifica profilo';
|
||||
window.l.it.notifications = 'Notifiche';
|
||||
window.l.it.xFavedYourQueet = 'ha aggiunto ai preferiti il tuo Queet';
|
||||
window.l.it.xRepeatedYourQueet = 'ti ha requittato';
|
||||
window.l.it.xStartedFollowingYou = 'ha iniziato a seguirti';
|
||||
|
||||
// Norwegian
|
||||
window.l.no = new Object();
|
||||
|
@ -1730,6 +1795,10 @@ window.l.no.registerRepeatPassword = 'Gjenta passord';
|
|||
window.l.no.moreSettings = 'Flere instillinger';
|
||||
window.l.no.otherServers = 'Det finnes flere instanser i GNUsocial nettverket som alternativt kan benyttes. <a href="http://gnu.io/social/try/">Følger du denne lenken finner du noen anbefalinger.</a>';
|
||||
window.l.no.editMyProfile = 'Rediger profil';
|
||||
window.l.no.notifications = 'Varsler';
|
||||
window.l.no.xFavedYourQueet = 'favorittmarkerte queeten din';
|
||||
window.l.no.xRepeatedYourQueet = 'requeetet deg';
|
||||
window.l.no.xStartedFollowingYou = 'følger deg';
|
||||
|
||||
|
||||
// set language, from local storage, else browser language, else english (english also if no localstorage availible)
|
||||
|
@ -1797,6 +1866,8 @@ $('.stream-selection[data-stream-name="qvitter/statuses/friends_timeline.json"]'
|
|||
$('.stream-selection[data-stream-name="qvitter/statuses/friends_timeline.json"]').attr('data-stream-header',window.sL.timeline);
|
||||
$('.stream-selection[data-stream-name="qvitter/statuses/mentions.json"]').prepend(window.sL.mentions);
|
||||
$('.stream-selection[data-stream-name="qvitter/statuses/mentions.json"]').attr('data-stream-header',window.sL.mentions);
|
||||
$('.stream-selection[data-stream-name="qvitter/statuses/notifications.json"]').prepend(window.sL.notifications);
|
||||
$('.stream-selection[data-stream-name="qvitter/statuses/notifications.json"]').attr('data-stream-header',window.sL.notifications);
|
||||
$('.stream-selection[data-stream-name="favorites.json"]').prepend(window.sL.favoritesNoun);
|
||||
$('.stream-selection[data-stream-name="favorites.json"]').attr('data-stream-header',window.sL.favoritesNoun);
|
||||
$('.stream-selection[data-stream-name="statuses/public_timeline.json"]').prepend(window.sL.publicTimeline);
|
||||
|
|
6
js/lib/jquery-2.0.2.min.js
vendored
6
js/lib/jquery-2.0.2.min.js
vendored
File diff suppressed because one or more lines are too long
4
js/lib/jquery-2.1.1.min.js
vendored
Normal file
4
js/lib/jquery-2.1.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -458,25 +458,27 @@ function findUrls(text) {
|
|||
· · · · · · · · · · · · */
|
||||
|
||||
function display_spinner() {
|
||||
$('body').prepend('\
|
||||
<div class="loader">\
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\
|
||||
width="40px" height="40px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">\
|
||||
<path opacity="0.2" enable-background="new " d="M20.201,8.503c-6.413,0-11.612,5.199-11.612,11.612s5.199,11.611,11.612,11.611\
|
||||
c6.412,0,11.611-5.198,11.611-11.611S26.613,8.503,20.201,8.503z M20.201,29.153c-4.992,0-9.039-4.046-9.039-9.038\
|
||||
s4.047-9.039,9.039-9.039c4.991,0,9.038,4.047,9.038,9.039S25.192,29.153,20.201,29.153z"/>\
|
||||
<path d="M24.717,12.293l1.285-2.227c-1.708-0.988-3.686-1.563-5.801-1.563l0,0v2.573l0,0C21.848,11.076,23.386,11.524,24.717,12.293 z">\
|
||||
<animateTransform attributeType="xml"\
|
||||
attributeName="transform"\
|
||||
type="rotate"\
|
||||
from="0 20 20"\
|
||||
to="360 20 20"\
|
||||
dur="1s"\
|
||||
repeatCount="indefinite"/>\
|
||||
</path>\
|
||||
</svg>\
|
||||
</div>\
|
||||
');
|
||||
if($('.loader').length<1) {
|
||||
$('body').prepend('\
|
||||
<div class="loader">\
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\
|
||||
width="40px" height="40px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">\
|
||||
<path opacity="0.2" enable-background="new " d="M20.201,8.503c-6.413,0-11.612,5.199-11.612,11.612s5.199,11.611,11.612,11.611\
|
||||
c6.412,0,11.611-5.198,11.611-11.611S26.613,8.503,20.201,8.503z M20.201,29.153c-4.992,0-9.039-4.046-9.039-9.038\
|
||||
s4.047-9.039,9.039-9.039c4.991,0,9.038,4.047,9.038,9.039S25.192,29.153,20.201,29.153z"/>\
|
||||
<path d="M24.717,12.293l1.285-2.227c-1.708-0.988-3.686-1.563-5.801-1.563l0,0v2.573l0,0C21.848,11.076,23.386,11.524,24.717,12.293 z">\
|
||||
<animateTransform attributeType="xml"\
|
||||
attributeName="transform"\
|
||||
type="rotate"\
|
||||
from="0 20 20"\
|
||||
to="360 20 20"\
|
||||
dur="1s"\
|
||||
repeatCount="indefinite"/>\
|
||||
</path>\
|
||||
</svg>\
|
||||
</div>\
|
||||
');
|
||||
}
|
||||
}
|
||||
function remove_spinner() {
|
||||
$('.loader').remove();
|
||||
|
|
|
@ -59,12 +59,12 @@ window.onpopstate = function(event) {
|
|||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
window.loginContentStartPos = $('.front-welcome-text').height()+45;
|
||||
$(window).scroll(function(e){
|
||||
if ($(this).scrollTop() > window.loginContentStartPos && $('#login-content').css('position') != 'fixed'){
|
||||
// console.log($('#feed').offset().top);
|
||||
if ($(this).scrollTop() > ($('#feed').offset().top-50) && $('#login-content').css('position') != 'fixed'){
|
||||
$('#login-content, .front-signup').not('#popup-signup').css({'position': 'fixed', 'top': '50px'});
|
||||
}
|
||||
else if ($(this).scrollTop() < window.loginContentStartPos && $('#login-content').css('position') != 'absolute'){
|
||||
else if ($(this).scrollTop() < ($('#feed').offset().top-50) && $('#login-content').css('position') != 'absolute'){
|
||||
$('#login-content, .front-signup').not('#popup-signup').css({'position': 'absolute', 'top': 'auto'});
|
||||
}
|
||||
});
|
||||
|
@ -123,9 +123,9 @@ if(!window.registrationsClosed) {
|
|||
$('#signup-user-nickname-step2').after('<div class="spinner-wrap"><div class="spinner"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div>');
|
||||
}
|
||||
window.checkNicknameTimeout = setTimeout(function(){
|
||||
getFromAPI('check_nickname.json?nickname=' + encodeURIComponent($('#signup-user-nickname-step2').val()),function(data){
|
||||
$.get(window.apiRoot + 'check_nickname.json?nickname=' + encodeURIComponent($('#signup-user-nickname-step2').val()),function(data){
|
||||
$('.spinner-wrap').remove();
|
||||
if(data=='taken') {
|
||||
if(data==0) {
|
||||
$('#signup-user-password2-step2').trigger('keyup'); // revalidates
|
||||
}
|
||||
else {
|
||||
|
@ -288,6 +288,7 @@ function doLogin(streamToSet) {
|
|||
// add user data to DOM, show search form, remeber user id, show the feed
|
||||
$('#user-container').css('z-index','1000');
|
||||
$('#top-compose').removeClass('hidden');
|
||||
$('#qvitter-notice').show();
|
||||
$('#user-avatar').attr('src', window.loggedIn.profile_image_url_profile_size);
|
||||
$('#user-name').append(window.loggedIn.name);
|
||||
$('#user-screen-name').append(window.loggedIn.screen_name);
|
||||
|
@ -298,6 +299,7 @@ function doLogin(streamToSet) {
|
|||
$('#user-groups strong').html(window.loggedIn.groups_count);
|
||||
$('.stream-selection.friends-timeline').attr('href', window.loggedIn.statusnet_profile_url + '/all');
|
||||
$('.stream-selection.mentions').attr('href', window.loggedIn.statusnet_profile_url + '/replies');
|
||||
$('.stream-selection.notifications').attr('href', window.loggedIn.statusnet_profile_url + '/notifications');
|
||||
$('.stream-selection.my-timeline').attr('href', window.loggedIn.statusnet_profile_url);
|
||||
$('.stream-selection.favorites').attr('href', window.loggedIn.statusnet_profile_url + '/favorites');
|
||||
window.myUserID = window.loggedIn.id;
|
||||
|
@ -668,6 +670,12 @@ $('body').on('click','.profile-banner-footer .stats li a, .queet-stream',functio
|
|||
else if($(this).hasClass('favorites')) {
|
||||
setNewCurrentStream('favorites.json?screen_name=' + screenName,function(){},true);
|
||||
}
|
||||
else if($(this).hasClass('following')) {
|
||||
setNewCurrentStream('statuses/friends.json?count=20',function(){},true);
|
||||
}
|
||||
else if($(this).hasClass('followers')) {
|
||||
setNewCurrentStream('statuses/followers.json?count=20',function(){},true);
|
||||
}
|
||||
else if($(this).hasClass('member-stats')) {
|
||||
setNewCurrentStream('statusnet/groups/membership/' + screenName + '.json?count=20',function(){},true);
|
||||
}
|
||||
|
@ -737,6 +745,10 @@ $(document).on('click','a', function(e) {
|
|||
e.preventDefault();
|
||||
setNewCurrentStream('qvitter/statuses/mentions.json',function(){},true);
|
||||
}
|
||||
else if ($(this).attr('href').replace('http://','').replace('https://','').replace(window.siteRootDomain + '/' + window.loggedIn.screen_name,'') == '/notifications') {
|
||||
e.preventDefault();
|
||||
setNewCurrentStream('qvitter/statuses/notifications.json',function(){},true);
|
||||
}
|
||||
else if ($(this).attr('href').replace('http://','').replace('https://','').replace(window.siteRootDomain + '/' + window.loggedIn.screen_name,'') == '/favorites') {
|
||||
e.preventDefault();
|
||||
setNewCurrentStream('favorites.json',function(){},true);
|
||||
|
@ -747,9 +759,6 @@ $(document).on('click','a', function(e) {
|
|||
if($(this).parent().attr('id') == 'user-profile-link') { // logged in user
|
||||
setNewCurrentStream('statuses/user_timeline.json?screen_name=' + window.loggedIn.screen_name,function(){},true);
|
||||
}
|
||||
else if($(this).hasClass('account-group')) { // any user
|
||||
setNewCurrentStream('statuses/user_timeline.json?screen_name=' + $(this).find('.screen-name').text().substring(1).toLowerCase(),function(){},true);
|
||||
}
|
||||
else { // any user
|
||||
setNewCurrentStream('statuses/user_timeline.json?screen_name=' + $(this).attr('href').replace('http://','').replace('https://','').replace(window.siteRootDomain + '/',''),function(){},true);
|
||||
}
|
||||
|
@ -763,6 +772,11 @@ $(document).on('click','a', function(e) {
|
|||
e.preventDefault();
|
||||
setNewCurrentStream('statusnet/tags/timeline/' + $(this).text().toLowerCase().replace('#','') + '.json',function(){},true);
|
||||
}
|
||||
// notices
|
||||
else if ($(this).attr('href').indexOf(window.siteRootDomain + '/notice/')>-1) {
|
||||
e.preventDefault();
|
||||
setNewCurrentStream('statuses/show/' + $(this).attr('href').replace('http://','').replace('https://','').replace(window.siteRootDomain + '/notice/','') + '.json',function(){},true);
|
||||
}
|
||||
// groups
|
||||
else if (/^[0-9]+$/.test($(this).attr('href').replace('http://','').replace('https://','').replace(window.siteRootDomain + '/group/','').replace('/id',''))) {
|
||||
e.preventDefault();
|
||||
|
@ -1005,10 +1019,12 @@ var updateTimesInterval=self.setInterval(function(){
|
|||
|
||||
/* ·
|
||||
·
|
||||
· Check for new queets
|
||||
· Check for new queets and notifications
|
||||
·
|
||||
· · · · · · · · · · · · · */
|
||||
|
||||
var checkForNewNotificationsInterval=window.setInterval(function(){checkForNewNotifications()},window.timeBetweenPolling);
|
||||
checkForNewNotifications();
|
||||
var checkForNewQueetsInterval=window.setInterval(function(){checkForNewQueets()},window.timeBetweenPolling);
|
||||
function checkForNewQueets() {
|
||||
|
||||
|
@ -1033,7 +1049,12 @@ function checkForNewQueets() {
|
|||
// if we have hidden items, show new-queets-bar
|
||||
if($('#feed-body').find('.stream-item.hidden').length > 0) {
|
||||
var new_queets_num = $('#feed-body').find('.stream-item.hidden').length;
|
||||
document.title = window.siteTitle + ' (' + new_queets_num + ')';
|
||||
|
||||
// if this is notifications page, update site title with hidden notification count
|
||||
if(window.currentStream == 'qvitter/statuses/notifications.json') {
|
||||
document.title = window.siteTitle + ' (' + new_queets_num + ')';
|
||||
}
|
||||
|
||||
$('#new-queets-bar').parent().removeClass('hidden');
|
||||
|
||||
// text plural
|
||||
|
@ -1050,8 +1071,6 @@ function checkForNewQueets() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ·
|
||||
·
|
||||
· Show hidden queets when user clicks on new-queets-bar
|
||||
|
@ -1059,7 +1078,9 @@ function checkForNewQueets() {
|
|||
· · · · · · · · · · · · · */
|
||||
|
||||
$('body').on('click','#new-queets-bar',function(){
|
||||
document.title = window.siteTitle;
|
||||
if(window.currentStream == 'qvitter/statuses/notifications.json') {
|
||||
document.title = window.siteTitle;
|
||||
}
|
||||
$('.stream-item.hidden').css('opacity','0')
|
||||
$('.stream-item.hidden').animate({opacity:'1'}, 200);
|
||||
$('.stream-item.hidden').removeClass('hidden');
|
||||
|
@ -1819,6 +1840,7 @@ $('body').on('click','.edit-profile-button',function(){
|
|||
</div>\
|
||||
</div>\
|
||||
</div>');
|
||||
$('#edit-profile-popup .profile-card').css('top',$('#page-container .profile-card').offset().top-53 + 'px'); // position exactly over
|
||||
}
|
||||
else {
|
||||
abortEditProfile();
|
||||
|
|
Loading…
Reference in New Issue
Block a user