diff --git a/CONFIGURE b/CONFIGURE index 285ccd11b3..c5fac78730 100644 --- a/CONFIGURE +++ b/CONFIGURE @@ -859,3 +859,12 @@ performance high: if you need high performance, or if you're seeing bad performance, set this to true. It will turn off some high-intensity code from the site. + +oldschool +--------- + +enabled: enable certain old-style user settings options, like stream-only mode, + conversation trees, and nicknames in streams. Off by default, and + may not be well supported in future versions. + + diff --git a/EVENTS.txt b/EVENTS.txt index 922b79a865..8358bed0b7 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -1422,3 +1422,6 @@ StartUpgrade: when starting a site upgrade EndUpgrade: when ending a site upgrade; good place to do your own upgrades +HaveIMPlugin: is there an IM plugin loaded? +- &$haveIMPlugin: set me to true if you're loaded! + diff --git a/actions/all.php b/actions/all.php index a987ebbadb..6e6dae5d16 100644 --- a/actions/all.php +++ b/actions/all.php @@ -1,7 +1,7 @@ user, Profile::current()); + $user = common_current_user(); + + if (!empty($user) && $user->streamModeOnly()) { + $stream = new InboxNoticeStream($this->user, Profile::current()); + } else { + $stream = new ThreadingInboxNoticeStream($this->user, Profile::current()); + } $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); @@ -176,7 +182,11 @@ class AllAction extends ProfileAction $profile = $current_user->getProfile(); } - $nl = new ThreadedNoticeList($this->notice, $this, $profile); + if (!empty($current_user) && $current_user->streamModeOnly()) { + $nl = new NoticeList($this->notice, $this); + } else { + $nl = new ThreadedNoticeList($this->notice, $this, $profile); + } $cnt = $nl->show(); diff --git a/actions/conversation.php b/actions/conversation.php index 637e86e4b2..aa2539d213 100644 --- a/actions/conversation.php +++ b/actions/conversation.php @@ -123,9 +123,15 @@ class ConversationAction extends Action */ function showContent() { - $tnl = new FullThreadedNoticeList($this->notices, $this, $this->userProfile); + $user = common_current_user(); - $cnt = $tnl->show(); + if (!empty($user) && $user->conversationTree()) { + $nl = new ConversationTree($this->notices, $this); + } else { + $nl = new FullThreadedNoticeList($this->notices, $this, $this->userProfile); + } + + $cnt = $nl->show(); } function isReadOnly() @@ -162,3 +168,4 @@ class ConversationAction extends Action _('Conversation feed (Activity Streams JSON)'))); } } + diff --git a/actions/hcard.php b/actions/hcard.php deleted file mode 100644 index 6db2972b9d..0000000000 --- a/actions/hcard.php +++ /dev/null @@ -1,121 +0,0 @@ -. - * - * @category Personal - * @package StatusNet - * @author Evan Prodromou - * @copyright 2010 StatusNet, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 - * @link http://status.net/ - */ - -if (!defined('STATUSNET')) { - exit(1); -} - -/** - * User profile page - * - * @category Personal - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 - * @link http://status.net/ - */ -class HcardAction extends Action -{ - var $user; - var $profile; - - function prepare($args) - { - parent::prepare($args); - - $nickname_arg = $this->arg('nickname'); - $nickname = common_canonical_nickname($nickname_arg); - - // Permanent redirect on non-canonical nickname - - if ($nickname_arg != $nickname) { - $args = array('nickname' => $nickname); - common_redirect(common_local_url('hcard', $args), 301); - return false; - } - - $this->user = User::staticGet('nickname', $nickname); - - if (!$this->user) { - // TRANS: Client error displayed when trying to get a user hCard for a non-existing user. - $this->clientError(_('No such user.'), 404); - return false; - } - - $this->profile = $this->user->getProfile(); - - if (!$this->profile) { - // TRANS: Error message displayed when referring to a user without a profile. - $this->serverError(_('User has no profile.')); - return false; - } - - return true; - } - - function handle($args) - { - parent::handle($args); - $this->showPage(); - } - - function title() - { - return $this->profile->getBestName(); - } - - function showContent() - { - $up = new ShortUserProfile($this, $this->user, $this->profile); - $up->show(); - } - - function showHeader() - { - return; - } - - function showAside() - { - return; - } - - function showSecondaryNav() - { - return; - } -} - -class ShortUserProfile extends UserProfile -{ - function showEntityActions() - { - return; - } -} diff --git a/actions/login.php b/actions/login.php index f774a0ed80..f8a1a5c6a3 100644 --- a/actions/login.php +++ b/actions/login.php @@ -94,8 +94,8 @@ class LoginAction extends Action parent::handle($args); if (common_is_real_login()) { - // TRANS: Client error displayed when trying to log in while already logged in. - $this->clientError(_('Already logged in.')); + $user = common_current_user(); + common_redirect(common_local_url('all', array('nickname' => $user->nickname)), 307); } else if ($_SERVER['REQUEST_METHOD'] == 'POST') { $this->checkLogin(); } else { diff --git a/actions/oldschoolsettings.php b/actions/oldschoolsettings.php new file mode 100644 index 0000000000..74c6c05cda --- /dev/null +++ b/actions/oldschoolsettings.php @@ -0,0 +1,228 @@ +. + * + * @category Oldschool + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Old-school settings + * + * @category Oldschool + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class OldschoolsettingsAction extends SettingsAction +{ + /** + * Title of the page + * + * @return string Title of the page + */ + function title() + { + // TRANS: Page title for profile settings. + return _('Old school UI settings'); + } + + /** + * Instructions for use + * + * @return instructions for use + */ + function getInstructions() + { + // TRANS: Usage instructions for profile settings. + return _('If you like it "the old way", you can set that here.'); + } + + /** + * For initializing members of the class. + * + * @param array $argarray misc. arguments + * + * @return boolean true + */ + + function prepare($argarray) + { + if (!common_config('oldschool', 'enabled')) { + throw new ClientException("Old-school settings not enabled."); + } + parent::prepare($argarray); + return true; + } + + /** + * Handler method + * + * @param array $argarray is ignored since it's now passed in in prepare() + * + * @return void + */ + + function handlePost() + { + $user = common_current_user(); + + $osp = Old_school_prefs::staticGet('user_id', $user->id); + $orig = null; + + if (!empty($osp)) { + $orig = clone($osp); + } else { + $osp = new Old_school_prefs(); + $osp->user_id = $user->id; + $osp->created = common_sql_now(); + } + + $osp->stream_mode_only = $this->boolean('stream_mode_only'); + $osp->conversation_tree = $this->boolean('conversation_tree'); + $osp->stream_nicknames = $this->boolean('stream_nicknames'); + $osp->modified = common_sql_now(); + + if (!empty($orig)) { + $osp->update($orig); + } else { + $osp->insert(); + } + + // TRANS: Confirmation shown when user profile settings are saved. + $this->showForm(_('Settings saved.'), true); + + return; + } + + function showContent() + { + $user = common_current_user(); + $form = new OldSchoolForm($this, $user); + $form->show(); + } +} + +class OldSchoolForm extends Form +{ + var $user; + + function __construct($out, $user) + { + parent::__construct($out); + $this->user = $user; + } + + /** + * Visible or invisible data elements + * + * Display the form fields that make up the data of the form. + * Sub-classes should overload this to show their data. + * + * @return void + */ + + function formData() + { + $this->elementStart('fieldset'); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + $this->checkbox('stream_mode_only', _('Only stream mode (no conversations) in timelines'), + $this->user->streamModeOnly()); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('conversation_tree', _('Show conversation page as hierarchical trees'), + $this->user->conversationTree()); + $this->elementEnd('li'); + $this->elementStart('li'); + $this->checkbox('stream_nicknames', _('Show nicknames (not full names) in timelines'), + $this->user->streamNicknames()); + $this->elementEnd('li'); + $this->elementEnd('fieldset'); + $this->elementEnd('ul'); + } + + /** + * Buttons for form actions + * + * Submit and cancel buttons (or whatever) + * Sub-classes should overload this to show their own buttons. + * + * @return void + */ + + function formActions() + { + $this->submit('submit', _('Save')); + } + + /** + * ID of the form + * + * Should be unique on the page. Sub-classes should overload this + * to show their own IDs. + * + * @return int ID of the form + */ + + function id() + { + return 'form_oldschool'; + } + + /** + * Action of the form. + * + * URL to post to. Should be overloaded by subclasses to give + * somewhere to post to. + * + * @return string URL to post to + */ + + function action() + { + return common_local_url('oldschoolsettings'); + } + + /** + * Class of the form. May include space-separated list of multiple classes. + * + * @return string the form's class + */ + + function formClass() + { + return 'form_settings'; + } +} diff --git a/actions/public.php b/actions/public.php index 75217cb229..cf732fe464 100644 --- a/actions/public.php +++ b/actions/public.php @@ -88,7 +88,13 @@ class PublicAction extends Action $this->userProfile = Profile::current(); - $stream = new ThreadingPublicNoticeStream($this->userProfile); + $user = common_current_user(); + + if (!empty($user) && $user->streamModeOnly()) { + $stream = new PublicNoticeStream($this->userProfile); + } else { + $stream = new ThreadingPublicNoticeStream($this->userProfile); + } $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); @@ -213,7 +219,13 @@ class PublicAction extends Action */ function showContent() { - $nl = new ThreadedNoticeList($this->notice, $this, $this->userProfile); + $user = common_current_user(); + + if (!empty($user) && $user->streamModeOnly()) { + $nl = new NoticeList($this->notice, $this); + } else { + $nl = new ThreadedNoticeList($this->notice, $this, $this->userProfile); + } $cnt = $nl->show(); diff --git a/actions/publicpeopletagcloud.php b/actions/publicpeopletagcloud.php deleted file mode 100644 index cb65bbb163..0000000000 --- a/actions/publicpeopletagcloud.php +++ /dev/null @@ -1,182 +0,0 @@ -. - * - * @category Public - * @package StatusNet - * @author Mike Cochrane - * @author Evan Prodromou - * @copyright 2008 Mike Cochrane - * @copyright 2008-2009 StatusNet, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } - -define('TAGS_PER_PAGE', 100); - -/** - * Public tag cloud for notices - * - * @category Personal - * @package StatusNet - * @author Mike Cochrane - * @author Evan Prodromou - * @copyright 2008 Mike Cochrane - * @copyright 2008-2009 StatusNet, Inc. - * @link http://status.net/ - */ -class PublicpeopletagcloudAction extends Action -{ - function isReadOnly($args) - { - return true; - } - - function title() - { - // TRANS: Title for page with public list cloud. - return _('Public list cloud'); - } - - function showPageNotice() - { - $this->element('p', 'instructions', - // TRANS: Page notice for page with public list cloud. - // TRANS: %s is a StatusNet sitename. - sprintf(_('These are largest lists on %s'), - common_config('site', 'name'))); - } - - function showEmptyList() - { - // TRANS: Empty list message on page with public list cloud. - // TRANS: This message contains Markdown links in the form [description](link). - $message = _('No one has [listed](%%doc.tags%%) anyone yet.') . ' '; - - if (common_logged_in()) { - // TRANS: Additional empty list message on page with public list cloud for logged in users. - $message .= _('Be the first to list someone!'); - } - else { - // TRANS: Additional empty list message on page with public list cloud for anonymous users. - // TRANS: This message contains Markdown links in the form [description](link). - $message .= _('Why not [register an account](%%action.register%%) and be the first to list someone!'); - } - - $this->elementStart('div', 'guide'); - $this->raw(common_markup_to_html($message)); - $this->elementEnd('div'); - } - - function showLocalNav() - { - $nav = new PublicGroupNav($this); - $nav->show(); - } - - function handle($args) - { - parent::handle($args); - $this->showPage(); - } - - function showContent() - { - // XXX: cache this - - $tags = new Profile_tag(); - $plist = new Profile_list(); - $plist->private = false; - - $tags->joinAdd($plist); - $tags->selectAdd(); - $tags->selectAdd('profile_tag.tag'); - $tags->selectAdd('count(profile_tag.tag) as weight'); - $tags->groupBy('profile_tag.tag'); - $tags->orderBy('weight DESC'); - - $tags->limit(TAGS_PER_PAGE); - - $cnt = $tags->find(); - - if ($cnt > 0) { - $this->elementStart('div', array('id' => 'tagcloud', - 'class' => 'section')); - - $tw = array(); - $sum = 0; - while ($tags->fetch()) { - $tw[$tags->tag] = $tags->weight; - $sum += $tags->weight; - } - - ksort($tw); - - $this->elementStart('dl'); - // TRANS: DT element on on page with public list cloud. - $this->element('dt', null, _('List cloud')); - $this->elementStart('dd'); - $this->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tw as $tag => $weight) { - if ($sum) { - $weightedSum = $weight/$sum; - } else { - $weightedSum = 0.5; - } - $this->showTag($tag, $weight, $weightedSum); - } - $this->elementEnd('ul'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); - $this->elementEnd('div'); - } else { - $this->showEmptyList(); - } - } - - function showTag($tag, $weight, $relative) - { - if ($relative > 0.1) { - $rel = 'tag-cloud-7'; - } else if ($relative > 0.05) { - $rel = 'tag-cloud-6'; - } else if ($relative > 0.02) { - $rel = 'tag-cloud-5'; - } else if ($relative > 0.01) { - $rel = 'tag-cloud-4'; - } else if ($relative > 0.005) { - $rel = 'tag-cloud-3'; - } else if ($relative > 0.002) { - $rel = 'tag-cloud-2'; - } else { - $rel = 'tag-cloud-1'; - } - - $this->elementStart('li', $rel); - - // TRANS: Link title for number of listed people. %d is the number of listed people. - $title = sprintf(_m('1 person listed','%d people listed',$weight),$weight); - $this->element('a', array('href' => common_local_url('peopletag', array('tag' => $tag)), - 'title' => $title), $tag); - $this->elementEnd('li'); - } -} diff --git a/actions/showgroup.php b/actions/showgroup.php index 9d4051bd89..2449ea1db7 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -97,10 +97,15 @@ class ShowgroupAction extends GroupAction $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1; - $this->userProfile = Profile::current(); - $stream = new ThreadingGroupNoticeStream($this->group, $this->userProfile); + $user = common_current_user(); + + if (!empty($user) && $user->streamModeOnly()) { + $stream = new GroupNoticeStream($this->group, $this->userProfile); + } else { + $stream = new ThreadingGroupNoticeStream($this->group, $this->userProfile); + } $this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); @@ -140,7 +145,14 @@ class ShowgroupAction extends GroupAction */ function showGroupNotices() { - $nl = new ThreadedNoticeList($this->notice, $this, $this->userProfile); + $user = common_current_user(); + + if (!empty($user) && $user->streamModeOnly()) { + $nl = new NoticeList($this->notice, $this); + } else { + $nl = new ThreadedNoticeList($this->notice, $this, $this->userProfile); + } + $cnt = $nl->show(); $this->pagination($this->page > 1, diff --git a/actions/showprofiletag.php b/actions/showprofiletag.php index a101e4bafa..278246c894 100644 --- a/actions/showprofiletag.php +++ b/actions/showprofiletag.php @@ -350,17 +350,7 @@ class ShowprofiletagAction extends Action } } - if ($cnt > PROFILES_PER_MINILIST) { - $this->elementStart('p'); - $this->element('a', array('href' => common_local_url('profiletagsubscribers', - array('nickname' => $this->tagger->nickname, - 'profiletag' => $this->peopletag->tag)), - 'class' => 'more'), - // TRANS: Link for more "People following tag x" - // TRANS: if there are more than the mini list's maximum. - _('All subscribers')); - $this->elementEnd('p'); - } + // FIXME: link to full list Event::handle('EndShowProfileTagSubscribersMiniList', array($this)); } diff --git a/classes/Foreign_user.php b/classes/Foreign_user.php index 67d8651fa9..4a41e07f4d 100644 --- a/classes/Foreign_user.php +++ b/classes/Foreign_user.php @@ -44,20 +44,18 @@ class Foreign_user extends Managed_DataObject ); } - // XXX: This only returns a 1->1 single obj mapping. Change? Or make - // a getForeignUsers() that returns more than one? --Zach static function getForeignUser($id, $service) { + $fuser = new Foreign_user(); - $fuser->whereAdd("service = $service"); - $fuser->whereAdd("id = $id"); + + $fuser->id = $id; + $fuser->service = $service; + $fuser->limit(1); - if ($fuser->find()) { - $fuser->fetch(); - return $fuser; - } + $result = $fuser->find(true); - return null; + return empty($result) ? null : $fuser; } static function getByNickname($nickname, $service) diff --git a/classes/Old_school_prefs.php b/classes/Old_school_prefs.php new file mode 100644 index 0000000000..29e13ddc74 --- /dev/null +++ b/classes/Old_school_prefs.php @@ -0,0 +1,88 @@ +. + * + * @category UI + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Separate table for storing UI preferences + * + * @category UI + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class Old_school_prefs extends Managed_DataObject +{ + public $__table = 'old_school_prefs'; // table name + public $user_id; + public $stream_mode_only; + public $conversation_tree; + public $stream_nicknames; + public $created; + public $modified; + + public static function schemaDef() + { + return array( + 'fields' => array( + 'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user who has the preference'), + 'stream_mode_only' => array('type' => 'int', + 'size' => 'tiny', + 'default' => 1, + 'description' => 'No conversation streams'), + 'conversation_tree' => array('type' => 'int', + 'size' => 'tiny', + 'default' => 1, + 'description' => 'Hierarchical tree view for conversations'), + 'stream_nicknames' => array('type' => 'int', + 'size' => 'tiny', + 'default' => 1, + 'description' => 'Show nicknames for authors and addressees in streams'), + 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'), + 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), + ), + 'primary key' => array('user_id'), + 'foreign keys' => array( + 'old_school_prefs_user_id_fkey' => array('user', array('user_id' => 'id')), + ), + ); + } + + function staticGet($k,$v=NULL) { + return Memcached_DataObject::staticGet('Old_school_prefs',$k,$v); + } +} diff --git a/classes/Profile.php b/classes/Profile.php index f61803dcd0..f983225fd5 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -436,42 +436,55 @@ class Profile extends Managed_DataObject return new ArrayWrapper($lists); } + /** + * Get tags that other people put on this profile, in reverse-chron order + * + * @param (Profile|User) $auth_user Authorized user (used for privacy) + * @param int $offset Offset from latest + * @param int $limit Max number to get + * @param datetime $since_id max date + * @param datetime $max_id min date + * + * @return Profile_list resulting lists + */ + function getOtherTags($auth_user=null, $offset=0, $limit=null, $since_id=0, $max_id=0) { - $lists = new Profile_list(); + $list = new Profile_list(); - $tags = new Profile_tag(); - $tags->tagged = $this->id; + $qry = sprintf('select profile_list.*, unix_timestamp(profile_tag.modified) as "cursor" ' . + 'from profile_tag join profile_list '. + 'on (profile_tag.tagger = profile_list.tagger ' . + ' and profile_tag.tag = profile_list.tag) ' . + 'where profile_tag.tagged = %d ', + $this->id); - $lists->joinAdd($tags); - - #@fixme: postgres (round(date_part('epoch', my_date))) - $lists->selectAdd('unix_timestamp(profile_tag.modified) as "cursor"'); if ($auth_user instanceof User || $auth_user instanceof Profile) { - $lists->whereAdd('( ( profile_list.private = false ) ' . - 'OR ( profile_list.tagger = ' . $auth_user->id . ' AND ' . - 'profile_list.private = true ) )'); + $qry .= sprintf('AND ( ( profile_list.private = false ) ' . + 'OR ( profile_list.tagger = %d AND ' . + 'profile_list.private = true ) )', + $auth_user->id); } else { - $lists->private = false; + $qry .= 'AND profile_list.private = 0 '; } - if ($since_id>0) { - $lists->whereAdd('cursor > '.$since_id); + if ($since_id > 0) { + $qry .= sprintf('AND (cursor > %d) ', $since_id); } - if ($max_id>0) { - $lists->whereAdd('cursor <= '.$max_id); + if ($max_id > 0) { + $qry .= sprintf('AND (cursor < %d) ', $max_id); } - if($offset>=0 && !is_null($limit)) { - $lists->limit($offset, $limit); + $qry .= 'ORDER BY profile_tag.modified DESC '; + + if ($offset >= 0 && !is_null($limit)) { + $qry .= sprintf('LIMIT %d OFFSET %d ', $limit, $offset); } - $lists->orderBy('profile_tag.modified DESC'); - $lists->find(); - - return $lists; + $list->query($qry); + return $list; } function getPrivateTags($offset=0, $limit=null, $since_id=0, $max_id=0) @@ -1420,14 +1433,18 @@ class Profile extends Managed_DataObject { $ids = array(); foreach ($profiles as $profile) { - $ids[] = $profile->id; + if (!empty($profile)) { + $ids[] = $profile->id; + } } $avatars = Avatar::pivotGet('profile_id', $ids, array('width' => $width, 'height' => $width)); foreach ($profiles as $profile) { - $profile->_fillAvatar($width, $avatars[$profile->id]); + if (!empty($profile)) { // ??? + $profile->_fillAvatar($width, $avatars[$profile->id]); + } } } diff --git a/classes/Profile_list.php b/classes/Profile_list.php index c433a53fee..27001978b6 100644 --- a/classes/Profile_list.php +++ b/classes/Profile_list.php @@ -221,7 +221,10 @@ class Profile_list extends Managed_DataObject { $subs = new Profile(); - $subs->joinAdd(array('id', 'profile_tag_subscription:profile_tag_id')); + $subs->joinAdd( + array('id', 'profile_tag_subscription:profile_id') + ); + $subs->whereAdd('profile_tag_subscription.profile_tag_id = ' . $this->id); $subs->selectAdd('unix_timestamp(profile_tag_subscription.' . 'created) as "cursor"'); diff --git a/classes/Profile_tag.php b/classes/Profile_tag.php index d9b094182f..07ed160d19 100644 --- a/classes/Profile_tag.php +++ b/classes/Profile_tag.php @@ -79,20 +79,17 @@ class Profile_tag extends Managed_DataObject return $tags; } - $profile_tag = new Profile_tag(); - $profile_list->tagger = $tagger; - $profile_tag->tagged = $tagged; + $qry = 'select profile_list.* from profile_list left join '. + 'profile_tag on (profile_list.tag = profile_tag.tag and '. + 'profile_list.tagger = profile_tag.tagger) where '. + 'profile_tag.tagger = %d and profile_tag.tagged = %d '; + $qry = sprintf($qry, $tagger, $tagged); - $profile_list->selectAdd(); + if (!$include_priv) { + $qry .= ' and profile_list.private = 0'; + } - // only fetch id, tag, mainpage and - // private hoping this will be faster - $profile_list->selectAdd('profile_list.id, ' . - 'profile_list.tag, ' . - 'profile_list.mainpage, ' . - 'profile_list.private'); - $profile_list->joinAdd($profile_tag); - $profile_list->find(); + $profile_list->query($qry); Profile_list::setCache($key, $profile_list); @@ -102,23 +99,26 @@ class Profile_tag extends Managed_DataObject static function getTagsArray($tagger, $tagged, $auth_user_id=null) { $ptag = new Profile_tag(); - $ptag->tagger = $tagger; - $ptag->tagged = $tagged; - if ($tagger != $auth_user_id) { - $list = new Profile_list(); - $list->private = false; - $ptag->joinAdd($list); - $ptag->selectAdd(); - $ptag->selectAdd('profile_tag.tag'); + $qry = sprintf('select profile_tag.tag '. + 'from profile_tag join profile_list '. + ' on (profile_tag.tagger = profile_list.tagger ' . + ' and profile_tag.tag = profile_list.tag) ' . + 'where profile_tag.tagger = %d ' . + 'and profile_tag.tagged = %d ', + $tagger, $tagged); + + if ($auth_user_id != $tagger) { + $qry .= 'and profile_list.private = 0'; } $tags = array(); - $ptag->find(); + + $ptag->query($qry); + while ($ptag->fetch()) { $tags[] = $ptag->tag; } - $ptag->free(); return $tags; } diff --git a/classes/User.php b/classes/User.php index 7289a17b69..65bc0485bf 100644 --- a/classes/User.php +++ b/classes/User.php @@ -1145,4 +1145,39 @@ class User extends Managed_DataObject // TRANS: Subject for password recovery e-mail. mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address); } + + function streamModeOnly() + { + if (common_config('oldschool', 'enabled')) { + $osp = Old_school_prefs::staticGet('user_id', $this->id); + if (!empty($osp)) { + return $osp->stream_mode_only; + } + } + + return false; + } + + function conversationTree() + { + if (common_config('oldschool', 'enabled')) { + $osp = Old_school_prefs::staticGet('user_id', $this->id); + if (!empty($osp)) { + return $osp->conversation_tree; + } + } + + return false; + } + + function streamNicknames() + { + if (common_config('oldschool', 'enabled')) { + $osp = Old_school_prefs::staticGet('user_id', $this->id); + if (!empty($osp)) { + return $osp->stream_nicknames; + } + } + return false; + } } diff --git a/db/core.php b/db/core.php index c484c8c785..bf8cae3c4b 100644 --- a/db/core.php +++ b/db/core.php @@ -29,7 +29,8 @@ * double-check what we've been doing on postgres? */ -$classes = array('Profile', +$classes = array('Schema_version', + 'Profile', 'Avatar', 'Sms_carrier', 'User', @@ -85,7 +86,7 @@ $classes = array('Profile', 'Conversation', 'Local_group', 'User_urlshortener_prefs', - 'Schema_version', + 'Old_school_prefs', ); foreach ($classes as $cls) { diff --git a/doc-src/lists b/doc-src/lists index b2e93aa853..01c5d3b65f 100644 --- a/doc-src/lists +++ b/doc-src/lists @@ -56,10 +56,6 @@ private prepend a '.' to the tag in the tags editing box. To set an existing public tag as private or vice-versa, go to the tag's edit page. -The most used public tags are displayed in the -[public people tag cloud](%%action.publicpeopletagcloud%%). Their -size shows their frequency of use. - Remote people tags ------------------ diff --git a/doc-src/tags b/doc-src/tags index b2e93aa853..3e9065a100 100644 --- a/doc-src/tags +++ b/doc-src/tags @@ -17,10 +17,6 @@ latin characters are not supported, and non-roman scripts are right out. The HTML for the notice will link to a stream of all the other notices with that tag. This can be a great way to keep track of a conversation. -The most popular current tags on the site can be found in the [public -tag cloud](%%action.publictagcloud%%). Their size shows their -popularity and recency. - Tagging yourself ---------------- diff --git a/install.php b/install.php index 190941c5ab..f44999285a 100644 --- a/install.php +++ b/install.php @@ -360,7 +360,7 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - + diff --git a/js/util.js b/js/util.js index 87a95c5313..c22802651a 100644 --- a/js/util.js +++ b/js/util.js @@ -638,13 +638,23 @@ var SN = { // StatusNet // Find the notice we're replying to... var id = $($('.notice_id', notice)[0]).text(); var parentNotice = notice; + var stripForm = true; // strip a couple things out of reply forms that are inline // Find the threaded replies view we'll be adding to... var list = notice.closest('.notices'); - if (list.hasClass('threaded-replies')) { + if (list.closest('.old-school').length) { + // We're replying to an old-school conversation thread; + // use the old-style ping into the top form. + SN.U.switchInputFormTab("status") + replyForm = $('#input_form_status').find('form'); + stripForm = false; + } else if (list.hasClass('threaded-replies')) { // We're replying to a reply; use reply form on the end of this list. // We'll add our form at the end of this; grab the root notice. parentNotice = list.closest('.notice'); + + // See if the form's already open... + var replyForm = $('.notice-reply-form', list); } else { // We're replying to a parent notice; pull its threaded list // and we'll add on the end of it. Will add if needed. @@ -658,18 +668,21 @@ var SN = { // StatusNet SN.U.NoticeInlineReplyPlaceholder(notice); } } - } - // See if the form's already open... - var replyForm = $('.notice-reply-form', list); + // See if the form's already open... + var replyForm = $('.notice-reply-form', list); + } var nextStep = function() { // Override...? replyForm.find('input[name=inreplyto]').val(id); - replyForm.find('#notice_to').attr('disabled', 'disabled').hide(); - replyForm.find('#notice_private').attr('disabled', 'disabled').hide(); - replyForm.find('label[for=notice_to]').hide(); - replyForm.find('label[for=notice_private]').hide(); + if (stripForm) { + // Don't do this for old-school reply form, as they don't come back! + replyForm.find('#notice_to').attr('disabled', 'disabled').hide(); + replyForm.find('#notice_private').attr('disabled', 'disabled').hide(); + replyForm.find('label[for=notice_to]').hide(); + replyForm.find('label[for=notice_private]').hide(); + } // Set focus... var text = replyForm.find('textarea'); diff --git a/js/util.min.js b/js/util.min.js index 3f370b45ef..78e0c89841 100644 --- a/js/util.min.js +++ b/js/util.min.js @@ -1 +1 @@ -var SN={C:{I:{CounterBlackout:false,MaxLength:140,PatternUsername:/^[0-9a-zA-Z\-_.]*$/,HTTP20x30x:[200,201,202,203,204,205,206,300,301,302,303,304,305,306,307],NoticeFormMaster:null},S:{Disabled:"disabled",Warning:"warning",Error:"error",Success:"success",Processing:"processing",CommandResult:"command_result",FormNotice:"form_notice",NoticeDataGeo:"notice_data-geo",NoticeDataGeoCookie:"NoticeDataGeo",NoticeDataGeoSelected:"notice_data-geo_selected",StatusNetInstance:"StatusNetInstance"}},messages:{},msg:function(a){if(typeof SN.messages[a]=="undefined"){return"["+a+"]"}else{return SN.messages[a]}},U:{FormNoticeEnhancements:function(b){if(jQuery.data(b[0],"ElementData")===undefined){MaxLength=b.find(".count").text();if(typeof(MaxLength)=="undefined"){MaxLength=SN.C.I.MaxLength}jQuery.data(b[0],"ElementData",{MaxLength:MaxLength});SN.U.Counter(b);NDT=b.find(".notice_data-text:first");NDT.bind("keyup",function(c){SN.U.Counter(b)});var a=function(c){window.setTimeout(function(){SN.U.Counter(b)},50)};NDT.bind("cut",a).bind("paste",a)}else{b.find(".count").text(jQuery.data(b[0],"ElementData").MaxLength)}},Counter:function(d){SN.C.I.FormNoticeCurrent=d;var b=jQuery.data(d[0],"ElementData").MaxLength;if(b<=0){return}var c=b-SN.U.CharacterCount(d);var a=d.find(".count");if(c.toString()!=a.text()){if(!SN.C.I.CounterBlackout||c===0){if(a.text()!=String(c)){a.text(c)}if(c<0){d.addClass(SN.C.S.Warning)}else{d.removeClass(SN.C.S.Warning)}if(!SN.C.I.CounterBlackout){SN.C.I.CounterBlackout=true;SN.C.I.FormNoticeCurrent=d;window.setTimeout("SN.U.ClearCounterBlackout(SN.C.I.FormNoticeCurrent);",500)}}}},CharacterCount:function(a){return a.find(".notice_data-text:first").val().length},ClearCounterBlackout:function(a){SN.C.I.CounterBlackout=false;SN.U.Counter(a)},RewriteAjaxAction:function(a){if(document.location.protocol=="https:"&&a.substr(0,5)=="http:"){return a.replace(/^http:\/\/[^:\/]+/,"https://"+document.location.host)}else{return a}},FormXHR:function(a,b){$.ajax({type:"POST",dataType:"xml",url:SN.U.RewriteAjaxAction(a.attr("action")),data:a.serialize()+"&ajax=1",beforeSend:function(c){a.addClass(SN.C.S.Processing).find(".submit").addClass(SN.C.S.Disabled).attr(SN.C.S.Disabled,SN.C.S.Disabled)},error:function(e,f,d){var c=null;if(e.responseXML){c=$("#error",e.responseXML).text()}alert(c||d||f);a.removeClass(SN.C.S.Processing).find(".submit").removeClass(SN.C.S.Disabled).removeAttr(SN.C.S.Disabled)},success:function(c,d){if(typeof($("form",c)[0])!="undefined"){form_new=document._importNode($("form",c)[0],true);a.replaceWith(form_new);if(b){b()}}else{if(typeof($("p",c)[0])!="undefined"){a.replaceWith(document._importNode($("p",c)[0],true));if(b){b()}}else{alert("Unknown error.")}}}})},FormNoticeXHR:function(b){SN.C.I.NoticeDataGeo={};b.append('');b.attr("action",SN.U.RewriteAjaxAction(b.attr("action")));var c=function(d,e){b.append($('

').addClass(d).text(e))};var a=function(){b.find(".form_response").remove()};b.ajaxForm({dataType:"xml",timeout:"60000",beforeSend:function(d){if(b.find(".notice_data-text:first").val()==""){b.addClass(SN.C.S.Warning);return false}b.addClass(SN.C.S.Processing).find(".submit").addClass(SN.C.S.Disabled).attr(SN.C.S.Disabled,SN.C.S.Disabled);SN.U.normalizeGeoData(b);return true},error:function(f,g,e){b.removeClass(SN.C.S.Processing).find(".submit").removeClass(SN.C.S.Disabled).removeAttr(SN.C.S.Disabled,SN.C.S.Disabled);a();if(g=="timeout"){c("error","Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.")}else{var d=SN.U.GetResponseXML(f);if($("."+SN.C.S.Error,d).length>0){b.append(document._importNode($("."+SN.C.S.Error,d)[0],true))}else{if(parseInt(f.status)===0||jQuery.inArray(parseInt(f.status),SN.C.I.HTTP20x30x)>=0){b.resetForm().find(".attach-status").remove();SN.U.FormNoticeEnhancements(b)}else{c("error","(Sorry! We had trouble sending your notice ("+f.status+" "+f.statusText+"). Please report the problem to the site administrator if this happens again.")}}}},success:function(j,f){a();var p=$("#"+SN.C.S.Error,j);if(p.length>0){c("error",p.text())}else{if($("body")[0].id=="bookmarklet"){self.close()}var d=$("#"+SN.C.S.CommandResult,j);if(d.length>0){c("success",d.text())}else{var o=document._importNode($("li",j)[0],true);var k=$("#notices_primary .notices:first");var m=b.closest("li.notice-reply");if(m.length>0){var l=b.closest(".threaded-replies");var n=l.find(".notice-reply-placeholder");m.remove();var e=$(o).attr("id");if($("#"+e).length==0){$(o).insertBefore(n)}else{}n.show()}else{if(k.length>0&&SN.U.belongsOnTimeline(o)){if($("#"+o.id).length===0){var h=b.find("[name=inreplyto]").val();var g="#notices_primary #notice-"+h;if($("body")[0].id=="conversation"){if(h.length>0&&$(g+" .notices").length<1){$(g).append('
    ')}$($(g+" .notices")[0]).append(o)}else{k.prepend(o)}$("#"+o.id).css({display:"none"}).fadeIn(2500);SN.U.NoticeWithAttachment($("#"+o.id));SN.U.switchInputFormTab("placeholder")}}else{c("success",$("title",j).text())}}}b.resetForm();b.find("[name=inreplyto]").val("");b.find(".attach-status").remove();SN.U.FormNoticeEnhancements(b)}},complete:function(d,e){b.removeClass(SN.C.S.Processing).find(".submit").removeAttr(SN.C.S.Disabled).removeClass(SN.C.S.Disabled);b.find("[name=lat]").val(SN.C.I.NoticeDataGeo.NLat);b.find("[name=lon]").val(SN.C.I.NoticeDataGeo.NLon);b.find("[name=location_ns]").val(SN.C.I.NoticeDataGeo.NLNS);b.find("[name=location_id]").val(SN.C.I.NoticeDataGeo.NLID);b.find("[name=notice_data-geo]").attr("checked",SN.C.I.NoticeDataGeo.NDG)}})},FormProfileSearchXHR:function(a){$.ajax({type:"POST",dataType:"xml",url:a.attr("action"),data:a.serialize()+"&ajax=1",beforeSend:function(b){a.addClass(SN.C.S.Processing).find(".submit").addClass(SN.C.S.Disabled).attr(SN.C.S.Disabled,SN.C.S.Disabled)},error:function(c,d,b){alert(b||d)},success:function(d,f){var b=$("#profile_search_results");if(typeof($("ul",d)[0])!="undefined"){var c=document._importNode($("ul",d)[0],true);b.replaceWith(c)}else{var e=$("
  • ").append(document._importNode($("p",d)[0],true));b.html(e)}a.removeClass(SN.C.S.Processing).find(".submit").removeClass(SN.C.S.Disabled).attr(SN.C.S.Disabled,false)}})},FormPeopletagsXHR:function(a){$.ajax({type:"POST",dataType:"xml",url:a.attr("action"),data:a.serialize()+"&ajax=1",beforeSend:function(b){a.find(".submit").addClass(SN.C.S.Processing).addClass(SN.C.S.Disabled).attr(SN.C.S.Disabled,SN.C.S.Disabled)},error:function(c,d,b){alert(b||d)},success:function(d,e){var c=a.parents(".entity_tags");if(typeof($(".entity_tags",d)[0])!="undefined"){var b=document._importNode($(".entity_tags",d)[0],true);$(b).find(".editable").append($('').closest(".notice-options").addClass("opaque");a.find("button.close").click(function(){$(this).remove();a.removeClass("dialogbox").closest(".notice-options").removeClass("opaque");a.find(".submit_dialogbox").remove();a.find(".submit").show();return false})},NoticeAttachments:function(){$(".notice a.attachment").each(function(){SN.U.NoticeWithAttachment($(this).closest(".notice"))})},NoticeWithAttachment:function(b){if(b.find(".attachment").length===0){return}var a=b.find(".attachment.more");if(a.length>0){$(a[0]).click(function(){var c=$(this);c.addClass(SN.C.S.Processing);$.get(c.attr("href")+"/ajax",null,function(d){c.parent(".entry-content").html($(d).find("#attachment_view .entry-content").html())});return false}).attr("title",SN.msg("showmore_tooltip"))}},NoticeDataAttach:function(b){var a=b.find("input[type=file]");a.change(function(f){b.find(".attach-status").remove();var d=$(this).val();if(!d){return false}var c=$('
    ');c.find("code").text(d);c.find("button").click(function(){c.remove();a.val("");return false});b.append(c);if(typeof this.files=="object"){for(var e=0;eg){f=false}if(f){h(c,function(k){var j=$("").attr("title",e).attr("alt",e).attr("src",k).attr("style","height: 120px");d.find(".attach-status").append(j)})}else{var b=$("
    ").text(e);d.find(".attach-status").append(b)}},NoticeLocationAttach:function(a){var e=a.find("[name=lat]");var l=a.find("[name=lon]");var g=a.find("[name=location_ns]").val();var m=a.find("[name=location_id]").val();var b="";var d=a.find("[name=notice_data-geo]");var c=a.find("[name=notice_data-geo]");var k=a.find("label.notice_data-geo");function f(o){k.attr("title",jQuery.trim(k.text())).removeClass("checked");a.find("[name=lat]").val("");a.find("[name=lon]").val("");a.find("[name=location_ns]").val("");a.find("[name=location_id]").val("");a.find("[name=notice_data-geo]").attr("checked",false);$.cookie(SN.C.S.NoticeDataGeoCookie,"disabled",{path:"/"});if(o){a.find(".geo_status_wrapper").removeClass("success").addClass("error");a.find(".geo_status_wrapper .geo_status").text(o)}else{a.find(".geo_status_wrapper").remove()}}function n(o,p){SN.U.NoticeGeoStatus(a,"Looking up place name...");$.getJSON(o,p,function(q){var r,s;if(typeof(q.location_ns)!="undefined"){a.find("[name=location_ns]").val(q.location_ns);r=q.location_ns}if(typeof(q.location_id)!="undefined"){a.find("[name=location_id]").val(q.location_id);s=q.location_id}if(typeof(q.name)=="undefined"){NLN_text=p.lat+";"+p.lon}else{NLN_text=q.name}SN.U.NoticeGeoStatus(a,NLN_text,p.lat,p.lon,q.url);k.attr("title",NoticeDataGeo_text.ShareDisable+" ("+NLN_text+")");a.find("[name=lat]").val(p.lat);a.find("[name=lon]").val(p.lon);a.find("[name=location_ns]").val(r);a.find("[name=location_id]").val(s);a.find("[name=notice_data-geo]").attr("checked",true);var t={NLat:p.lat,NLon:p.lon,NLNS:r,NLID:s,NLN:NLN_text,NLNU:q.url,NDG:true};$.cookie(SN.C.S.NoticeDataGeoCookie,JSON.stringify(t),{path:"/"})})}if(c.length>0){if($.cookie(SN.C.S.NoticeDataGeoCookie)=="disabled"){c.attr("checked",false)}else{c.attr("checked",true)}var h=a.find(".notice_data-geo_wrap");var j=h.attr("data-api");k.attr("title",k.text());c.change(function(){if(c.attr("checked")===true||$.cookie(SN.C.S.NoticeDataGeoCookie)===null){k.attr("title",NoticeDataGeo_text.ShareDisable).addClass("checked");if($.cookie(SN.C.S.NoticeDataGeoCookie)===null||$.cookie(SN.C.S.NoticeDataGeoCookie)=="disabled"){if(navigator.geolocation){SN.U.NoticeGeoStatus(a,"Requesting location from browser...");navigator.geolocation.getCurrentPosition(function(q){a.find("[name=lat]").val(q.coords.latitude);a.find("[name=lon]").val(q.coords.longitude);var r={lat:q.coords.latitude,lon:q.coords.longitude,token:$("#token").val()};n(j,r)},function(q){switch(q.code){case q.PERMISSION_DENIED:f("Location permission denied.");break;case q.TIMEOUT:f("Location lookup timeout.");break}},{timeout:10000})}else{if(e.length>0&&l.length>0){var o={lat:e,lon:l,token:$("#token").val()};n(j,o)}else{f();c.remove();k.remove()}}}else{var p=JSON.parse($.cookie(SN.C.S.NoticeDataGeoCookie));a.find("[name=lat]").val(p.NLat);a.find("[name=lon]").val(p.NLon);a.find("[name=location_ns]").val(p.NLNS);a.find("[name=location_id]").val(p.NLID);a.find("[name=notice_data-geo]").attr("checked",p.NDG);SN.U.NoticeGeoStatus(a,p.NLN,p.NLat,p.NLon,p.NLNU);k.attr("title",NoticeDataGeo_text.ShareDisable+" ("+p.NLN+")").addClass("checked")}}else{f()}}).change()}},NoticeGeoStatus:function(e,a,f,g,c){var h=e.find(".geo_status_wrapper");if(h.length==0){h=$('
    ');h.find("button.close").click(function(){e.find("[name=notice_data-geo]").removeAttr("checked").change();return false});e.append(h)}var b;if(c){b=$("").attr("href",c)}else{b=$("")}b.text(a);if(f||g){var d=f+";"+g;b.attr("title",d);if(!a){b.text(d)}}h.find(".geo_status").empty().append(b)},NewDirectMessage:function(){NDM=$(".entity_send-a-message a");NDM.attr({href:NDM.attr("href")+"&ajax=1"});NDM.bind("click",function(){var a=$(".entity_send-a-message form");if(a.length===0){$(this).addClass(SN.C.S.Processing);$.get(NDM.attr("href"),null,function(b){$(".entity_send-a-message").append(document._importNode($("form",b)[0],true));a=$(".entity_send-a-message .form_notice");SN.U.FormNoticeXHR(a);SN.U.FormNoticeEnhancements(a);a.append('');$(".entity_send-a-message button").click(function(){a.hide();return false});NDM.removeClass(SN.C.S.Processing)})}else{a.show();$(".entity_send-a-message textarea").focus()}return false})},GetFullYear:function(c,d,a){var b=new Date();b.setFullYear(c,d,a);return b},StatusNetInstance:{Set:function(b){var a=SN.U.StatusNetInstance.Get();if(a!==null){b=$.extend(a,b)}$.cookie(SN.C.S.StatusNetInstance,JSON.stringify(b),{path:"/",expires:SN.U.GetFullYear(2029,0,1)})},Get:function(){var a=$.cookie(SN.C.S.StatusNetInstance);if(a!==null){return JSON.parse(a)}return null},Delete:function(){$.cookie(SN.C.S.StatusNetInstance,null)}},belongsOnTimeline:function(b){var a=$("body").attr("id");if(a=="public"){return true}var c=$("#nav_profile a").attr("href");if(c){var d=$(b).find(".vcard.author a.url").attr("href");if(d==c){if(a=="all"||a=="showstream"){return true}}}return false},switchInputFormTab:function(a){$(".input_form_nav_tab.current").removeClass("current");if(a=="placeholder"){$("#input_form_nav_status").addClass("current")}else{$("#input_form_nav_"+a).addClass("current")}var b=$(".input_form.current.nonav");if(b.length>0){return}$(".input_form.current").removeClass("current");$("#input_form_"+a).addClass("current").find(".ajax-notice").each(function(){var c=$(this);SN.Init.NoticeFormSetup(c)}).find(".notice_data-text").focus()},showMoreMenuItems:function(c){$("#"+c+" .more_link").remove();var b="#"+c+" .extended_menu";var a=$(b);a.removeClass("extended_menu");return void (0)}},Init:{NoticeForm:function(){if($("body.user_in").length>0){$("#input_form_placeholder input.placeholder").focus(function(){SN.U.switchInputFormTab("status")});$("body").bind("click",function(g){var d=$("#content .input_forms div.current");if(d.length>0){if($("#content .input_forms").has(g.target).length==0){var a=d.find('textarea, input[type=text], input[type=""]');var c=false;a.each(function(){c=c||$(this).val()});if(!c){SN.U.switchInputFormTab("placeholder")}}}var b=$("li.notice-reply");if(b.length>0){var f=$(g.target);b.each(function(){var k=$(this);if(k.has(g.target).length==0){var h=k.find(".notice_data-text:first");var j=$.trim(h.val());if(j==""||j==h.data("initialText")){var e=k.closest("li.notice");k.remove();e.find("li.notice-reply-placeholder").show()}}})}});$(".input_forms fieldset fieldset label").inFieldLabels({fadeOpacity:0})}},NoticeFormSetup:function(a){if(!a.data("NoticeFormSetup")){SN.U.NoticeLocationAttach(a);SN.U.FormNoticeXHR(a);SN.U.FormNoticeEnhancements(a);SN.U.NoticeDataAttach(a);a.data("NoticeFormSetup",true)}},Notices:function(){if($("body.user_in").length>0){var a=$(".form_notice:first");if(a.length>0){SN.C.I.NoticeFormMaster=document._importNode(a[0],true)}SN.U.NoticeRepeat();SN.U.NoticeReply();SN.U.NoticeInlineReplySetup()}SN.U.NoticeAttachments()},EntityActions:function(){if($("body.user_in").length>0){$(".form_user_subscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_unsubscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_group_join").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_group_leave").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_nudge").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_peopletag_subscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_peopletag_unsubscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_add_peopletag").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_remove_peopletag").live("click",function(){SN.U.FormXHR($(this));return false});SN.U.NewDirectMessage()}},ProfileSearch:function(){if($("body.user_in").length>0){$(".form_peopletag_edit_user_search input.submit").live("click",function(){SN.U.FormProfileSearchXHR($(this).parents("form"));return false})}},Login:function(){if(SN.U.StatusNetInstance.Get()!==null){var a=SN.U.StatusNetInstance.Get().Nickname;if(a!==null){$("#form_login #nickname").val(a)}}$("#form_login").bind("submit",function(){SN.U.StatusNetInstance.Set({Nickname:$("#form_login #nickname").val()});return true})},PeopletagAutocomplete:function(b){var a=function(d){return d.split(/\s+/)};var c=function(d){return a(d).pop()};b.live("keydown",function(d){if(d.keyCode===$.ui.keyCode.TAB&&$(this).data("autocomplete").menu.active){d.preventDefault()}}).autocomplete({minLength:0,source:function(e,d){d($.ui.autocomplete.filter(SN.C.PtagACData,c(e.term)))},focus:function(){return false},select:function(e,f){var d=a(this.value);d.pop();d.push(f.item.value);d.push("");this.value=d.join(" ");return false}}).data("autocomplete")._renderItem=function(e,f){var d=''+f.tag+' '+f.mode+''+f.freq+"";return $("
  • ").addClass("mode-"+f.mode).addClass("ptag-ac-line").data("item.autocomplete",f).append(d).appendTo(e)}},PeopleTags:function(){$(".user_profile_tags .editable").append($('').closest(".notice-options").addClass("opaque");a.find("button.close").click(function(){$(this).remove();a.removeClass("dialogbox").closest(".notice-options").removeClass("opaque");a.find(".submit_dialogbox").remove();a.find(".submit").show();return false})},NoticeAttachments:function(){$(".notice a.attachment").each(function(){SN.U.NoticeWithAttachment($(this).closest(".notice"))})},NoticeWithAttachment:function(b){if(b.find(".attachment").length===0){return}var a=b.find(".attachment.more");if(a.length>0){$(a[0]).click(function(){var c=$(this);c.addClass(SN.C.S.Processing);$.get(c.attr("href")+"/ajax",null,function(d){c.parent(".entry-content").html($(d).find("#attachment_view .entry-content").html())});return false}).attr("title",SN.msg("showmore_tooltip"))}},NoticeDataAttach:function(b){var a=b.find("input[type=file]");a.change(function(f){b.find(".attach-status").remove();var d=$(this).val();if(!d){return false}var c=$('
    ');c.find("code").text(d);c.find("button").click(function(){c.remove();a.val("");return false});b.append(c);if(typeof this.files=="object"){for(var e=0;eg){f=false}if(f){h(c,function(k){var j=$("").attr("title",e).attr("alt",e).attr("src",k).attr("style","height: 120px");d.find(".attach-status").append(j)})}else{var b=$("
    ").text(e);d.find(".attach-status").append(b)}},NoticeLocationAttach:function(a){var e=a.find("[name=lat]");var l=a.find("[name=lon]");var g=a.find("[name=location_ns]").val();var m=a.find("[name=location_id]").val();var b="";var d=a.find("[name=notice_data-geo]");var c=a.find("[name=notice_data-geo]");var k=a.find("label.notice_data-geo");function f(o){k.attr("title",jQuery.trim(k.text())).removeClass("checked");a.find("[name=lat]").val("");a.find("[name=lon]").val("");a.find("[name=location_ns]").val("");a.find("[name=location_id]").val("");a.find("[name=notice_data-geo]").attr("checked",false);$.cookie(SN.C.S.NoticeDataGeoCookie,"disabled",{path:"/"});if(o){a.find(".geo_status_wrapper").removeClass("success").addClass("error");a.find(".geo_status_wrapper .geo_status").text(o)}else{a.find(".geo_status_wrapper").remove()}}function n(o,p){SN.U.NoticeGeoStatus(a,"Looking up place name...");$.getJSON(o,p,function(q){var r,s;if(typeof(q.location_ns)!="undefined"){a.find("[name=location_ns]").val(q.location_ns);r=q.location_ns}if(typeof(q.location_id)!="undefined"){a.find("[name=location_id]").val(q.location_id);s=q.location_id}if(typeof(q.name)=="undefined"){NLN_text=p.lat+";"+p.lon}else{NLN_text=q.name}SN.U.NoticeGeoStatus(a,NLN_text,p.lat,p.lon,q.url);k.attr("title",NoticeDataGeo_text.ShareDisable+" ("+NLN_text+")");a.find("[name=lat]").val(p.lat);a.find("[name=lon]").val(p.lon);a.find("[name=location_ns]").val(r);a.find("[name=location_id]").val(s);a.find("[name=notice_data-geo]").attr("checked",true);var t={NLat:p.lat,NLon:p.lon,NLNS:r,NLID:s,NLN:NLN_text,NLNU:q.url,NDG:true};$.cookie(SN.C.S.NoticeDataGeoCookie,JSON.stringify(t),{path:"/"})})}if(c.length>0){if($.cookie(SN.C.S.NoticeDataGeoCookie)=="disabled"){c.attr("checked",false)}else{c.attr("checked",true)}var h=a.find(".notice_data-geo_wrap");var j=h.attr("data-api");k.attr("title",k.text());c.change(function(){if(c.attr("checked")===true||$.cookie(SN.C.S.NoticeDataGeoCookie)===null){k.attr("title",NoticeDataGeo_text.ShareDisable).addClass("checked");if($.cookie(SN.C.S.NoticeDataGeoCookie)===null||$.cookie(SN.C.S.NoticeDataGeoCookie)=="disabled"){if(navigator.geolocation){SN.U.NoticeGeoStatus(a,"Requesting location from browser...");navigator.geolocation.getCurrentPosition(function(q){a.find("[name=lat]").val(q.coords.latitude);a.find("[name=lon]").val(q.coords.longitude);var r={lat:q.coords.latitude,lon:q.coords.longitude,token:$("#token").val()};n(j,r)},function(q){switch(q.code){case q.PERMISSION_DENIED:f("Location permission denied.");break;case q.TIMEOUT:f("Location lookup timeout.");break}},{timeout:10000})}else{if(e.length>0&&l.length>0){var o={lat:e,lon:l,token:$("#token").val()};n(j,o)}else{f();c.remove();k.remove()}}}else{var p=JSON.parse($.cookie(SN.C.S.NoticeDataGeoCookie));a.find("[name=lat]").val(p.NLat);a.find("[name=lon]").val(p.NLon);a.find("[name=location_ns]").val(p.NLNS);a.find("[name=location_id]").val(p.NLID);a.find("[name=notice_data-geo]").attr("checked",p.NDG);SN.U.NoticeGeoStatus(a,p.NLN,p.NLat,p.NLon,p.NLNU);k.attr("title",NoticeDataGeo_text.ShareDisable+" ("+p.NLN+")").addClass("checked")}}else{f()}}).change()}},NoticeGeoStatus:function(e,a,f,g,c){var h=e.find(".geo_status_wrapper");if(h.length==0){h=$('
    ');h.find("button.close").click(function(){e.find("[name=notice_data-geo]").removeAttr("checked").change();return false});e.append(h)}var b;if(c){b=$("").attr("href",c)}else{b=$("")}b.text(a);if(f||g){var d=f+";"+g;b.attr("title",d);if(!a){b.text(d)}}h.find(".geo_status").empty().append(b)},NewDirectMessage:function(){NDM=$(".entity_send-a-message a");NDM.attr({href:NDM.attr("href")+"&ajax=1"});NDM.bind("click",function(){var a=$(".entity_send-a-message form");if(a.length===0){$(this).addClass(SN.C.S.Processing);$.get(NDM.attr("href"),null,function(b){$(".entity_send-a-message").append(document._importNode($("form",b)[0],true));a=$(".entity_send-a-message .form_notice");SN.U.FormNoticeXHR(a);SN.U.FormNoticeEnhancements(a);a.append('');$(".entity_send-a-message button").click(function(){a.hide();return false});NDM.removeClass(SN.C.S.Processing)})}else{a.show();$(".entity_send-a-message textarea").focus()}return false})},GetFullYear:function(c,d,a){var b=new Date();b.setFullYear(c,d,a);return b},StatusNetInstance:{Set:function(b){var a=SN.U.StatusNetInstance.Get();if(a!==null){b=$.extend(a,b)}$.cookie(SN.C.S.StatusNetInstance,JSON.stringify(b),{path:"/",expires:SN.U.GetFullYear(2029,0,1)})},Get:function(){var a=$.cookie(SN.C.S.StatusNetInstance);if(a!==null){return JSON.parse(a)}return null},Delete:function(){$.cookie(SN.C.S.StatusNetInstance,null)}},belongsOnTimeline:function(b){var a=$("body").attr("id");if(a=="public"){return true}var c=$("#nav_profile a").attr("href");if(c){var d=$(b).find(".vcard.author a.url").attr("href");if(d==c){if(a=="all"||a=="showstream"){return true}}}return false},switchInputFormTab:function(a){$(".input_form_nav_tab.current").removeClass("current");if(a=="placeholder"){$("#input_form_nav_status").addClass("current")}else{$("#input_form_nav_"+a).addClass("current")}var b=$(".input_form.current.nonav");if(b.length>0){return}$(".input_form.current").removeClass("current");$("#input_form_"+a).addClass("current").find(".ajax-notice").each(function(){var c=$(this);SN.Init.NoticeFormSetup(c)}).find(".notice_data-text").focus()},showMoreMenuItems:function(c){$("#"+c+" .more_link").remove();var b="#"+c+" .extended_menu";var a=$(b);a.removeClass("extended_menu");return void (0)}},Init:{NoticeForm:function(){if($("body.user_in").length>0){$("#input_form_placeholder input.placeholder").focus(function(){SN.U.switchInputFormTab("status")});$("body").bind("click",function(g){var d=$("#content .input_forms div.current");if(d.length>0){if($("#content .input_forms").has(g.target).length==0){var a=d.find('textarea, input[type=text], input[type=""]');var c=false;a.each(function(){c=c||$(this).val()});if(!c){SN.U.switchInputFormTab("placeholder")}}}var b=$("li.notice-reply");if(b.length>0){var f=$(g.target);b.each(function(){var k=$(this);if(k.has(g.target).length==0){var h=k.find(".notice_data-text:first");var j=$.trim(h.val());if(j==""||j==h.data("initialText")){var e=k.closest("li.notice");k.remove();e.find("li.notice-reply-placeholder").show()}}})}});$(".input_forms fieldset fieldset label").inFieldLabels({fadeOpacity:0})}},NoticeFormSetup:function(a){if(!a.data("NoticeFormSetup")){SN.U.NoticeLocationAttach(a);SN.U.FormNoticeXHR(a);SN.U.FormNoticeEnhancements(a);SN.U.NoticeDataAttach(a);a.data("NoticeFormSetup",true)}},Notices:function(){if($("body.user_in").length>0){var a=$(".form_notice:first");if(a.length>0){SN.C.I.NoticeFormMaster=document._importNode(a[0],true)}SN.U.NoticeRepeat();SN.U.NoticeReply();SN.U.NoticeInlineReplySetup()}SN.U.NoticeAttachments()},EntityActions:function(){if($("body.user_in").length>0){$(".form_user_subscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_unsubscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_group_join").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_group_leave").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_nudge").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_peopletag_subscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_peopletag_unsubscribe").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_add_peopletag").live("click",function(){SN.U.FormXHR($(this));return false});$(".form_user_remove_peopletag").live("click",function(){SN.U.FormXHR($(this));return false});SN.U.NewDirectMessage()}},ProfileSearch:function(){if($("body.user_in").length>0){$(".form_peopletag_edit_user_search input.submit").live("click",function(){SN.U.FormProfileSearchXHR($(this).parents("form"));return false})}},Login:function(){if(SN.U.StatusNetInstance.Get()!==null){var a=SN.U.StatusNetInstance.Get().Nickname;if(a!==null){$("#form_login #nickname").val(a)}}$("#form_login").bind("submit",function(){SN.U.StatusNetInstance.Set({Nickname:$("#form_login #nickname").val()});return true})},PeopletagAutocomplete:function(b){var a=function(d){return d.split(/\s+/)};var c=function(d){return a(d).pop()};b.live("keydown",function(d){if(d.keyCode===$.ui.keyCode.TAB&&$(this).data("autocomplete").menu.active){d.preventDefault()}}).autocomplete({minLength:0,source:function(e,d){d($.ui.autocomplete.filter(SN.C.PtagACData,c(e.term)))},focus:function(){return false},select:function(e,f){var d=a(this.value);d.pop();d.push(f.item.value);d.push("");this.value=d.join(" ");return false}}).data("autocomplete")._renderItem=function(e,f){var d=''+f.tag+' '+f.mode+''+f.freq+"";return $("
  • ").addClass("mode-"+f.mode).addClass("ptag-ac-line").data("item.autocomplete",f).append(d).appendTo(e)}},PeopleTags:function(){$(".user_profile_tags .editable").append($('