2013-08-19 22:30:57 +09:00
/ * · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
· ·
· ·
· 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 . ·
· ·
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · * /
/ * ·
·
2015-02-26 05:16:24 +09:00
· Show favs and requeets in queet element
2013-08-19 22:30:57 +09:00
·
· @ param q : queet jQuery object
2015-02-26 05:16:24 +09:00
· @ param data : object with users that has faved and requeeted
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · * /
2015-02-26 05:16:24 +09:00
function showFavsAndRequeetsInQueet ( q , data ) {
2013-08-19 22:30:57 +09:00
2015-02-26 05:16:24 +09:00
// remove any existing stats container and add a new empty one
if ( q . children ( '.queet' ) . find ( 'ul.stats' ) . length > 0 ) {
q . children ( '.queet' ) . find ( 'ul.stats' ) . remove ( ) ;
2013-08-19 22:30:57 +09:00
}
2015-02-26 05:16:24 +09:00
q . children ( '.queet' ) . find ( '.queet-stats-container' ) . prepend ( '<ul class="stats"><li class="avatar-row"></li></ul>' ) ;
2013-08-19 22:30:57 +09:00
2015-02-26 05:16:24 +09:00
// add favs
if ( data . favs . length > 0 ) {
if ( data . favs . length == 1 ) {
var favLabel = window . sL . favoriteNoun ;
}
else if ( data . favs . length > 1 ) {
var favLabel = window . sL . favoritesNoun ;
}
if ( q . children ( '.queet' ) . find ( '.fav-count' ) . length > 0 ) {
q . children ( '.queet' ) . find ( '.fav-count' ) . children ( 'strong' ) . html ( data . favs . length ) ;
}
else {
q . children ( '.queet' ) . find ( 'li.avatar-row' ) . before ( '<li class="fav-count"><a>' + favLabel + ' </a><strong>' + data . favs . length + '</strong></li>' ) ;
}
2013-08-19 22:30:57 +09:00
}
2015-02-26 05:16:24 +09:00
// add repeats
if ( data . repeats . length > 0 ) {
if ( data . repeats . length == 1 ) {
var repeatsLabel = window . sL . requeetNoun ;
}
else if ( data . repeats . length > 1 ) {
var repeatsLabel = window . sL . requeetsNoun ;
}
if ( q . children ( '.queet' ) . find ( '.rq-count' ) . length > 0 ) {
q . children ( '.queet' ) . find ( '.rq-count' ) . children ( 'strong' ) . html ( data . repeats . length ) ;
}
else {
q . children ( '.queet' ) . find ( 'li.avatar-row' ) . before ( '<li class="rq-count"><a>' + repeatsLabel + ' </a><strong>' + data . repeats . length + '</strong></li>' ) ;
}
2013-08-19 22:30:57 +09:00
}
2015-02-26 05:16:24 +09:00
2013-08-19 22:30:57 +09:00
2015-02-26 05:16:24 +09:00
// merge favs and repeats objects by user_id (removes duplicate users)
var favsAndRepeats = { } ;
$ . each ( data . repeats , function ( ) {
favsAndRepeats [ this . user _id ] = this ;
} ) ;
$ . each ( data . favs , function ( ) {
favsAndRepeats [ this . user _id ] = this ;
} ) ;
// make an object with time the key
var favsAndRepeatsByTime = { } ;
$ . each ( favsAndRepeats , function ( ) {
favsAndRepeatsByTime [ this . time ] = this ;
} ) ;
// create an array with times and sort it
var timeSorted = [ ] ;
$ . each ( favsAndRepeats , function ( ) {
timeSorted . push ( this . time ) ;
} ) ;
timeSorted . sort ( ) ;
// display avatars in chronological order, max 7
var avatarnum = 1 ;
$ . each ( timeSorted , function ( ) {
q . children ( '.queet' ) . find ( '.avatar-row' ) . append ( '<a title="' + favsAndRepeatsByTime [ this ] . fullname + '" data-user-id="' + favsAndRepeatsByTime [ this ] . user _id + '" href="' + favsAndRepeatsByTime [ this ] . profileurl + '"><img alt="' + favsAndRepeatsByTime [ this ] . fullname + '" src="' + favsAndRepeatsByTime [ this ] . avatarurl + '" class="avatar size24" id="av-' + favsAndRepeatsByTime [ this ] . user _id + '"></a>' ) ;
2015-02-26 05:50:16 +09:00
if ( avatarnum > 15 ) {
return false ;
}
2015-02-26 05:16:24 +09:00
avatarnum ++ ;
} ) ;
2013-08-19 22:30:57 +09:00
}
/ * ·
·
· Adds a profile card before feed element , with data from the first object in the included object
·
· @ param data : an object with one or more queet objects
·
· · · · · · · · · * /
function profileCardFromFirstObject ( data , screen _name ) {
var first = new Object ( ) ;
for ( var i in data ) {
if ( data . hasOwnProperty ( i ) && typeof ( i ) !== 'function' ) {
first = data [ i ] ;
break ;
}
}
if ( typeof first . user != 'undefined' ) {
2014-06-02 04:51:28 +09:00
first . user = cleanUpUserObject ( first . user ) ;
// use avatar if no cover photo
2014-11-24 21:47:45 +09:00
var coverPhotoHtml = '' ;
if ( first . user . cover _photo !== false ) {
coverPhotoHtml = 'background-image:url(\'' + first . user . cover _photo + '\')' ;
2014-06-02 04:51:28 +09:00
}
2013-08-19 22:30:57 +09:00
2014-09-30 21:52:41 +09:00
// follows me?
var follows _you = '' ;
if ( first . user . follows _you === true && window . myUserID != first . user . id ) {
var follows _you = '<span class="follows-you">' + window . sL . followsYou + '</span>' ;
2014-11-24 21:47:45 +09:00
}
2014-09-30 21:52:41 +09:00
2013-08-19 22:30:57 +09:00
// show user actions if logged in
var followingClass = '' ;
if ( first . user . following ) {
followingClass = 'following' ;
}
var followButton = '' ;
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name != 'undefined' && window . myUserID != first . user . id ) {
2015-01-27 01:35:44 +09:00
var followButton = '<div class="user-actions"><button data-follow-user-id="' + first . user . id + '" data-follow-user="' + first . user . statusnet _profile _url + '" type="button" class="qvitter-follow-button ' + followingClass + '"><span class="button-text follow-text"><i class="follow"></i>' + window . sL . userFollow + '</span><span class="button-text following-text">' + window . sL . userFollowing + '</span><span class="button-text unfollow-text">' + window . sL . userUnfollow + '</span></button></div>' ;
2013-11-23 08:31:04 +09:00
}
// follow from external instance if logged out
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name == 'undefined' ) {
2013-11-23 08:31:04 +09:00
var followButton = '<div class="user-actions"><button type="button" class="external-follow-button ' + followingClass + '"><span class="button-text follow-text"><i class="follow"></i>' + window . sL . userExternalFollow + '</span></button></div>' ;
}
2014-06-02 04:51:28 +09:00
// edit profile button if me
if ( typeof window . loggedIn . screen _name != 'undefined' && window . myUserID == first . user . id ) {
var followButton = '<div class="user-actions"><button type="button" class="edit-profile-button"><span class="button-text edit-profile-text">' + window . sL . editMyProfile + '</span></button></div>' ;
}
2014-11-24 21:47:45 +09:00
// is webpage empty?
var emptyWebpage = '' ;
if ( first . user . url . length < 1 ) {
emptyWebpage = ' empty' ;
}
2013-08-26 03:11:53 +09:00
2013-08-26 05:34:09 +09:00
// change design
changeDesign ( first . user ) ;
2014-01-29 03:42:47 +09:00
// remove any old profile card
$ ( '#feed' ) . siblings ( '.profile-card' ) . remove ( ) ;
// insert profile card into dom
2014-11-24 21:47:45 +09:00
$ ( '#feed' ) . before ( '<div class="profile-card"><div class="profile-header-inner" style="' + coverPhotoHtml + '"><div class="profile-header-inner-overlay"></div><a class="profile-picture" href="' + first . user . profile _image _url _original + '"><img src="' + first . user . profile _image _url _profile _size + '" /></a><div class="profile-card-inner"><h1 class="fullname">' + first . user . name + '<span></span></h1><h2 class="username"><span class="screen-name">@' + first . user . screen _name + '</span>' + follows _you + '</h2><div class="bio-container"><p>' + first . user . description + '</p></div><p class="location-and-url"><span class="location">' + first . user . location + '</span><span class="url' + emptyWebpage + '"><span class="divider"> · </span><a href="' + first . user . url + '">' + first . user . url . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) + '</a></span></p></div></div><div class="profile-banner-footer"><ul class="stats"><li><a class="tweet-stats">' + window . sL . notices + '<strong>' + first . user . statuses _count + '</strong></a></li><li><a class="following-stats">' + window . sL . following + '<strong>' + first . user . friends _count + '</strong></a></li><li><a class="follower-stats">' + window . sL . followers + '<strong>' + first . user . followers _count + '</strong></a></li><li><a class="groups-stats">' + window . sL . groups + '<strong>' + first . user . groups _count + '</strong></a></li></ul>' + followButton + '<div class="clearfix"></div></div></div>' ) ;
2013-08-19 22:30:57 +09:00
}
// if user hasn't queeted or if we're not allowed to read their queets
else {
getFromAPI ( 'users/show/' + screen _name + '.json' , function ( data ) { if ( data ) {
2014-06-02 04:51:28 +09:00
data = cleanUpUserObject ( data ) ;
2013-08-19 22:30:57 +09:00
2014-06-02 04:51:28 +09:00
// use avatar if no cover photo
2014-11-24 21:47:45 +09:00
var coverPhotoHtml = '' ;
if ( data . cover _photo !== false ) {
coverPhotoHtml = 'background-image:url(\'' + data . cover _photo + '\')' ;
}
2014-06-02 04:51:28 +09:00
2014-09-30 21:52:41 +09:00
// follows me?
var follows _you = '' ;
if ( data . follows _you === true && window . myUserID != data . id ) {
var follows _you = '<span class="follows-you">' + window . sL . followsYou + '</span>' ;
}
2013-08-19 22:30:57 +09:00
// show user actions if logged in
var followingClass = '' ;
if ( data . following ) {
followingClass = 'following' ;
}
var followButton = '' ;
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name != 'undefined' && window . myUserID != data . id ) {
2015-01-27 01:35:44 +09:00
var followButton = '<div class="user-actions"><button data-follow-user-id="' + data . id + '" data-follow-user="' + data . statusnet _profile _url + '" type="button" class="qvitter-follow-button ' + followingClass + '"><span class="button-text follow-text"><i class="follow"></i>' + window . sL . userFollow + '</span><span class="button-text following-text">' + window . sL . userFollowing + '</span><span class="button-text unfollow-text">' + window . sL . userUnfollow + '</span></button></div>' ;
2013-08-19 22:30:57 +09:00
}
2013-08-26 03:11:53 +09:00
2014-06-02 04:51:28 +09:00
// follow from external instance if logged out
if ( typeof window . loggedIn . screen _name == 'undefined' ) {
var followButton = '<div class="user-actions"><button type="button" class="external-follow-button ' + followingClass + '"><span class="button-text follow-text"><i class="follow"></i>' + window . sL . userExternalFollow + '</span></button></div>' ;
}
// edit profile button if me
if ( typeof window . loggedIn . screen _name != 'undefined' && window . myUserID == data . id ) {
var followButton = '<div class="user-actions"><button type="button" class="edit-profile-button"><span class="button-text edit-profile-text">' + window . sL . editMyProfile + '</span></button></div>' ;
}
2014-11-24 21:47:45 +09:00
// is webpage empty?
var emptyWebpage = '' ;
if ( data . url . length < 1 ) {
emptyWebpage = ' empty' ;
}
2014-06-02 04:51:28 +09:00
2013-08-26 05:34:09 +09:00
// change design
changeDesign ( data ) ;
2014-01-29 03:42:47 +09:00
// remove any old profile card and show profile card
$ ( '#feed' ) . siblings ( '.profile-card' ) . remove ( ) ;
2014-11-24 21:47:45 +09:00
$ ( '#feed' ) . before ( '<div class="profile-card"><div class="profile-header-inner" style="' + coverPhotoHtml + '"><div class="profile-header-inner-overlay"></div><a class="profile-picture" href="' + data . profile _image _url _original + '"><img src="' + data . profile _image _url _profile _size + '" /></a><div class="profile-card-inner"><h1 class="fullname">' + data . name + '<span></span></h1><h2 class="username"><span class="screen-name">@' + data . screen _name + '</span>' + follows _you + '</span></h2><div class="bio-container"><p>' + data . description + '</p></div><p class="location-and-url"><span class="location">' + data . location + '</span><span class="url' + emptyWebpage + '"><span class="divider"> · </span><a href="' + data . url + '">' + data . url . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) + '</a></span></p></div></div><div class="profile-banner-footer"><ul class="stats"><li><a class="tweet-stats">' + window . sL . notices + '<strong>' + data . statuses _count + '</strong></a></li><li><a class="following-stats">' + window . sL . following + '<strong>' + data . friends _count + '</strong></a></li><li><a class="follower-stats">' + window . sL . followers + '<strong>' + data . followers _count + '</strong></a></li><li><a class="groups-stats">' + window . sL . groups + '<strong>' + data . groups _count + '</strong></a></li></ul>' + followButton + '<div class="clearfix"></div></div></div>' ) ;
2013-08-19 22:30:57 +09:00
} } ) ;
}
}
/ * ·
·
· Adds a group profile card before feed element
·
· @ param data : an object with one or more queet objects
·
· · · · · · · · · * /
function groupProfileCard ( groupAlias ) {
getFromAPI ( 'statusnet/groups/show/' + groupAlias + '.json' , function ( data ) { if ( data ) {
data . nickname = data . nickname || '' ;
data . fullname = data . fullname || '' ;
2014-05-14 03:52:55 +09:00
data . stream _logo = data . stream _logo || window . fullUrlToThisQvitterApp + 'img/default-avatar-stream.png' ;
data . homepage _logo = data . homepage _logo || window . fullUrlToThisQvitterApp + 'img/default-avatar-profile.png' ;
data . original _logo = data . original _logo || window . fullUrlToThisQvitterApp + 'img/default-avatar-profile.png' ;
2013-08-19 22:30:57 +09:00
data . description = data . description || '' ;
data . homepage = data . homepage || '' ;
data . url = data . url || '' ;
data . member _count = data . member _count || 0 ;
data . admin _count = data . admin _count || 0 ;
// show user actions if logged in
var memberClass = '' ;
if ( data . member ) {
memberClass = 'member' ;
}
var memberButton = '' ;
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name != 'undefined' ) {
2013-08-19 22:30:57 +09:00
var memberButton = '<div class="user-actions"><button data-group-id="' + data . id + '" type="button" class="member-button ' + memberClass + '"><span class="button-text join-text"><i class="join"></i>' + window . sL . joinGroup + '</span><span class="button-text ismember-text">' + window . sL . isMemberOfGroup + '</span><span class="button-text leave-text">' + window . sL . leaveGroup + '</span></button></div>' ;
}
2014-01-29 03:42:47 +09:00
// follow from external instance if logged out
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name == 'undefined' ) {
2014-01-29 03:42:47 +09:00
var memberButton = '<div class="user-actions"><button type="button" class="external-member-button"><span class="button-text join-text"><i class="join"></i>' + window . sL . joinExternalGroup + '</span></button></div>' ;
}
2013-08-19 22:30:57 +09:00
// add card to DOM
2014-01-29 03:42:47 +09:00
$ ( '#feed' ) . siblings ( '.profile-card' ) . remove ( ) ; // remove any old profile card
2014-11-24 21:47:45 +09:00
$ ( '#feed' ) . before ( '<div class="profile-card"><div class="profile-header-inner" style="background-image:url(' + data . original _logo + ')"><div class="profile-header-inner-overlay"></div><a class="profile-picture" href="' + data . original _logo + '"><img src="' + data . homepage _logo + '" /></a><div class="profile-card-inner"><h1 class="fullname">' + data . fullname + '<span></span></h1><h2 class="username"><span class="screen-name">!' + data . nickname + '</span></span></h2><div class="bio-container"><p>' + data . description + '</p></div><p class="location-and-url"></span><span class="url"><a href="' + data . homepage + '">' + data . homepage . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) + '</a></span></p></div></div><div class="profile-banner-footer"><ul class="stats"><li><a class="member-stats">' + window . sL . memberCount + '<strong>' + data . member _count + '</strong></a></li><li><a class="admin-stats">' + window . sL . adminCount + '<strong>' + data . admin _count + '</strong></a></li></ul>' + memberButton + '<div class="clearfix"></div></div></div>' ) ;
2013-08-19 22:30:57 +09:00
} } ) ;
}
/ * ·
·
· Change stream
·
· @ param stream : part of the url to the api ( everything after api base url )
· @ param actionOnSuccess : callback function on success
·
· · · · · · · · · * /
function setNewCurrentStream ( stream , actionOnSuccess , setLocation ) {
2014-01-29 03:42:47 +09:00
// remember state of old stream (including profile card)
window . oldStreams [ window . currentStream ] = $ ( '#feed' ) . siblings ( '.profile-card' ) . outerHTML ( ) + $ ( '#feed' ) . outerHTML ( ) ;
2013-08-19 22:30:57 +09:00
// set location bar from stream
2014-05-14 16:46:07 +09:00
if ( setLocation ) {
2013-08-19 22:30:57 +09:00
setUrlFromStream ( stream ) ;
}
// halt interval that checks for new queets
window . clearInterval ( checkForNewQueetsInterval ) ;
display _spinner ( ) ;
2014-09-20 09:53:10 +09:00
// scroll to top
$ ( window ) . scrollTop ( 0 ) ;
$ ( 'body' ) . addClass ( 'androidFix' ) . scrollTop ( 0 ) . removeClass ( 'androidFix' ) ;
2013-08-19 22:30:57 +09:00
$ ( '#feed-body' ) . removeAttr ( 'data-search-page-number' ) ; // null any searches
// remember the most recent stream selection in global var
window . currentStream = stream ;
// if this is a @user stream, i.e. user's queets, user's followers, user's following, we set _queets_ as the default stream in the menu
2013-08-20 22:26:25 +09:00
if ( stream . substring ( 0 , 45 ) == 'statuses/followers.json?count=20&screen_name='
|| stream . substring ( 0 , 43 ) == 'statuses/friends.json?count=20&screen_name='
|| stream . substring ( 0 , 48 ) == 'statusnet/groups/list.json?count=10&screen_name='
2014-10-03 02:24:54 +09:00
|| stream . substring ( 0 , 43 ) == 'statuses/friends_timeline.json?screen_name='
2013-08-19 22:30:57 +09:00
|| stream . substring ( 0 , 27 ) == 'favorites.json?screen_name='
2014-10-03 02:24:54 +09:00
|| stream . substring ( 0 , 35 ) == 'statuses/mentions.json?screen_name='
2013-08-19 22:30:57 +09:00
|| stream . substring ( 0 , 27 ) == 'statuses/user_timeline.json' ) {
2013-08-20 22:26:25 +09:00
var defaultStreamName = 'statuses/user_timeline.json?' + stream . substring ( stream . indexOf ( 'screen_name=' ) ) ;
var streamHeader = '@' + stream . substring ( stream . lastIndexOf ( '=' ) + 1 ) ;
2013-08-19 22:30:57 +09:00
}
// if this is a my user streams, i.e. my followers, my following
2013-08-20 22:26:25 +09:00
else if ( stream == 'statuses/followers.json?count=20'
|| stream == 'statuses/friends.json?count=20'
|| stream == 'statusnet/groups/list.json?count=10' ) {
2013-08-19 22:30:57 +09:00
var defaultStreamName = stream ;
2014-05-16 11:07:30 +09:00
var streamHeader = '@' + window . loggedIn . screen _name ;
2013-08-19 22:30:57 +09:00
}
// if this is one of the default streams, get header from DOM
2014-10-03 02:24:54 +09:00
else if ( stream == 'statuses/friends_timeline.json'
|| stream == 'statuses/mentions.json'
2014-09-25 06:20:35 +09:00
|| stream == 'qvitter/statuses/notifications.json'
2013-08-19 22:30:57 +09:00
|| stream == 'favorites.json'
2014-01-29 03:42:47 +09:00
|| stream == 'statuses/public_timeline.json'
2014-05-16 11:07:30 +09:00
|| stream == 'statuses/public_and_external_timeline.json' ) {
2013-08-19 22:30:57 +09:00
var defaultStreamName = stream ;
var streamHeader = $ ( '.stream-selection[data-stream-name="' + stream + '"]' ) . attr ( 'data-stream-header' ) ;
}
// if this is a !group stream
2013-08-20 22:26:25 +09:00
else if ( stream . substring ( 0 , 26 ) == 'statusnet/groups/timeline/'
|| stream . substring ( 0 , 28 ) == 'statusnet/groups/membership/'
|| stream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' ) {
var defaultStreamName = 'statusnet/groups/timeline/' + stream . substring ( stream . lastIndexOf ( '/' ) + 1 ) ;
var streamHeader = '!' + stream . substring ( stream . lastIndexOf ( '/' ) + 1 , stream . indexOf ( '.json' ) ) ;
2013-08-19 22:30:57 +09:00
}
// if this is a #tag stream
else if ( stream . substring ( 0 , 24 ) == 'statusnet/tags/timeline/' ) {
var defaultStreamName = stream ;
var streamHeader = '#' + stream . substring ( stream . indexOf ( '/timeline/' ) + 10 , stream . indexOf ( '.json' ) ) ;
}
2014-09-25 06:20:35 +09:00
// 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' ) ) ;
}
2013-08-19 22:30:57 +09:00
// if this is a search stream
else if ( stream . substring ( 0 , 11 ) == 'search.json' ) {
var defaultStreamName = stream ;
2015-01-20 21:47:58 +09:00
var streamHeader = window . sL . searchVerb + ': ' + replaceHtmlSpecialChars ( decodeURIComponent ( stream . substring ( stream . indexOf ( '?q=' ) + 3 ) ) ) ;
2013-08-19 22:30:57 +09:00
}
// set the h2 header in the feed
if ( stream . substring ( 0 , 23 ) == 'statuses/followers.json' ) {
2014-09-25 06:20:35 +09:00
var h2FeedHeader = '<div class="queet-streams"><a class="queet-stream following">' + window . sL . following + '</a> / </div>' + window . sL . followers ;
2013-08-19 22:30:57 +09:00
}
else if ( stream . substring ( 0 , 21 ) == 'statuses/friends.json' ) {
2014-09-25 06:20:35 +09:00
var h2FeedHeader = window . sL . following + '<div class="queet-streams">/ <a class="queet-stream followers">' + window . sL . followers + '</a></div>' ;
2013-08-19 22:30:57 +09:00
}
else if ( stream . substring ( 0 , 40 ) == 'statuses/user_timeline.json?screen_name=' ) {
2013-08-20 05:09:33 +09:00
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>' ;
2013-08-19 22:30:57 +09:00
}
2014-10-03 02:24:54 +09:00
else if ( stream . substring ( 0 , 35 ) == 'statuses/mentions.json?screen_name=' ) {
2013-08-19 22:30:57 +09:00
var h2FeedHeader = '<div class="queet-streams"><a class="queet-stream queets">' + window . sL . notices + '</a> /</div>' + window . sL . mentions + '<div class="queet-streams">/ <a class="queet-stream favorites">' + window . sL . favoritesNoun + '</a></div>' ;
}
else if ( stream . substring ( 0 , 27 ) == 'favorites.json?screen_name=' ) {
var h2FeedHeader = '<div class="queet-streams"><a class="queet-stream queets">' + window . sL . notices + '</a> / <a class="queet-stream mentions">' + window . sL . mentions + '</a> /</div>' + window . sL . favoritesNoun ;
}
else if ( stream . substring ( 0 , 26 ) == 'statusnet/groups/list.json' ) {
var h2FeedHeader = window . sL . groups ;
2013-08-20 22:26:25 +09:00
}
else if ( stream . substring ( 0 , 28 ) == 'statusnet/groups/membership/' ) {
var h2FeedHeader = window . sL . memberCount ;
}
else if ( stream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' ) {
var h2FeedHeader = window . sL . adminCount ;
}
2014-10-03 02:24:54 +09:00
else if ( stream . substring ( 0 , 43 ) == 'statuses/friends_timeline.json?screen_name=' ) {
2013-08-19 22:30:57 +09:00
var h2FeedHeader = '<span style="unicode-bidi:bidi-override;direction:ltr;">' + streamHeader + '/all</span>' ; // ugly rtl fix, sry, we should have translations for this stream header
}
else {
var h2FeedHeader = streamHeader ;
}
2014-01-29 03:42:47 +09:00
// if we have a saved copy of this stream, show it immediately (but it is replaced when stream finishes to load later)
if ( typeof window . oldStreams [ window . currentStream ] != "undefined" ) {
2013-08-19 22:30:57 +09:00
$ ( '.profile-card' ) . remove ( ) ;
2014-01-29 03:42:47 +09:00
$ ( '#feed' ) . remove ( ) ;
$ ( '#user-container' ) . after ( window . oldStreams [ window . currentStream ] ) ;
$ ( '.profile-card' ) . css ( 'display' , 'none' ) ;
$ ( '#feed' ) . css ( 'display' , 'none' ) ;
2014-09-20 09:53:10 +09:00
$ ( '.profile-card' ) . show ( ) ;
$ ( '#feed' ) . show ( ) ;
$ ( '#feed-header-inner h2' ) . css ( 'opacity' , '0.2' ) ;
$ ( '#feed-header-inner h2' ) . animate ( { opacity : '1' } , 1000 ) ;
2014-01-29 03:42:47 +09:00
}
// otherwise we fade out and wait for stream to load
else {
// fade out
$ ( '#feed,.profile-card' ) . animate ( { opacity : '0' } , 150 , function ( ) {
// when fade out finishes, remove any profile cards and set new header
$ ( '.profile-card' ) . remove ( ) ;
$ ( '#feed-header-inner h2' ) . html ( h2FeedHeader ) ;
} ) ;
}
2013-08-19 22:30:57 +09:00
// add this stream to history menu if it doesn't exist there (but not if this is me or if we're not logged in)
if ( $ ( '.stream-selection[data-stream-header="' + streamHeader + '"]' ) . length == 0
2014-05-16 11:07:30 +09:00
&& streamHeader != '@' + window . loggedIn . screen _name
&& typeof window . loggedIn . screen _name != 'undefined' ) {
2014-01-29 03:42:47 +09:00
$ ( '#history-container' ) . append ( '<a class="stream-selection" data-stream-header="' + streamHeader + '" href="' + $ ( '.stream-selection.public-timeline' ) . attr ( 'href' ) + convertStreamToPath ( defaultStreamName ) + '">' + streamHeader + '<i class="chev-right"></i></a>' ) ;
2013-08-19 22:30:57 +09:00
updateHistoryLocalStorage ( ) ;
}
// mark this stream as current in menu
$ ( '.stream-selection' ) . removeClass ( 'current' ) ;
$ ( '.stream-selection[data-stream-header="' + streamHeader + '"]' ) . addClass ( 'current' ) ;
2014-09-25 06:20:35 +09:00
2013-08-19 22:30:57 +09:00
// 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'
|| stream . substring ( 0 , 26 ) == 'statusnet/groups/list.json'
2014-10-03 02:24:54 +09:00
|| stream . substring ( 0 , 35 ) == 'statuses/mentions.json?screen_name='
2013-08-19 22:30:57 +09:00
|| stream . substring ( 0 , 27 ) == 'favorites.json?screen_name='
2014-10-03 02:24:54 +09:00
|| stream . substring ( 0 , 43 ) == 'statuses/friends_timeline.json?screen_name=' ) {
2013-08-19 22:30:57 +09:00
getFromAPI ( defaultStreamName + '&count=1' , function ( profile _data ) {
if ( profile _data ) {
getFromAPI ( stream , function ( user _data ) {
if ( user _data ) {
// while waiting for this data user might have changed stream, so only proceed if current stream still is this one
2013-08-20 22:26:25 +09:00
if ( window . currentStream == stream ) {
2013-08-26 05:34:09 +09:00
// change design
changeDesign ( window ) ;
2013-08-26 03:11:53 +09:00
2013-08-20 22:26:25 +09:00
// get screen name from stream, if not found, this is me
if ( stream . indexOf ( 'screen_name=' ) > - 1 ) {
var thisUsersScreenName = stream . substring ( stream . indexOf ( 'screen_name=' ) + 12 ) ;
}
else {
2014-05-16 11:07:30 +09:00
var thisUsersScreenName = window . loggedIn . screen _name ;
2013-08-20 22:26:25 +09:00
}
profileCardFromFirstObject ( profile _data , thisUsersScreenName ) ; // show profile card
2014-09-25 06:20:35 +09:00
// start checking for new queets again
window . clearInterval ( checkForNewQueetsInterval ) ;
checkForNewQueetsInterval = window . setInterval ( function ( ) { checkForNewQueets ( ) } , window . timeBetweenPolling ) ;
2015-01-27 01:13:34 +09:00
2013-08-19 22:30:57 +09:00
remove _spinner ( ) ;
$ ( '#feed-body' ) . html ( '' ) ; // empty feed only now so the scrollers don't flicker on and off
2013-08-20 07:16:01 +09:00
$ ( '#new-queets-bar' ) . parent ( ) . addClass ( 'hidden' ) ; document . title = window . siteTitle ; // hide new queets bar if it's visible there
2014-01-29 03:42:47 +09:00
$ ( '#feed-body' ) . removeAttr ( 'data-search-page-number' ) ; // reset
2013-08-19 22:30:57 +09:00
addToFeed ( user _data , false , 'visible' ) ; // add stream items to feed element
$ ( '#feed' ) . animate ( { opacity : '1' } , 150 ) ; // fade in
$ ( 'body' ) . removeClass ( 'loading-older' ) ; $ ( 'body' ) . removeClass ( 'loading-newer' ) ;
actionOnSuccess ( ) ; // return
}
}
} ) ;
}
} ) ;
}
// if this is a queet stream
else {
getFromAPI ( stream , function ( queet _data ) {
if ( queet _data ) {
// while waiting for this data user might have changed stream, so only proceed if current stream still is this one
if ( window . currentStream == stream ) {
2014-05-23 21:13:38 +09:00
2013-08-26 05:34:09 +09:00
// change design
changeDesign ( window ) ;
2013-08-26 03:33:07 +09:00
2013-08-19 22:30:57 +09:00
// show profile card if this is a user's queet stream
if ( stream . substring ( 0 , 27 ) == 'statuses/user_timeline.json' ) {
var thisUsersScreenName = stream . replace ( 'statuses/user_timeline.json' , '' ) . replace ( '?screen_name=' , '' ) . replace ( '?id=' , '' ) . replace ( '?user_id=' , '' ) ;
profileCardFromFirstObject ( queet _data , thisUsersScreenName ) ;
}
// show group profile card if this is a group stream
2013-08-20 22:26:25 +09:00
else if ( stream . substring ( 0 , 26 ) == 'statusnet/groups/timeline/'
|| stream . substring ( 0 , 28 ) == 'statusnet/groups/membership/'
|| stream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' ) {
var thisGroupAlias = stream . substring ( stream . lastIndexOf ( '/' ) + 1 , stream . indexOf ( '.json' ) ) ;
2013-08-19 22:30:57 +09:00
groupProfileCard ( thisGroupAlias ) ;
}
2014-09-25 06:20:35 +09:00
// start checking for new queets again
window . clearInterval ( checkForNewQueetsInterval ) ;
checkForNewQueetsInterval = window . setInterval ( function ( ) { checkForNewQueets ( ) } , window . timeBetweenPolling ) ;
2013-08-19 22:30:57 +09:00
remove _spinner ( ) ;
$ ( '#feed-body' ) . html ( '' ) ; // empty feed only now so the scrollers don't flicker on and off
2013-08-20 07:16:01 +09:00
$ ( '#new-queets-bar' ) . parent ( ) . addClass ( 'hidden' ) ; document . title = window . siteTitle ; // hide new queets bar if it's visible there
2013-08-19 22:30:57 +09:00
addToFeed ( queet _data , false , 'visible' ) ; // add stream items to feed element
$ ( '#feed' ) . animate ( { opacity : '1' } , 150 ) ; // fade in
$ ( 'body' ) . removeClass ( 'loading-older' ) ; $ ( 'body' ) . removeClass ( 'loading-newer' ) ;
2014-11-24 21:47:45 +09:00
$ ( 'html,body' ) . scrollTop ( 0 ) ; // scroll to top
2013-08-19 22:30:57 +09:00
actionOnSuccess ( ) ; // return
}
}
} ) ;
}
}
/ * ·
·
2013-11-23 08:31:04 +09:00
· Convert stream to path
2013-08-19 22:30:57 +09:00
·
· @ param stream : the stream , e . g . 'public_timeline.json'
2013-11-23 08:31:04 +09:00
· @ returns : relative path
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · * /
2013-11-23 08:31:04 +09:00
function convertStreamToPath ( stream ) {
2013-08-20 22:26:25 +09:00
if ( stream . substring ( 0 , 45 ) == 'statuses/followers.json?count=20&screen_name=' ) {
var screenName = stream . substring ( stream . lastIndexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName + '/subscribers' ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
else if ( stream . substring ( 0 , 43 ) == 'statuses/friends.json?count=20&screen_name=' ) {
var screenName = stream . substring ( stream . lastIndexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName + '/subscriptions' ;
2013-08-19 22:30:57 +09:00
}
2014-10-03 02:24:54 +09:00
else if ( stream . substring ( 0 , 35 ) == 'statuses/mentions.json?screen_name=' ) {
2013-08-19 22:30:57 +09:00
var screenName = stream . substring ( stream . indexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName + '/replies' ;
2013-08-19 22:30:57 +09:00
}
else if ( stream . substring ( 0 , 27 ) == 'favorites.json?screen_name=' ) {
var screenName = stream . substring ( stream . indexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName + '/favorites' ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
else if ( stream . substring ( 0 , 48 ) == 'statusnet/groups/list.json?count=10&screen_name=' ) {
var screenName = stream . substring ( stream . lastIndexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName + '/groups' ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
else if ( stream == 'statuses/followers.json?count=20' ) {
2014-05-16 11:07:30 +09:00
return window . loggedIn . screen _name + '/subscribers' ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
else if ( stream == 'statuses/friends.json?count=20' ) {
2014-05-16 11:07:30 +09:00
return window . loggedIn . screen _name + '/subscriptions' ;
2013-08-19 22:30:57 +09:00
}
2014-10-03 02:24:54 +09:00
else if ( stream == 'statuses/mentions.json' ) {
2014-05-16 11:07:30 +09:00
return window . loggedIn . screen _name + '/replies' ;
2013-08-19 22:30:57 +09:00
}
2014-09-25 06:20:35 +09:00
else if ( stream == 'qvitter/statuses/notifications.json' ) {
return window . loggedIn . screen _name + '/notifications' ;
}
2013-08-19 22:30:57 +09:00
else if ( stream == 'favorites.json' ) {
2014-05-16 11:07:30 +09:00
return window . loggedIn . screen _name + '/favorites' ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
else if ( stream == 'statusnet/groups/list.json?count=10' ) {
2014-05-16 11:07:30 +09:00
return window . loggedIn . screen _name + '/groups' ;
2013-08-19 22:30:57 +09:00
}
else if ( stream . substring ( 0 , 27 ) == 'statuses/user_timeline.json' ) {
var screenName = stream . substring ( stream . indexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName ;
2013-08-19 22:30:57 +09:00
}
2014-10-03 02:24:54 +09:00
else if ( stream == 'statuses/friends_timeline.json' ) {
2014-05-16 11:07:30 +09:00
return window . loggedIn . screen _name + '/all' ;
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
else if ( stream . substring ( 0 , 43 ) == 'statuses/friends_timeline.json?screen_name=' ) {
2013-08-19 22:30:57 +09:00
var screenName = stream . substring ( stream . indexOf ( '=' ) + 1 ) ;
2013-11-23 08:31:04 +09:00
return screenName + '/all' ;
2013-08-19 22:30:57 +09:00
}
else if ( stream == 'statuses/public_timeline.json' ) {
2013-11-23 08:31:04 +09:00
return '' ;
2013-08-19 22:30:57 +09:00
}
2014-05-16 11:07:30 +09:00
else if ( stream == 'statuses/public_and_external_timeline.json' ) {
2014-01-29 03:42:47 +09:00
return 'main/all' ;
}
2013-08-19 22:30:57 +09:00
else if ( stream . substring ( 0 , 26 ) == 'statusnet/groups/timeline/' ) {
2013-08-20 22:26:25 +09:00
var groupName = stream . substring ( stream . lastIndexOf ( '/' ) + 1 , stream . indexOf ( '.json' ) ) ;
2013-11-23 08:31:04 +09:00
return 'group/' + groupName ;
2013-08-19 22:30:57 +09:00
}
2013-08-20 22:26:25 +09:00
else if ( stream . substring ( 0 , 28 ) == 'statusnet/groups/membership/' ) {
var groupName = stream . substring ( stream . lastIndexOf ( '/' ) + 1 , stream . indexOf ( '.json' ) ) ;
2013-11-23 08:31:04 +09:00
return 'group/' + groupName + '/members' ;
2013-08-20 22:26:25 +09:00
}
else if ( stream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' ) {
var groupName = stream . substring ( stream . lastIndexOf ( '/' ) + 1 , stream . indexOf ( '.json' ) ) ;
2013-11-23 08:31:04 +09:00
return 'group/' + groupName + '/admins' ;
2013-08-20 22:26:25 +09:00
}
2013-08-19 22:30:57 +09:00
else if ( stream . substring ( 0 , 24 ) == 'statusnet/tags/timeline/' ) {
var tagName = stream . substring ( stream . indexOf ( '/timeline/' ) + 10 , stream . indexOf ( '.json' ) ) ;
2013-11-23 08:31:04 +09:00
return 'tag/' + tagName ;
2013-08-19 22:30:57 +09:00
}
2014-09-25 06:20:35 +09:00
else if ( stream . substring ( 0 , 14 ) == 'statuses/show/' ) {
var noticeId = stream . substring ( stream . indexOf ( '/show/' ) + 6 , stream . indexOf ( '.json' ) ) ;
return 'notice/' + noticeId ;
}
2013-08-19 22:30:57 +09:00
else if ( stream . substring ( 0 , 11 ) == 'search.json' ) {
var searchTerms = stream . substring ( stream . indexOf ( '?q=' ) + 3 ) ;
2013-11-23 08:31:04 +09:00
return 'search/notice?q=' + searchTerms ;
2013-08-19 22:30:57 +09:00
}
}
2013-11-23 08:31:04 +09:00
/ * ·
·
· Sets the location bar in the browser to correspond with given stream
·
· @ param stream : the stream , e . g . 'public_timeline.json'
·
· · · · · · · · · * /
function setUrlFromStream ( stream ) {
history . pushState ( { strm : stream } , '' , '/' + convertStreamToPath ( stream ) ) ;
}
2013-08-19 22:30:57 +09:00
/ * ·
·
· Get stream from location bar
·
· @ param stream : the stream , e . g . 'public_timeline.json'
·
· · · · · · · · · * /
function getStreamFromUrl ( ) {
var loc = window . location . href . replace ( 'http://' , '' ) . replace ( 'https://' , '' ) . replace ( window . siteRootDomain , '' ) ;
// default/fallback
var streamToSet = 'statuses/public_timeline.json' ;
2014-01-29 03:42:47 +09:00
// main/all, i.e. full network
if ( loc == '/main/all' ) {
2014-05-16 11:07:30 +09:00
streamToSet = 'statuses/public_and_external_timeline.json' ;
2014-01-29 03:42:47 +09:00
}
2013-11-23 08:31:04 +09:00
// {domain}/{screen_name} or {domain}/{screen_name}/
2014-01-29 03:42:47 +09:00
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . substring ( 0 , loc . length - 1 ) . replace ( '/' , '' ) ) ) ) {
2013-11-23 08:31:04 +09:00
var userToStream = loc . replace ( '/' , '' ) . replace ( '/' , '' ) ;
2013-08-19 22:30:57 +09:00
if ( userToStream . length > 0 ) {
streamToSet = 'statuses/user_timeline.json?screen_name=' + userToStream ;
}
}
// {domain}/{screen_name}/all
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . replace ( '/' , '' ) . replace ( '/all' , '' ) ) ) ) {
var userToStream = loc . replace ( '/' , '' ) . replace ( '/all' , '' ) ;
if ( userToStream . length > 0 ) {
2014-05-16 11:07:30 +09:00
if ( window . loggedIn . screen _name == userToStream ) {
2014-10-03 02:24:54 +09:00
streamToSet = 'statuses/friends_timeline.json' ;
2013-08-19 22:30:57 +09:00
}
else {
2014-10-03 02:24:54 +09:00
streamToSet = 'statuses/friends_timeline.json?screen_name=' + userToStream ;
2013-08-19 22:30:57 +09:00
}
}
}
// {domain}/{screen_name}/replies
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . replace ( '/' , '' ) . replace ( '/replies' , '' ) ) ) ) {
var userToStream = loc . replace ( '/' , '' ) . replace ( '/replies' , '' ) ;
if ( userToStream . length > 0 ) {
2014-05-16 11:07:30 +09:00
if ( window . loggedIn . screen _name == userToStream ) {
2014-10-03 02:24:54 +09:00
streamToSet = 'statuses/mentions.json' ;
2013-08-19 22:30:57 +09:00
}
else {
2014-10-03 02:24:54 +09:00
streamToSet = 'statuses/mentions.json?screen_name=' + userToStream ;
2013-08-19 22:30:57 +09:00
}
}
}
2014-09-25 06:20:35 +09:00
// {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 ) ;
}
}
}
2013-08-19 22:30:57 +09:00
// {domain}/{screen_name}/favorites
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . replace ( '/' , '' ) . replace ( '/favorites' , '' ) ) ) ) {
var userToStream = loc . replace ( '/' , '' ) . replace ( '/favorites' , '' ) ;
if ( userToStream . length > 0 ) {
2014-05-16 11:07:30 +09:00
if ( window . loggedIn . screen _name == userToStream ) {
2013-08-19 22:30:57 +09:00
streamToSet = 'favorites.json' ;
}
else {
streamToSet = 'favorites.json?screen_name=' + userToStream ;
}
}
}
// {domain}/{screen_name}/subscribers
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . replace ( '/' , '' ) . replace ( '/subscribers' , '' ) ) ) ) {
var userToStream = loc . replace ( '/' , '' ) . replace ( '/subscribers' , '' ) ;
if ( userToStream . length > 0 ) {
2014-05-16 11:07:30 +09:00
if ( window . loggedIn . screen _name == userToStream ) {
2013-08-20 22:26:25 +09:00
streamToSet = 'statuses/followers.json?count=20' ;
2013-08-19 22:30:57 +09:00
}
else {
2013-08-20 22:26:25 +09:00
streamToSet = 'statuses/followers.json?count=20&screen_name=' + userToStream ;
2013-08-19 22:30:57 +09:00
}
}
}
// {domain}/{screen_name}/subscriptions
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . replace ( '/' , '' ) . replace ( '/subscriptions' , '' ) ) ) ) {
var userToStream = loc . replace ( '/' , '' ) . replace ( '/subscriptions' , '' ) ;
if ( userToStream . length > 0 ) {
2014-05-16 11:07:30 +09:00
if ( window . loggedIn . screen _name == userToStream ) {
2013-08-20 22:26:25 +09:00
streamToSet = 'statuses/friends.json?count=20' ;
2013-08-19 22:30:57 +09:00
}
else {
2013-08-20 22:26:25 +09:00
streamToSet = 'statuses/friends.json?count=20&screen_name=' + userToStream ;
2013-08-19 22:30:57 +09:00
}
}
}
// {domain}/{screen_name}/groups
else if ( ( /^[a-zA-Z0-9]+$/ . test ( loc . replace ( '/' , '' ) . replace ( '/groups' , '' ) ) ) ) {
var userToStream = loc . replace ( '/' , '' ) . replace ( '/groups' , '' ) ;
if ( userToStream . length > 0 ) {
2014-05-16 11:07:30 +09:00
if ( window . loggedIn . screen _name == userToStream ) {
2013-08-20 22:26:25 +09:00
streamToSet = 'statusnet/groups/list.json?count=10' ;
2013-08-19 22:30:57 +09:00
}
else {
2013-08-20 22:26:25 +09:00
streamToSet = 'statusnet/groups/list.json?count=10&screen_name=' + userToStream ;
2013-08-19 22:30:57 +09:00
}
}
}
// {domain}/tag/{tag}
else if ( loc . indexOf ( '/tag/' ) > - 1 ) {
var tagToStream = loc . replace ( '/tag/' , '' ) ;
if ( tagToStream . length > 0 ) {
streamToSet = 'statusnet/tags/timeline/' + tagToStream + '.json' ;
}
}
2014-09-25 06:20:35 +09:00
// {domain}/notice/{notide_id}
else if ( loc . indexOf ( '/notice/' ) > - 1 ) {
var noticeToStream = loc . replace ( '/notice/' , '' ) ;
if ( noticeToStream . length > 0 ) {
streamToSet = 'statuses/show/' + noticeToStream + '.json' ;
}
}
2013-08-20 22:26:25 +09:00
// {domain}/group/{group}/members, {domain}/group/{group}/admins or {domain}/group/{group}
else if ( loc . indexOf ( '/group/' ) > - 1 ) {
if ( loc . indexOf ( '/members' ) > - 1 ) {
var groupToStream = loc . replace ( '/group/' , '' ) . replace ( '/members' , '' ) ;
if ( groupToStream . length > 0 ) {
streamToSet = 'statusnet/groups/membership/' + groupToStream + '.json?count=20' ;
}
}
else if ( loc . indexOf ( '/admins' ) > - 1 ) {
var groupToStream = loc . replace ( '/group/' , '' ) . replace ( '/admins' , '' ) ;
if ( groupToStream . length > 0 ) {
streamToSet = 'statusnet/groups/admins/' + groupToStream + '.json?count=20' ;
}
}
else {
var groupToStream = loc . replace ( '/group/' , '' ) ;
if ( groupToStream . length > 0 ) {
streamToSet = 'statusnet/groups/timeline/' + groupToStream + '.json' ;
}
2013-08-19 22:30:57 +09:00
}
}
// {domain}/search/notice?q={urlencoded searh terms}
else if ( loc . indexOf ( '/search/notice?q=' ) > - 1 ) {
2015-01-20 22:45:42 +09:00
var searchToStream = replaceHtmlSpecialChars ( loc . replace ( '/search/notice?q=' , '' ) ) ;
2013-11-23 08:31:04 +09:00
if ( searchToStream . length > 0 ) {
2013-08-19 22:30:57 +09:00
streamToSet = 'search.json?q=' + searchToStream ;
}
}
return streamToSet ;
}
/ * ·
·
· Expand / de - expand queet
·
· @ param q : the stream item to expand
2013-11-23 08:31:04 +09:00
· @ param doScrolling : if we should scroll back to position or not
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · * /
2013-11-23 08:31:04 +09:00
function expand _queet ( q , doScrolling ) {
2013-08-19 22:30:57 +09:00
2014-11-24 21:47:45 +09:00
// don't do anything if this is a queet being posted
if ( q . hasClass ( 'temp-post' ) ) {
return ;
}
// don't expand if this is a remote profile popup
if ( q . closest ( '#popup-external-profile' ) . length > 0 ) {
return ;
}
2013-11-23 08:31:04 +09:00
doScrolling = typeof doScrolling !== 'undefined' ? doScrolling : true ;
2013-08-19 22:30:57 +09:00
var qid = q . attr ( 'data-quitter-id' ) ;
// de-expand if expanded
if ( q . hasClass ( 'expanded' ) && ! q . hasClass ( 'collapsing' ) ) {
2013-11-23 08:31:04 +09:00
var sel = getSelection ( ) . toString ( ) ;
2014-10-18 00:08:14 +09:00
if ( ! sel
&& ! q . find ( '.queet-button' ) . children ( 'button' ) . hasClass ( 'enabled' )
&& ! q . find ( '.queet-button' ) . children ( 'button' ) . hasClass ( 'too-long' ) ) { // don't collapse if text is selected, or if queet has an active queet button, or if queet text is too long
2014-09-25 06:20:35 +09:00
// remove some things right away
q . find ( '.inline-reply-caret' ) . remove ( ) ;
2013-11-23 08:31:04 +09:00
q . addClass ( 'collapsing' ) ;
2014-05-28 03:40:51 +09:00
q . css ( 'overflow' , 'hidden' ) ;
2013-11-23 08:31:04 +09:00
if ( q . hasClass ( 'conversation' ) ) {
2014-11-24 21:47:45 +09:00
q . removeClass ( 'expanded' ) ;
2013-11-23 08:31:04 +09:00
q . removeClass ( 'collapsing' ) ;
q . find ( '.view-more-container-top' ) . remove ( ) ;
q . find ( '.view-more-container-bottom' ) . remove ( ) ;
q . find ( '.stream-item.conversation' ) . remove ( ) ;
q . find ( '.inline-reply-queetbox' ) . remove ( ) ;
2014-11-24 21:47:45 +09:00
q . find ( '.expanded-content' ) . remove ( ) ;
2013-11-23 08:31:04 +09:00
}
else {
2014-01-29 03:42:47 +09:00
rememberMyScrollPos ( q . children ( '.queet' ) , qid , 0 ) ;
// give stream item a height
q . css ( 'height' , q . height ( ) + 'px' ) ;
2014-09-25 06:20:35 +09:00
q . children ( '.queet' ) . find ( '.expanded-content' ) . css ( 'height' , q . find ( '.expanded-content' ) . height ( ) + 'px' ) ;
2014-01-29 03:42:47 +09:00
q . children ( 'div' ) . not ( '.queet' ) . children ( 'a' ) . css ( 'opacity' , '0.5' ) ;
q . children ( 'div' ) . not ( '.queet' ) . children ( ) . children ( ) . css ( 'opacity' , '0.5' ) ;
2014-11-24 21:47:45 +09:00
var collapseTime = 100 + q . find ( '.stream-item.conversation:not(.hidden-conversation)' ) . length * 50 ;
2014-01-29 03:42:47 +09:00
// set transition time (needs to be delayed, otherwise webkit animates the height-setting above)
setTimeout ( function ( ) {
q . children ( '.queet' ) . css ( '-moz-transition-duration' , Math . round ( collapseTime / 1000 * 10 ) / 10 + 's' ) ;
q . children ( '.queet' ) . css ( '-o-transition-duration' , Math . round ( collapseTime / 1000 * 10 ) / 10 + 's' ) ;
q . children ( '.queet' ) . css ( '-webkit-transition-duration' , Math . round ( collapseTime * 1000 * 10 ) / 10 + 's' ) ;
q . children ( '.queet' ) . css ( 'transition-duration' , Math . round ( collapseTime / 1000 * 10 ) / 10 + 's' ) ;
q . css ( '-moz-transition-duration' , Math . round ( collapseTime / 1000 * 10 ) / 10 + 's' ) ;
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' ) ;
2014-09-25 06:20:35 +09:00
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' ) ;
2014-01-29 03:42:47 +09:00
// set new heights and margins to animate to
2014-11-24 21:47:45 +09:00
var animateToHeight = q . children ( '.queet' ) . outerHeight ( ) - q . find ( '.inline-reply-queetbox' ) . outerHeight ( ) - q . children ( '.queet' ) . find ( '.expanded-content' ) . outerHeight ( ) - 2 ;
if ( animateToHeight < 73 ) { // no less than this
animateToHeight = 73 ;
}
q . css ( 'height' , animateToHeight + 'px' ) ;
2014-01-29 03:42:47 +09:00
q . children ( '.queet' ) . css ( 'margin-top' , '-' + ( q . children ( '.queet' ) . offset ( ) . top - q . offset ( ) . top ) + 'px' ) ;
2014-11-24 21:47:45 +09:00
q . children ( '.queet' ) . find ( '.expanded-content' ) . css ( 'height' , '0' ) ;
2014-01-29 03:42:47 +09:00
2014-11-24 21:47:45 +09:00
} , 50 ) ;
2013-11-23 08:31:04 +09:00
if ( doScrolling ) {
2014-11-24 21:47:45 +09:00
setTimeout ( function ( ) {
backToMyScrollPos ( q , qid , 500 , function ( ) {
setTimeout ( function ( ) {
cleanUpAfterCollapseQueet ( q ) ;
} , 250 ) ;
} ) ;
} , collapseTime ) ;
}
else {
setTimeout ( function ( ) {
cleanUpAfterCollapseQueet ( q ) ;
} , collapseTime + 250 ) ;
2013-11-23 08:31:04 +09:00
}
2014-01-29 03:42:47 +09:00
2013-11-23 08:31:04 +09:00
}
}
2013-08-19 22:30:57 +09:00
}
2014-09-25 06:20:35 +09:00
else if ( ! q . hasClass ( 'collapsing' ) ) {
2013-08-19 22:30:57 +09:00
2014-09-25 06:20:35 +09:00
// not for acitivity or notifications
if ( ! q . hasClass ( 'activity' ) && ! q . hasClass ( 'repeat' ) && ! q . hasClass ( 'like' ) && ! q . hasClass ( 'follow' ) ) {
2013-11-23 08:31:04 +09:00
2014-11-24 21:47:45 +09:00
q . addClass ( 'expanded' ) ;
q . prev ( ) . addClass ( 'next-expanded' ) ;
2013-08-19 22:30:57 +09:00
2015-02-26 05:16:24 +09:00
// if shortened queet, get full text
if ( q . children ( '.queet' ) . find ( 'span.attachment.more' ) . length > 0 ) {
var attachmentId = q . children ( '.queet' ) . find ( 'span.attachment.more' ) . attr ( 'data-attachment-id' ) ;
2015-02-26 07:46:32 +09:00
// get full html for queet, first try localstorage cache
localStorageObjectCache _GET ( 'fullQueetHtml' , qid , function ( data ) {
2015-02-26 05:16:24 +09:00
if ( data ) {
q . children ( '.queet' ) . find ( '.queet-text' ) . html ( $ . trim ( data . replace ( /@<a/gi , '<a' ) . replace ( /!<a/gi , '<a' ) . replace ( /@<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /!<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /#<span class="tag">/gi , '<span class="tag">' ) . replace ( /@<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /@<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /!<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /#<span class="tag">/gi , '<span class="tag">' ) ) ) ;
}
2015-02-26 07:46:32 +09:00
else {
getFromAPI ( "attachment/" + attachmentId + ".json" , function ( data ) {
if ( data ) {
localStorageObjectCache _STORE ( 'fullQueetHtml' , qid , data ) ;
q . children ( '.queet' ) . find ( '.queet-text' ) . html ( $ . trim ( data . replace ( /@<a/gi , '<a' ) . replace ( /!<a/gi , '<a' ) . replace ( /@<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /!<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /#<span class="tag">/gi , '<span class="tag">' ) . replace ( /@<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /@<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /!<span class="vcard">/gi , '<span class="vcard">' ) . replace ( /#<span class="tag">/gi , '<span class="tag">' ) ) ) ;
}
} ) ;
}
} ) ;
2013-08-19 22:30:57 +09:00
}
// add expanded container
var longdate = parseTwitterLongDate ( q . find ( '.created-at' ) . attr ( 'data-created-at' ) ) ;
var qurl = q . find ( '.created-at' ) . find ( 'a' ) . attr ( 'href' ) ;
2013-11-23 08:31:04 +09:00
var metadata = '<span class="longdate" title="' + longdate + '">' + longdate + ' · ' + unescape ( q . attr ( 'data-source' ) ) + '</span> · <a href="' + qurl + '" class="permalink-link">' + window . sL . details + '</a>' ;
2013-08-19 22:30:57 +09:00
// show expanded content
2014-09-25 06:20:35 +09:00
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>' ) ;
2013-08-19 22:30:57 +09:00
2014-05-12 07:23:57 +09:00
2014-01-29 03:42:47 +09:00
// maybe show images or videos
2014-05-12 07:23:57 +09:00
$ . each ( $ ( '#' + q . children ( '.queet' ) . attr ( 'id' ) + ' .queet-text, #' + q . children ( '.queet' ) . attr ( 'id' ) + ' > .attachments' ) . find ( 'a' ) , function ( ) {
2015-01-24 00:28:41 +09:00
2015-02-25 04:44:48 +09:00
var attachment _mimetype = $ ( this ) . find ( 'img' ) . attr ( 'data-mime-type' ) ;
if ( typeof attachment _mimetype == 'undefined' ) {
attachment _mimetype = '' ;
}
2013-08-19 22:30:57 +09:00
var attachment _title = $ ( this ) . attr ( 'title' ) ;
2014-05-12 07:23:57 +09:00
// attachments in the .attachments container don't have a title, their full url is in the href
if ( typeof attachment _title == 'undefined' ) {
attachment _title = $ ( this ) . attr ( 'href' ) ;
}
2015-02-26 06:53:09 +09:00
// filename extension
var attachment _title _extension = attachment _title . substr ( ( ~ - attachment _title . lastIndexOf ( "." ) >>> 0 ) + 2 ) ;
2014-05-12 07:23:57 +09:00
// attachments in the content link to /attachment/etc url and not direct to image/video, link is in title
2013-08-19 22:30:57 +09:00
if ( typeof attachment _title != 'undefined' ) {
2014-01-29 03:42:47 +09:00
// images
2015-02-26 06:53:09 +09:00
if ( $ . inArray ( attachment _mimetype , [ 'image/gif' , 'image/jpeg' , 'image/png' ] ) >= 0
|| $ . inArray ( attachment _title _extension , [ 'jpeg' , 'gif' , 'jpg' , 'png' ] ) >= 0 ) {
2014-11-24 21:47:45 +09:00
if ( q . children ( '.queet' ) . find ( '.expanded-content' ) . children ( '.media' ) . children ( 'a[href="' + attachment _title + '"]' ) . length < 1 ) { // not if already showed
2015-01-24 00:28:41 +09:00
// local attachment with a thumbnail
if ( typeof $ ( this ) . find ( 'img' ) . attr ( 'data-big-thumbnail' ) != 'undefined' ) {
var attachment _src = $ ( this ) . find ( 'img' ) . attr ( 'data-big-thumbnail' ) ;
}
// external "deep linked" images
else {
var attachment _src = attachment _title ;
}
// don't show thumbnails for gifs
2015-02-25 04:44:48 +09:00
if ( attachment _mimetype == 'image/gif' ) {
2015-01-24 00:28:41 +09:00
var attachment _src = attachment _title ;
}
2014-11-24 21:47:45 +09:00
if ( q . children ( '.queet' ) . find ( '.expanded-content' ) . children ( '.media' ) . length > 0 ) {
2015-01-24 00:28:41 +09:00
q . children ( '.queet' ) . find ( '.media' ) . last ( ) . after ( '<div class="media"><a href="' + attachment _title + '" target="_blank"><img src="' + attachment _src + '" /></a></div>' ) ;
2014-11-24 21:47:45 +09:00
}
else {
2015-01-24 00:28:41 +09:00
q . children ( '.queet' ) . find ( '.expanded-content' ) . prepend ( '<div class="media"><a href="' + attachment _title + '" target="_blank"><img src="' + attachment _src + '" /></a></div>' ) ;
2014-11-24 21:47:45 +09:00
}
2015-02-26 06:53:09 +09:00
}
2013-08-19 22:30:57 +09:00
}
2014-01-29 03:42:47 +09:00
// videos
2015-02-25 10:11:32 +09:00
else if ( $ . inArray ( attachment _mimetype , [ 'video/mp4' , 'video/ogg' , 'video/quicktime' , 'video/webm' ] ) >= 0 ) {
2015-02-25 10:27:11 +09:00
if ( q . children ( '.queet' ) . find ( '.expanded-content' ) . children ( '.media' ) . children ( 'video' ) . children ( 'source[href="' + attachment _title + '"]' ) . length < 1 ) { // not if already showed
2015-02-25 10:11:32 +09:00
// local attachment with a thumbnail
if ( typeof $ ( this ) . find ( 'img' ) . attr ( 'data-big-thumbnail' ) != 'undefined' ) {
var attachment _poster = $ ( this ) . find ( 'img' ) . attr ( 'data-big-thumbnail' ) ;
}
if ( q . children ( '.queet' ) . find ( '.expanded-content' ) . children ( '.media' ) . length > 0 ) {
q . children ( '.queet' ) . find ( '.media' ) . last ( ) . after ( '<div class="media"><video class="u-video" controls="controls" poster="' + attachment _poster + '"><source type="' + attachment _mimetype + '" src="' + attachment _title + '" /></video></div>' ) ;
}
else {
q . children ( '.queet' ) . find ( '.expanded-content' ) . prepend ( '<div class="media"><video class="u-video" controls="controls" poster="' + attachment _poster + '"><source type="' + attachment _mimetype + '" src="' + attachment _title + '" /></video></div>' ) ;
}
}
}
2014-05-12 07:23:57 +09:00
else if ( attachment _title . indexOf ( 'youtube.com/watch?v=' ) > - 1 || attachment _title . indexOf ( '://youtu.be/' ) > - 1 ) {
var youtubeId = attachment _title . replace ( 'http://www.youtube.com/watch?v=' , '' ) . replace ( 'https://www.youtube.com/watch?v=' , '' ) . replace ( 'http://youtu.be/' , '' ) . replace ( 'https://youtu.be/' , '' ) . substr ( 0 , 11 ) ;
if ( q . children ( '.queet' ) . find ( '.expanded-content' ) . children ( '.media' ) . children ( 'iframe' ) . attr ( 'src' ) != '//www.youtube.com/embed/' + youtubeId ) { // not if already showed
q . children ( '.queet' ) . find ( '.expanded-content' ) . prepend ( '<div class="media"><iframe width="420" height="315" src="//www.youtube.com/embed/' + youtubeId + '" frameborder="0" allowfullscreen></iframe></div>' ) ;
}
2014-01-29 03:42:47 +09:00
}
2015-03-03 08:33:18 +09:00
else {
// other plugins, e.g. gotabulo, can check for other attachment file formats to expand
window . currentlyExpanding = {
"attachment_title" : attachment _title ,
"attachment_mimetype" : attachment _mimetype ,
"attachment_title_extension" : attachment _title _extension ,
"streamItem" : q ,
"thisAttachmentLink" : $ ( this )
} ;
$ ( document ) . trigger ( 'qvitterExpandOtherAttachments' ) ;
}
2013-08-19 22:30:57 +09:00
}
} ) ;
2015-02-26 05:16:24 +09:00
// get and show favs and repeats
getFavsAndRequeetsForQueet ( q , qid ) ;
2013-08-19 22:30:57 +09:00
// show conversation and reply form (but not if already in conversation)
if ( ! q . hasClass ( 'conversation' ) ) {
2015-02-26 05:16:24 +09:00
// show conversation (wait for css to animate the margin 50ms)
setTimeout ( function ( ) {
getConversation ( q , qid ) ;
} , 50 ) ;
2013-08-19 22:30:57 +09:00
2013-09-03 01:13:15 +09:00
// show inline reply form if logged in
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name != 'undefined' ) {
2013-09-03 01:13:15 +09:00
q . find ( '#q-' + qid ) . append ( replyFormHtml ( q , qid ) ) ;
}
2013-08-19 22:30:57 +09:00
}
}
}
}
2014-11-24 21:47:45 +09:00
function cleanUpAfterCollapseQueet ( q ) {
q . css ( 'height' , 'auto' ) ;
q . children ( '.queet' ) . css ( 'margin-top' , '0' ) ;
q . removeClass ( 'expanded' ) ;
q . prev ( ) . removeClass ( 'next-expanded' ) ;
q . removeClass ( 'collapsing' ) ;
q . find ( '.expanded-content' ) . remove ( ) ;
q . find ( '.view-more-container-top' ) . remove ( ) ;
q . find ( '.view-more-container-bottom' ) . remove ( ) ;
q . find ( '.inline-reply-queetbox' ) . remove ( ) ;
q . find ( '.stream-item.conversation' ) . remove ( ) ;
q . find ( '.show-full-conversation' ) . remove ( ) ;
q . removeAttr ( 'style' ) ;
q . children ( '.queet' ) . removeAttr ( 'style' ) ;
}
2014-05-28 03:40:51 +09:00
/ * ·
·
· Get an inline queet box
·
· @ return the html for the queet box
·
· · · · · · · · · * /
function queetBoxHtml ( ) {
var startText = encodeURIComponent ( window . sL . compose ) ;
2014-11-24 21:47:45 +09:00
return '<div class="inline-reply-queetbox"><div class="queet-box queet-box-syntax" data-start-text="' + startText + '">' + decodeURIComponent ( startText ) + '</div><div class="syntax-middle"></div><div class="syntax-two" contenteditable="true"></div><div class="mentions-suggestions"></div><div class="queet-toolbar toolbar-reply"><div class="queet-box-extras"><button class="upload-image"></button><button class="shorten disabled">URL</button></div><div class="queet-button"><span class="queet-counter"></span><button>' + window . sL . queetVerb + '</button></div></div></div>' ;
2014-05-28 03:40:51 +09:00
}
2013-08-19 22:30:57 +09:00
/ * ·
·
· Get a reply form
·
· @ param q : the stream item to open reply form in
· @ param qid : queet id
· @ return the html for the reply form
·
· · · · · · · · · * /
function replyFormHtml ( q , qid ) {
// get all @:s
2013-11-29 20:49:54 +09:00
var user _screen _name = q . children ( '.queet' ) . find ( '.screen-name' ) . html ( ) . substring ( 1 ) ;
2013-08-19 22:30:57 +09:00
var user _screen _name _html = '<a>@' + user _screen _name + '</a>' ;
2013-11-23 08:31:04 +09:00
var user _screen _name _text = '@' + user _screen _name ;
2013-08-19 22:30:57 +09:00
var reply _to _screen _name = '' ;
var reply _to _screen _name _html = '' ;
2013-11-23 08:31:04 +09:00
var reply _to _screen _name _text = '' ;
2013-08-19 22:30:57 +09:00
if ( q . attr ( 'data-in-reply-to-screen-name' ) . length > 0 // not if not a reply
&& q . attr ( 'data-in-reply-to-screen-name' ) != $ ( '#user-screen-name' ) . html ( ) // not if it's me
&& q . attr ( 'data-in-reply-to-screen-name' ) != user _screen _name // not same screen name twice
) {
reply _to _screen _name = q . attr ( 'data-in-reply-to-screen-name' ) ;
reply _to _screen _name _html = ' <a>@' + reply _to _screen _name + '</a>' ;
2013-11-23 08:31:04 +09:00
reply _to _screen _name _text = ' @' + reply _to _screen _name ;
2013-08-19 22:30:57 +09:00
}
var more _reply _tos = '' ;
2013-11-23 08:31:04 +09:00
var more _reply _tos _text = '' ;
2013-11-29 20:49:54 +09:00
$ . each ( q . children ( '.queet' ) . find ( '.queet-text' ) . find ( '.mention' ) , function ( key , obj ) {
2013-08-19 22:30:57 +09:00
if ( $ ( obj ) . html ( ) != user _screen _name && $ ( obj ) . html ( ) != reply _to _screen _name && $ ( obj ) . html ( ) != $ ( '#user-screen-name' ) . html ( ) ) {
more _reply _tos = more _reply _tos + ' <a>@' + $ ( obj ) . html ( ) + '</a>' ;
2013-11-23 08:31:04 +09:00
more _reply _tos _text = more _reply _tos _text + ' @' + $ ( obj ) . html ( ) ;
2013-08-19 22:30:57 +09:00
}
} ) ;
2014-05-28 03:40:51 +09:00
var startText = encodeURIComponent ( window . sL . replyTo + ' ' + user _screen _name _html + reply _to _screen _name _html + more _reply _tos + ' <br>' ) ;
2014-11-29 12:29:18 +09:00
var repliesText = encodeURIComponent ( user _screen _name _text + reply _to _screen _name _text + more _reply _tos _text + ' ' ) ;
2014-11-24 21:47:45 +09:00
return '<div class="inline-reply-queetbox"><span class="inline-reply-caret"><span class="caret-inner"></span></span><img class="reply-avatar" src="' + $ ( '#user-avatar' ) . attr ( 'src' ) + '" /><div class="queet-box queet-box-syntax" id="queet-box-' + qid + '" data-start-text="' + startText + '" data-replies-text="' + repliesText + '">' + decodeURIComponent ( startText ) + '</div><div class="syntax-middle"></div><div class="syntax-two" contenteditable="true"></div><div class="mentions-suggestions"></div><div class="queet-toolbar toolbar-reply"><div class="queet-box-extras"><button class="upload-image"></button><button class="shorten disabled">URL</button></div><div class="queet-button"><span class="queet-counter"></span><button>' + window . sL . queetVerb + '</button></div></div></div>' ;
2013-08-19 22:30:57 +09:00
}
/ * ·
·
· Popup for replies , deletes , etc
·
· @ param popupId : popups id
· @ param heading : popops header
· @ param bodyHtml : popups body html
· @ param footerHtml : popups footer html
·
· · · · · · · · · · · · · * /
function popUpAction ( popupId , heading , bodyHtml , footerHtml ) {
2014-11-24 21:47:45 +09:00
$ ( '.modal-container' ) . remove ( ) ; // remove any open popups
2013-08-19 22:30:57 +09:00
var allFooterHtml = '' ;
if ( footerHtml ) {
allFooterHtml = '<div class="modal-footer">' + footerHtml + '</div>' ;
}
$ ( 'body' ) . prepend ( '<div id="' + popupId + '" class="modal-container"><div class="modal-draggable"><div class="modal-content"><button class="modal-close" type="button"><span class="icon"></span></button><div class="modal-header"><h3 class="modal-title">' + heading + '</h3></div><div class="modal-body">' + bodyHtml + '</div>' + allFooterHtml + '</div></div></div>' ) ;
var this _modal _height = $ ( '#' + popupId ) . children ( '.modal-draggable' ) . height ( ) ;
var this _modal _width = $ ( '#' + popupId ) . children ( '.modal-draggable' ) . width ( ) ;
var popupPos = $ ( '#' + popupId ) . children ( '.modal-draggable' ) . offset ( ) . top - $ ( window ) . scrollTop ( ) ;
if ( ( popupPos - ( this _modal _height / 2 ) ) < 5 ) {
var marginTop = 5 - popupPos ;
}
else {
var marginTop = 0 - this _modal _height / 2 ;
}
$ ( '#' + popupId ) . children ( '.modal-draggable' ) . css ( 'margin-top' , marginTop + 'px' ) ;
$ ( '#' + popupId ) . children ( '.modal-draggable' ) . css ( 'margin-left' , '-' + ( this _modal _width / 2 ) + 'px' ) ;
$ ( '#' + popupId ) . children ( '.modal-draggable' ) . draggable ( { handle : ".modal-header" } ) ;
$ ( '#' + popupId ) . children ( '.modal-header' ) . disableSelection ( ) ;
}
2014-05-12 20:20:26 +09:00
/ * ·
·
· Gnu social don ' t use url as uri anymore , we need to handle both cases
·
· · · · · · · · · · · · · * /
function convertNewGNUSocialURItoURL ( obj ) {
2014-11-25 00:10:59 +09:00
if ( typeof obj . uri == 'undefined' ) {
obj . uri = '' ;
}
2014-05-12 20:20:26 +09:00
if ( obj . uri . substring ( 0 , 4 ) != 'http' ) {
// guess the url if we only have the non-url uri
if ( typeof obj . url == 'undefined' ) {
var httpOrHttps = obj . user . statusnet _profile _url . substring ( 0 , obj . user . statusnet _profile _url . indexOf ( '://' ) ) ;
obj . uri = httpOrHttps + '://' + obj . uri . substring ( 4 , obj . uri . indexOf ( ',' ) ) + '/notice/' + obj . uri . substring ( obj . uri . indexOf ( 'noticeId=' ) + 9 , obj . uri . indexOf ( ':objectType' ) ) ;
}
// if an url record is present, use that
else {
obj . uri = obj . url ;
}
}
return obj ;
}
2013-08-19 22:30:57 +09:00
/ * ·
·
2015-02-26 05:16:24 +09:00
· Get and show conversation
2013-08-19 22:30:57 +09:00
·
· This function has grown into a monster , needs fixing
·
· · · · · · · · · · · · · * /
2015-02-26 05:16:24 +09:00
function getConversation ( q , qid ) {
2015-01-27 09:57:08 +09:00
2015-02-26 05:16:24 +09:00
// check if we have a conversation for this notice cached in localstorage
if ( localStorageIsEnabled ( ) ) {
2013-11-23 08:31:04 +09:00
2015-02-26 05:16:24 +09:00
if ( typeof localStorage [ 'conversation-' + qid ] != 'undefined' && localStorage [ 'conversation-' + qid ] !== null ) {
showConversation ( q , qid , JSON . parse ( localStorage [ 'conversation-' + qid ] ) ) ;
}
// if we have a conversation for the notice that this notice is a reply to,
// we assume it's the same conversation, and use that
else if ( q . attr ( 'data-in-reply-to-status-id' ) !== null
&& q . attr ( 'data-in-reply-to-status-id' ) != 'null'
&& typeof localStorage [ 'conversation-' + q . attr ( 'data-in-reply-to-status-id' ) ] != 'undefined'
&& localStorage [ 'conversation-' + q . attr ( 'data-in-reply-to-status-id' ) ] !== null ) {
showConversation ( q , qid , JSON . parse ( localStorage [ 'conversation-' + q . attr ( 'data-in-reply-to-status-id' ) ] ) ) ;
}
}
// always get most recent conversation from server
getFromAPI ( 'statusnet/conversation/' + $ ( '#stream-item-' + qid ) . attr ( 'data-conversation-id' ) + '.json?count=100' , function ( data ) { if ( data ) {
2014-11-24 21:47:45 +09:00
2015-02-26 05:16:24 +09:00
// cache in localstorage
if ( localStorageIsEnabled ( ) ) {
localStorage [ 'conversation-' + qid ] = JSON . stringify ( data ) ;
}
2013-11-23 08:31:04 +09:00
2015-02-26 05:16:24 +09:00
showConversation ( q , qid , data ) ;
} } ) ;
}
function showConversation ( q , qid , data ) {
rememberMyScrollPos ( q . children ( '.queet' ) , qid , 0 ) ;
if ( data && ! q . hasClass ( 'collapsing' ) ) {
2014-05-12 20:20:26 +09:00
2015-02-26 05:16:24 +09:00
if ( data . length > 1 ) {
var before _or _after = 'before' ;
$ . each ( data . reverse ( ) , function ( key , obj ) {
// switch to append after original queet
if ( obj . id == qid ) {
before _or _after = 'after' ;
}
// don't add clicked queet to DOM, but all else
// note: first we add the full conversation, but hidden
if ( obj . id != qid ) {
var queetTime = parseTwitterDate ( obj . created _at ) ;
if ( obj . source == 'activity' ) {
var queetHtml = '<div id="conversation-stream-item-' + obj . id + '" class="stream-item conversation activity hidden-conversation" data-source="' + escape ( obj . source ) + '" data-quitter-id="' + obj . id + '" data-quitter-id-in-stream="' + obj . id + '"><div class="queet" id="conversation-q-' + obj . id + '"><div class="queet-content"><div class="stream-item-header"><small class="created-at" data-created-at="' + obj . created _at + '"><a>' + queetTime + '</a></small></div><div class="queet-text">' + $ . trim ( obj . statusnet _html ) + '</div></div></div></div>' ;
}
else {
var queetHtml = buildQueetHtml ( obj , obj . id , 'conversation hidden-conversation' , false , true ) ;
}
// detect rtl
queetHtml = detectRTL ( queetHtml ) ;
if ( q . hasClass ( 'expanded' ) ) { // add queet to conversation only if still expanded
// replace already existing queets' html
if ( q . children ( '#conversation-stream-item-' + obj . id ) . length > 0 ) {
var streamItemInnerHtml = $ ( '<div/>' ) . append ( queetHtml ) . find ( '.stream-item' ) . html ( ) ;
q . children ( '#conversation-stream-item-' + obj . id ) . html ( streamItemInnerHtml ) ;
2014-11-24 21:47:45 +09:00
}
2015-02-26 05:16:24 +09:00
else if ( before _or _after == 'before' ) {
q . children ( '.queet' ) . before ( queetHtml ) ;
2013-08-19 22:30:57 +09:00
}
else {
2015-02-26 05:16:24 +09:00
if ( q . children ( '.queet' ) . nextAll ( '.conversation' ) . length < 1 ) {
q . children ( '.queet' ) . after ( queetHtml ) ;
2013-08-19 22:30:57 +09:00
}
else {
2015-02-26 05:16:24 +09:00
q . children ( '.queet' ) . nextAll ( '.conversation' ) . last ( ) . after ( queetHtml ) ;
2013-08-19 22:30:57 +09:00
}
}
2015-02-26 05:16:24 +09:00
2013-08-19 22:30:57 +09:00
}
}
2015-02-26 05:16:24 +09:00
convertAttachmentMoreHref ( ) ;
} ) ;
2013-08-19 22:30:57 +09:00
}
else {
remove _spinner ( ) ;
2015-02-26 05:16:24 +09:00
}
// loop trough this stream items conversation and show the "strict" line of replies
findInReplyToStatusAndShow ( q , qid , q . attr ( 'data-in-reply-to-status-id' ) , true , false ) ;
backToMyScrollPos ( q . children ( '.queet' ) , qid , false ) ;
findAndMarkLastVisibleInConversation ( q ) ;
}
else {
remove _spinner ( ) ;
}
2013-08-19 22:30:57 +09:00
}
2014-11-26 08:58:56 +09:00
/ * ·
·
· Add last visible class , since that ' s not possible to select in pure css
·
· · · · · · · · · · · · · * /
function findAndMarkLastVisibleInConversation ( streamItem ) {
streamItem . children ( ) . removeClass ( 'last-visible' ) ;
2014-11-26 09:51:07 +09:00
streamItem . children ( ) . removeClass ( 'first-visible-after-parent' ) ;
streamItem . children ( ) . not ( '.hidden-conversation' ) . last ( ) . addClass ( 'last-visible' ) ;
streamItem . children ( '.queet' ) . nextAll ( ) . not ( '.hidden-conversation' ) . first ( ) . addClass ( 'first-visible-after-parent' ) ;
2014-11-26 08:58:56 +09:00
}
2013-08-19 22:30:57 +09:00
/ * ·
·
· Recursive walker functions to view onlt reyplies to replies , not full conversation
·
· · · · · · · · · · · · · * /
2015-02-26 05:16:24 +09:00
function findInReplyToStatusAndShow ( q , qid , reply , only _first , onlyINreplyto ) {
2013-08-19 22:30:57 +09:00
var reply _found = $ ( '#stream-item-' + qid ) . find ( '.stream-item[data-quitter-id="' + reply + '"]' ) ;
var reply _found _reply _to = $ ( '#stream-item-' + qid ) . find ( '.stream-item[data-quitter-id="' + reply _found . attr ( 'data-in-reply-to-status-id' ) + '"]' ) ;
if ( reply _found . length > 0 ) {
reply _found . removeClass ( 'hidden-conversation' ) ;
2014-01-29 03:42:47 +09:00
reply _found . css ( 'opacity' , '1' ) ;
2013-08-19 22:30:57 +09:00
if ( only _first && reply _found _reply _to . length > 0 ) {
2015-02-26 05:16:24 +09:00
if ( q . children ( '.view-more-container-top' ) . length < 1 ) {
reply _found . before ( '<div class="view-more-container-top" data-trace-from="' + reply + '"><a>' + window . sL . viewMoreInConvBefore + '</a></div>' ) ;
}
findReplyToStatusAndShow ( q , qid , qid , true ) ;
2013-08-19 22:30:57 +09:00
}
else {
2015-02-26 05:16:24 +09:00
findInReplyToStatusAndShow ( q , qid , reply _found . attr ( 'data-in-reply-to-status-id' ) , false , onlyINreplyto ) ;
2013-08-19 22:30:57 +09:00
}
}
else if ( ! onlyINreplyto ) {
2015-02-26 05:16:24 +09:00
findReplyToStatusAndShow ( q , qid , qid , true ) ;
2013-08-19 22:30:57 +09:00
}
else {
2015-02-26 05:16:24 +09:00
checkForHiddenConversationQueets ( q , qid ) ;
2013-08-19 22:30:57 +09:00
}
}
// recursive function to find the replies to a status
2015-02-26 05:16:24 +09:00
function findReplyToStatusAndShow ( q , qid , this _id , only _first ) {
var replies _found = q . find ( '.stream-item[data-in-reply-to-status-id="' + this _id + '"]' ) ;
$ . each ( replies _found , function ( k , reply _found ) {
var reply _founds _reply = q . find ( '.stream-item[data-in-reply-to-status-id="' + $ ( reply _found ) . attr ( 'data-quitter-id' ) + '"]' ) ;
$ ( reply _found ) . removeClass ( 'hidden-conversation' ) ;
$ ( reply _found ) . css ( 'opacity' , '1' ) ;
2014-01-29 03:42:47 +09:00
if ( ! only _first ) {
2015-02-26 05:16:24 +09:00
findReplyToStatusAndShow ( q , qid , $ ( this ) . attr ( 'data-quitter-id' ) , false ) ;
2014-01-29 03:42:47 +09:00
}
2013-08-19 22:30:57 +09:00
if ( only _first && reply _founds _reply . length > 0 ) {
2015-02-26 05:16:24 +09:00
if ( q . children ( '.view-more-container-bottom' ) . length < 1 ) {
q . append ( '<div class="view-more-container-bottom" data-replies-after="' + qid + '"><a>' + window . sL . viewMoreInConvAfter + '</a></div>' ) ;
}
2013-08-19 22:30:57 +09:00
}
2015-02-26 05:16:24 +09:00
} ) ;
checkForHiddenConversationQueets ( q , qid ) ;
2013-08-19 22:30:57 +09:00
}
// helper function for the above recursive functions
2015-02-26 05:16:24 +09:00
function checkForHiddenConversationQueets ( q , qid ) {
2013-08-19 22:30:57 +09:00
// here we check if there are any remaining hidden queets in conversation, if there are, we put a "show full conversation"-link
2015-02-26 05:16:24 +09:00
if ( q . find ( '.hidden-conversation' ) . length > 0 ) {
if ( q . children ( '.queet' ) . find ( '.show-full-conversation' ) . length == 0 ) {
q . children ( '.queet' ) . find ( '.stream-item-footer' ) . append ( '<span class="show-full-conversation" data-stream-item-id="' + qid + '">' + window . sL . expandFullConversation + '</span>' ) ;
2014-11-24 21:47:45 +09:00
// if this is a single notice, we show conversation
if ( window . currentStream . substring ( 0 , 14 ) == 'statuses/show/' ) {
2015-02-26 05:16:24 +09:00
q . children ( '.queet' ) . find ( '.show-full-conversation' ) . trigger ( 'click' ) ;
2014-11-24 21:47:45 +09:00
}
2013-08-19 22:30:57 +09:00
}
}
else {
2015-02-26 05:16:24 +09:00
q . children ( '.queet' ) . find ( '.show-full-conversation' ) . remove ( ) ;
2013-08-19 22:30:57 +09:00
}
}
/ * ·
·
· Build stream items and add them to feed
·
· Also a function that has grown out of control ... Needs total makeover
·
· · · · · · · · · · · · · * /
2014-10-17 23:06:39 +09:00
function addToFeed ( feed , after , extraClasses , isReply ) {
2014-09-25 06:20:35 +09:00
// some streams, e.g. /statuses/show/1234.json is not enclosed in an array, make sure it is
if ( ! $ . isArray ( feed ) ) {
feed = [ feed ] ;
}
2014-05-28 03:40:51 +09:00
2013-08-19 22:30:57 +09:00
$ . each ( feed . reverse ( ) , function ( key , obj ) {
2014-11-24 21:47:45 +09:00
var extraClassesThisRun = extraClasses ;
// is this a temp-post-placeholder?
var isTempPost = false ;
if ( after ) {
if ( after . indexOf ( 'stream-item-temp-post' ) > - 1 ) {
isTempPost = true ;
}
}
2013-08-19 22:30:57 +09:00
2014-10-17 23:06:39 +09:00
// if this is the notifications feed, but not if it is a reply
if ( window . currentStream . substring ( 0 , 35 ) == 'qvitter/statuses/notifications.json'
&& ! isReply ) {
2014-09-25 06:20:35 +09:00
2014-11-14 08:48:02 +09:00
// don't show any notices with object_type "activity"
2014-11-24 21:47:45 +09:00
if ( typeof obj . notice != 'undefined' && obj . notice !== null && obj . notice . is _activity === true ) {
2014-11-14 08:48:02 +09:00
return true ;
2014-11-24 21:47:45 +09:00
}
2014-09-25 06:20:35 +09:00
// only if this notification isn't already in stream
2015-01-20 01:05:12 +09:00
if ( $ ( '#feed-body > .stream-item[data-quitter-id-in-stream="' + obj . id + '"]' ) . length == 0 ) {
2014-09-25 06:20:35 +09:00
obj . from _profile . description = obj . from _profile . description || '' ;
var notificationTime = parseTwitterDate ( obj . created _at ) ;
if ( obj . is _seen == '0' ) {
extraClassesThisRun = extraClassesThisRun + ' not-seen'
}
2014-11-24 21:47:45 +09:00
// external
var ostatusHtml = '' ;
if ( obj . from _profile . is _local === false ) {
2015-02-25 06:50:31 +09:00
ostatusHtml = '<a target="_blank" title="' + window . sL . goToOriginalNotice + '" class="ostatus-link" href="' + obj . from _profile . statusnet _profile _url + '"></a>' ;
2014-11-24 21:47:45 +09:00
}
2014-09-25 06:20:35 +09:00
if ( obj . ntype == 'like' ) {
var noticeTime = parseTwitterDate ( obj . notice . created _at ) ;
obj . notice = convertNewGNUSocialURItoURL ( obj . notice ) ;
2014-11-24 21:47:45 +09:00
var notificationHtml = '<div data-quitter-id-in-stream="' + obj . id + '" id="stream-item-n-' + obj . id + '" class="stream-item ' + extraClassesThisRun + ' notification like"><div class="queet"><div class="dogear"></div>' + ostatusHtml + '<div class="queet-content"><div class="stream-item-header"><a class="account-group" href="' + obj . from _profile . statusnet _profile _url + '"></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 + '<small class="created-at" data-created-at="' + obj . created _at + '" title="' + obj . created _at + '">' + notificationTime + '</small></div><div class="small-grey-notice"><a href="' + obj . notice . uri + '">' + noticeTime + '</a>: ' + $ . trim ( obj . notice . statusnet _html ) + '</div></div></div></div>' ;
2014-09-25 06:20:35 +09:00
}
else if ( obj . ntype == 'repeat' ) {
obj . notice = convertNewGNUSocialURItoURL ( obj . notice ) ;
var noticeTime = parseTwitterDate ( obj . notice . created _at ) ;
2014-11-24 21:47:45 +09:00
var notificationHtml = '<div data-quitter-id-in-stream="' + obj . id + '" id="stream-item-n-' + obj . id + '" class="stream-item ' + extraClassesThisRun + ' notification repeat"><div class="queet"><div class="queet-content"><div class="dogear"></div>' + ostatusHtml + '<div class="stream-item-header"><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 . xRepeatedYourQueet + '<small class="created-at" data-created-at="' + obj . created _at + '" title="' + obj . created _at + '">' + notificationTime + '</small></div><div class="small-grey-notice"><a href="' + obj . notice . uri + '">' + noticeTime + '</a>: ' + $ . trim ( obj . notice . statusnet _html ) + '</div></div></div></div>' ;
2014-09-25 06:20:35 +09:00
}
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' ) {
2014-11-24 21:47:45 +09:00
var notificationHtml = '<div data-quitter-id-in-stream="' + obj . id + '" id="stream-item-n-' + obj . id + '" class="stream-item ' + extraClassesThisRun + ' notification follow"><div class="queet"><div class="queet-content">' + ostatusHtml + '<div class="stream-item-header"><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 + '<small class="created-at" data-created-at="' + obj . created _at + '" title="' + obj . created _at + '">' + notificationTime + '</small></div></div></div></div>' ;
2014-09-25 06:20:35 +09:00
}
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>' ) ;
}
} ) ;
}
}
2013-08-19 22:30:57 +09:00
// if this is a user feed
2014-11-24 21:47:45 +09:00
else if ( ( window . currentStream . substring ( 0 , 21 ) == 'statuses/friends.json'
2013-08-20 22:26:25 +09:00
|| window . currentStream . substring ( 0 , 18 ) == 'statuses/followers'
|| window . currentStream . substring ( 0 , 28 ) == 'statusnet/groups/membership/'
2014-11-24 21:47:45 +09:00
|| window . currentStream . substring ( 0 , 24 ) == 'statusnet/groups/admins/' )
&& isTempPost === false // not if we're posting queet
) {
2013-08-20 22:26:25 +09:00
// only if not user is already in stream
if ( $ ( '#stream-item-' + obj . id ) . length == 0 ) {
obj . description = obj . description || '' ;
2014-11-24 21:47:45 +09:00
// external
var ostatusHtml = '' ;
if ( obj . is _local === false ) {
2015-02-25 06:50:31 +09:00
ostatusHtml = '<a target="_blank" title="' + window . sL . goToOriginalNotice + '" class="ostatus-link" href="' + obj . statusnet _profile _url + '"></a>' ;
2014-11-24 21:47:45 +09:00
}
2013-08-20 22:26:25 +09:00
// show user actions
var followingClass = '' ;
if ( obj . following ) {
followingClass = 'following' ;
}
var followButton = '' ;
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name != 'undefined' // if logged in
2013-08-20 22:26:25 +09:00
&& window . myUserID != obj . id ) { // not if this is me
if ( ! ( obj . statusnet _profile _url . indexOf ( '/twitter.com/' ) > - 1 && obj . following === false ) ) { // only unfollow twitter users
2015-01-27 01:35:44 +09:00
var followButton = '<div class="user-actions"><button data-follow-user-id="' + obj . id + '" data-follow-user="' + obj . statusnet _profile _url + '" type="button" class="qvitter-follow-button ' + followingClass + '"><span class="button-text follow-text"><i class="follow"></i>' + window . sL . userFollow + '</span><span class="button-text following-text">' + window . sL . userFollowing + '</span><span class="button-text unfollow-text">' + window . sL . userUnfollow + '</span></button></div>' ;
2013-08-20 22:26:25 +09:00
}
}
2013-11-29 20:49:54 +09:00
2014-11-24 21:47:45 +09:00
var userHtml = '<div id="stream-item-' + obj . id + '" class="stream-item user"><div class="queet">' + followButton + '<div class="queet-content"><div class="stream-item-header"><a class="account-group" href="' + obj . statusnet _profile _url + '"><img class="avatar" src="' + obj . profile _image _url _profile _size + '" /><strong class="name" data-user-id="' + obj . id + '">' + obj . name + '</strong> <span class="screen-name">@' + obj . screen _name + '</span></a>' + ostatusHtml + '</div><div class="queet-text">' + obj . description + '</div></div></div></div>' ;
2013-08-20 22:26:25 +09:00
if ( after ) {
$ ( '#' + after ) . after ( userHtml ) ;
}
else {
$ ( '#feed-body' ) . prepend ( userHtml ) ;
2013-08-19 22:30:57 +09:00
}
}
}
2013-08-20 22:26:25 +09:00
// if this is a list of groups
2014-11-24 21:47:45 +09:00
else if ( window . currentStream . substring ( 0 , 26 ) == 'statusnet/groups/list.json'
&& isTempPost === false // not if we're posting queet
) {
2013-08-19 22:30:57 +09:00
2013-08-20 22:26:25 +09:00
// only if not group is already in stream
if ( $ ( '#stream-item-' + obj . id ) . length == 0 ) {
obj . description = obj . description || '' ;
2014-05-14 03:52:55 +09:00
obj . stream _logo = obj . stream _logo || window . fullUrlToThisQvitterApp + 'img/default-avatar-profile.png' ;
2013-08-20 22:26:25 +09:00
// show group actions if logged in
var memberClass = '' ;
if ( obj . member ) {
memberClass = 'member' ;
}
var memberButton = '' ;
2014-05-16 11:07:30 +09:00
if ( typeof window . loggedIn . screen _name != 'undefined' ) {
2014-01-29 03:42:47 +09:00
console . log ( obj ) ;
2013-08-20 22:26:25 +09:00
var memberButton = '<div class="user-actions"><button data-group-id="' + obj . id + '" type="button" class="member-button ' + memberClass + '"><span class="button-text join-text"><i class="join"></i>' + window . sL . joinGroup + '</span><span class="button-text ismember-text">' + window . sL . isMemberOfGroup + '</span><span class="button-text leave-text">' + window . sL . leaveGroup + '</span></button></div>' ;
}
2014-01-29 03:42:47 +09:00
var groupAvatar = obj . stream _logo ;
if ( obj . homepage _logo != null ) {
groupAvatar = obj . homepage _logo ;
}
var groupHtml = '<div id="stream-item-' + obj . id + '" class="stream-item user"><div class="queet">' + memberButton + '<div class="queet-content"><div class="stream-item-header"><a class="account-group" href="' + obj . url + '"><img class="avatar" src="' + groupAvatar + '" /><strong class="name" data-group-id="' + obj . id + '">' + obj . fullname + '</strong> <span class="screen-name">!' + obj . nickname + '</span></a></div><div class="queet-text">' + obj . description + '</div></div></div></div>' ;
2013-08-20 22:26:25 +09:00
if ( after ) {
$ ( '#' + after ) . after ( groupHtml ) ;
}
else {
$ ( '#feed-body' ) . prepend ( groupHtml ) ;
}
}
2013-08-19 22:30:57 +09:00
}
// if this is a retweet
else if ( typeof obj . retweeted _status != 'undefined' ) {
2014-11-24 21:47:45 +09:00
// don't show any notices with object_type "activity"
if ( typeof obj . retweeted _status . is _activity != 'undefined' && obj . retweeted _status . is _activity === true ) {
return true ;
}
2013-08-19 22:30:57 +09:00
// retweeted object already exist in feed
if ( $ ( '#q-' + obj . retweeted _status . id ) . length > 0 ) {
// only if not already shown and not mine
if ( $ ( '#requeet-' + obj . id ) . length == 0 && obj . user . statusnet _profile _url != $ ( '#user-profile-link' ) . children ( 'a' ) . attr ( 'href' ) ) {
2014-11-24 21:47:45 +09:00
// if requeeted before
if ( $ ( '#q-' + obj . retweeted _status . id + ' > .context' ) . find ( '.requeet-text' ) . length > 0 ) {
2013-08-19 22:30:57 +09:00
// if users rt not already added
2014-11-24 21:47:45 +09:00
if ( $ ( '#q-' + obj . retweeted _status . id + ' > .context' ) . find ( '.requeet-text' ) . find ( 'a[data-user-id="' + obj . user . id + '"]' ) . length == 0 ) {
$ ( '#q-' + obj . retweeted _status . id + ' > .context' ) . find ( '.requeet-text' ) . children ( 'a' ) . last ( ) . after ( '<a data-user-id="' + obj . user . id + '" href="' + obj . user . statusnet _profile _url + '"> <b>' + obj . user . name + '</b></a>' ) ;
2013-08-19 22:30:57 +09:00
}
}
2014-11-24 21:47:45 +09:00
// if no context requeets
2013-08-19 22:30:57 +09:00
else {
2014-11-24 21:47:45 +09:00
var requeetHtml = '<a data-user-id="' + obj . user . id + '" href="' + obj . user . statusnet _profile _url + '"> <b>' + obj . user . name + '</b></a>' ;
$ ( '#q-' + obj . retweeted _status . id ) . prepend ( '<div class="context" id="requeet-' + obj . id + '"><span class="with-icn"><i class="badge-requeeted"></i><span class="requeet-text"> ' + window . sL . requeetedBy . replace ( '{requeeted-by}' , requeetHtml ) + '</span></span></div>' ) ;
2013-08-19 22:30:57 +09:00
}
}
}
2013-08-20 00:46:56 +09:00
// retweeted object don't exist in feed
else {
2013-08-19 22:30:57 +09:00
2014-09-25 06:20:35 +09:00
var queetHtml = buildQueetHtml ( obj . retweeted _status , obj . id , extraClassesThisRun , obj ) ;
2013-08-19 22:30:57 +09:00
if ( after ) {
$ ( '#' + after ) . after ( queetHtml ) ;
}
else {
$ ( '#feed-body' ) . prepend ( queetHtml ) ;
}
}
}
// ordinary tweet
else {
2014-11-24 21:47:45 +09:00
// don't show any notices with object_type "activity"
if ( typeof obj . is _activity != 'undefined' && obj . is _activity === true ) {
2014-11-14 08:48:02 +09:00
return true ;
2014-11-24 21:47:45 +09:00
}
2013-08-19 22:30:57 +09:00
// only if not already exist
if ( $ ( '#q-' + obj . id ) . length == 0 ) {
// activity get special design
if ( obj . source == 'activity' ) {
var queetTime = parseTwitterDate ( obj . created _at ) ;
2014-11-24 21:47:45 +09:00
var queetHtml = '<div id="stream-item-' + obj . id + '" class="stream-item activity ' + extraClassesThisRun + '" data-quitter-id="' + obj . id + '" data-conversation-id="' + obj . statusnet _conversation _id + '" data-quitter-id-in-stream="' + obj . id + '"><div class="queet" id="q-' + obj . id + '"><div class="queet-content"><div class="stream-item-header"><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></div></div>' ;
2013-08-19 22:30:57 +09:00
// detect rtl
queetHtml = detectRTL ( queetHtml ) ;
if ( after ) {
$ ( '#' + after ) . after ( queetHtml ) ;
}
else {
$ ( '#feed-body' ) . prepend ( queetHtml ) ;
}
}
else {
// if this is my queet, remove any temp-queets
if ( typeof obj . user != 'undefined' ) {
if ( obj . user . screen _name == $ ( '#user-screen-name' ) . html ( ) ) {
if ( $ ( '.temp-post' ) . length > 0 ) {
$ ( '.temp-post' ) . each ( function ( ) {
// remove temp duplicate
$ ( this ) . css ( 'display' , 'none' ) ;
// we do this so this queet gets added after correct temp-queet in expanded conversations
if ( $ ( this ) . find ( '.queet-text' ) . text ( ) == obj . text ) {
after = $ ( this ) . attr ( 'id' ) ;
}
// but don't hide my new queet
extraClassesThisRun = 'visible' ;
} ) ;
}
}
}
2014-09-25 06:20:35 +09:00
var queetHtml = buildQueetHtml ( obj , obj . id , extraClassesThisRun ) ;
2013-08-19 22:30:57 +09:00
if ( after ) {
if ( $ ( '#' + after ) . hasClass ( 'conversation' ) ) { // if this is a reply, give stream item some conversation formatting
if ( $ ( '#conversation-q-' + obj . id ) . length == 0 ) { // only if it's not already there
$ ( '#' + after ) . after ( queetHtml . replace ( 'id="stream-item' , 'id="conversation-stream-item' ) . replace ( 'class="stream-item' , 'class="stream-item conversation' ) . replace ( 'id="q' , 'id="conversation-q' ) ) ;
$ ( '#' + after ) . remove ( ) ;
}
}
else {
$ ( '#' + after ) . after ( queetHtml ) ;
}
}
else {
2014-09-25 06:20:35 +09:00
$ ( '#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 ) ) ;
}
2013-08-19 22:30:57 +09:00
}
2014-11-24 21:47:45 +09:00
// fadeout any posting-popups
setTimeout ( function ( ) {
$ ( '#popup-sending' ) . fadeOut ( 1000 , function ( ) {
$ ( '#popup-sending' ) . remove ( ) ;
} ) ;
} , 100 ) ;
2013-08-19 22:30:57 +09:00
}
}
}
convertAttachmentMoreHref ( ) ;
} ) ;
$ ( '.stream-selection' ) . removeAttr ( 'data-current-user-stream-name' ) ; // don't remeber user feeds
}
/ * ·
·
2014-09-25 06:20:35 +09:00
· Build HTML for a queet from an object
2013-08-19 22:30:57 +09:00
·
2014-09-25 06:20:35 +09:00
· @ param obj : a queet object
· @ param requeeted _by : if this is a requeet
2013-08-19 22:30:57 +09:00
·
· · · · · · · · · · · · · * /
2015-02-26 05:16:24 +09:00
function buildQueetHtml ( obj , idInStream , extraClassesThisRun , requeeted _by , isConversation ) {
2014-09-25 06:20:35 +09:00
2015-02-26 07:46:32 +09:00
// if we have the full html for a truncated notice cached in localstorage, we use that
localStorageObjectCache _GET ( 'fullQueetHtml' , obj . id , function ( data ) {
if ( data ) {
obj . statusnet _html = data ;
}
} ) ;
2014-09-25 06:20:35 +09:00
// 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 ;
2015-02-26 05:16:24 +09:00
}
// conversations has some slightly different id's
var idPrepend = '' ;
if ( typeof isConversation != 'undefined' && isConversation === true ) {
var idPrepend = 'conversation-' ;
}
2014-09-25 06:20:35 +09:00
2015-01-27 09:57:08 +09:00
// is this mine?
var isThisMine = 'not-mine' ;
2014-09-25 06:20:35 +09:00
if ( obj . user . id == window . myUserID ) {
2015-01-27 09:57:08 +09:00
var isThisMine = 'is-mine' ;
2014-09-25 06:20:35 +09:00
}
2015-02-26 05:16:24 +09:00
// requeeted by me?
var requeetedByMe = '' ;
if ( obj . repeated _id ) {
requeetedByMe = ' data-requeeted-by-me-id="' + obj . repeated _id + '" ' ;
}
2015-01-27 09:57:08 +09:00
// requeet html
var requeetedClass = '' ;
if ( obj . repeated ) {
2014-11-24 21:47:45 +09:00
var requeetHtml = '<li class="action-rt-container"><a class="with-icn done"><span class="icon sm-rt" title="' + window . sL . requeetedVerb + '"></span></a></li>' ;
2014-09-25 06:20:35 +09:00
var requeetedClass = 'requeeted' ;
}
else {
2015-01-27 09:57:08 +09:00
var requeetHtml = '<li class="action-rt-container"><a class="with-icn"><span class="icon sm-rt ' + isThisMine + '" title="' + window . sL . requeetVerb + '"></span></a></li>' ;
2014-09-25 06:20:35 +09:00
}
// favorite html
var favoritedClass = '' ;
if ( obj . favorited ) {
2014-11-24 21:47:45 +09:00
var favoriteHtml = '<a class="with-icn done"><span class="icon sm-fav" title="' + window . sL . favoritedVerb + '"></span></a>' ;
2014-09-25 06:20:35 +09:00
favoritedClass = 'favorited' ;
}
else {
2014-11-24 21:47:45 +09:00
var favoriteHtml = '<a class="with-icn"><span class="icon sm-fav" title="' + window . sL . favoriteVerb + '"></span></a>' ;
2014-09-25 06:20:35 +09:00
}
// actions only for logged in users
var queetActions = '' ;
if ( typeof window . loggedIn . screen _name != 'undefined' ) {
2015-01-27 09:57:08 +09:00
queetActions = '<ul class="queet-actions"><li class="action-reply-container"><a class="with-icn"><span class="icon sm-reply" title="' + window . sL . replyVerb + '"></span></a></li>' + requeetHtml + '<li class="action-fav-container">' + favoriteHtml + '</li><li class="action-ellipsis-container"><a class="with-icn"><span class="icon sm-ellipsis" title="' + window . sL . ellipsisMore + '"></span></a></li></ul>' ;
2014-09-25 06:20:35 +09:00
}
// reply-to html
var reply _to _html = '' ;
2014-11-24 21:47:45 +09:00
if ( obj . in _reply _to _screen _name !== null && obj . in _reply _to _profileurl !== null && obj . in _reply _to _screen _name != obj . user . screen _name ) {
reply _to _html = '<span class="reply-to"><a class="h-card mention" href="' + obj . in _reply _to _profileurl + '">@' + obj . in _reply _to _screen _name + '</a></span> ' ;
2014-09-25 06:20:35 +09:00
}
// in-groups html
var in _groups _html = '' ;
2014-11-25 00:10:59 +09:00
if ( typeof obj . statusnet _in _groups != 'undefined' && obj . statusnet _in _groups !== false && typeof obj . statusnet _in _groups === 'object' ) {
2014-11-24 21:47:45 +09:00
$ . each ( obj . statusnet _in _groups , function ( ) {
in _groups _html = '<span class="in-groups"><a class="h-card group" href="' + obj . statusnet _in _groups . url + '">!' + obj . statusnet _in _groups . nickname + '</a></span>' ;
} ) ;
2014-09-25 06:20:35 +09:00
}
// image attachment thumbnails
var attachment _html = '' ;
if ( typeof obj . attachments != "undefined" ) {
2014-11-24 21:47:45 +09:00
obj . attachments . reverse ( ) ; // last on top
2014-09-25 06:20:35 +09:00
$ . each ( obj . attachments , function ( ) {
2015-01-24 00:28:41 +09:00
if ( this . id != null ) {
var bigThumbW = 1000 ;
var bigThumbH = 3000 ;
if ( bigThumbW > window . siteMaxThumbnailSize ) {
bigThumbW = window . siteMaxThumbnailSize ;
}
if ( bigThumbH > window . siteMaxThumbnailSize ) {
bigThumbH = window . siteMaxThumbnailSize ;
2015-01-26 03:05:09 +09:00
}
// if thumb_url is set, we use that
if ( typeof this . thumb _url != 'undefined' ) {
var thumb _url = this . thumb _url ;
}
else {
var thumb _url = window . siteAttachmentURLBase + this . id + '/thumbnail?w=200&h=200' ;
}
2015-02-25 04:44:48 +09:00
attachment _html = attachment _html + '<a href="' + this . url + '"><img data-mime-type="' + this . mimetype + '" data-big-thumbnail="' + window . siteAttachmentURLBase + this . id + '/thumbnail?w=' + bigThumbW + '&h=' + bigThumbH + '" src="' + thumb _url + '"/></a>' ;
2014-09-25 06:20:35 +09:00
}
} ) ;
}
if ( attachment _html . length > 0 ) {
attachment _html = '<div class="attachments">' + attachment _html + '</div>' ;
}
// requeets
var requeetHtml = '' ;
2015-02-26 05:16:24 +09:00
if ( typeof requeeted _by != 'undefined' && requeeted _by !== false ) {
2014-11-24 21:47:45 +09:00
var requeetedByHtml = '<a data-user-id="' + requeeted _by . user . id + '" href="' + requeeted _by . user . statusnet _profile _url + '"> <b>' + requeeted _by . user . name + '</b></a>' ;
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 . replace ( '{requeeted-by}' , requeetedByHtml ) + '</span></span></div>' ;
2014-09-25 06:20:35 +09:00
}
2014-11-25 00:10:59 +09:00
2014-11-24 21:47:45 +09:00
obj = convertNewGNUSocialURItoURL ( obj ) ;
2014-09-25 06:20:35 +09:00
2014-11-24 21:47:45 +09:00
// external
var ostatusHtml = '' ;
if ( obj . is _local === false ) {
2015-02-25 06:50:31 +09:00
ostatusHtml = '<a target="_blank" title="' + window . sL . goToOriginalNotice + '" class="ostatus-link" href="' + obj . external _url + '"></a>' ;
2014-11-24 21:47:45 +09:00
}
2014-09-25 06:20:35 +09:00
var queetTime = parseTwitterDate ( obj . created _at ) ;
var queetHtml = ' < div \
2015-02-26 05:16:24 +09:00
id = "' + idPrepend + 'stream-item-' + obj.id + '" \
2014-09-25 06:20:35 +09:00
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 + '" \
2015-02-26 05:16:24 +09:00
data - in - reply - to - status - id = "' + obj.in_reply_to_status_id + '" \
' + requeetedByMe + ' > \
< div class = "queet" id = "' + idPrepend + 'q-' + obj.id + '" > \
2014-11-24 21:47:45 +09:00
' + requeetHtml + ' \
2014-09-25 06:20:35 +09:00
' + attachment_html + ' \
2014-11-24 21:47:45 +09:00
' + ostatusHtml + ' \
2014-09-25 06:20:35 +09:00
< 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 + ' < / s t r o n g > \
< span class = "screen-name" > @ ' + obj.user.screen_name + ' < / s p a n > \
< / a > \
< i class = "addressees" > ' + reply_to_html + in_groups_html + ' < / i > \
< small class = "created-at" data - created - at = "' + obj.created_at + '" > \
2014-11-24 21:47:45 +09:00
< a href = "' + window.siteInstanceURL + 'notice/' + obj.id + '" > ' + queetTime + ' < / a > \
2014-09-25 06:20:35 +09:00
< / s m a l l > \
< / d i v > \
< div class = "queet-text" > ' + $.trim(obj.statusnet_html) + ' < / d i v > \
< div class = "stream-item-footer" > \
' + queetActions + ' \
< / d i v > \
< / d i v > \
< / d i v > \
< / d i v > ' ;
// detect rtl
queetHtml = detectRTL ( queetHtml ) ;
return queetHtml ;
}